0

I am working on creating a regex parser for a class project, and I've run into a problem I can't figure out how to fix. Whenever it encounters a parenthesized group, it is supposed to add a placeholder to the groups ArrayList where a group can then be captured from a String. The problem is that it throws a NullPointerException whenever it attempts to add to this ArrayList. Here is the Segment constructor, where this occurs:

public Segment(String value, boolean capture) throws ParseException {
    values = new ArrayList<>();
    parse(value);
    minimum = 1;
    maximum = 1;
    matchNot = false;
    captureGroup = capture;
    if (capture) {
        RegexGUI.input.groups.add(""); //error occurs on this line
    }
}

Note that RegexGUI.input refers to the relevant instance of Regex, which the constructor for is here:

public Regex(String value) throws ParseException {
    this.value = value;
    segments = new ArrayList<>();
    groups = new ArrayList<>();
    anchorStart = false;
    anchorEnd = false;
    tokenize(value, true, false);
}

As you can see, groups is clearly initialized in the constructor. Also, the Segment constructor is only called in the tokenize() method in the Regex class, and that method is only called by the Regex constructor, so there is no possible way I could see that the problem would simply be that groups has not been initialized.

The entire stacktrace is here:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at regexparser.Segment.<init>(Segment.java:39)
    at regexparser.Regex.tokenize(Regex.java:57)
    at regexparser.Regex.<init>(Regex.java:27)
    at regexparser.RegexGUI.actionPerformed(RegexGUI.java:80)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6535)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6300)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4891)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4713)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

This is the line of code in tokenize() mentioned in the stacktrace:

segments.add(new Segment(value.substring(0, value.indexOf(")")+1), true));

This is the line of code in actionPerformed() mentioned in the stacktrace:

input = new Regex(regexInput.getText());

I don't know if this is necessary to post or not, but here are my instance and class variables for each class:

Regex class:

String value;
ArrayList<Segment> segments;
ArrayList<String> groups;
boolean anchorStart;
boolean anchorEnd;

Segment class:

ArrayList<String> values;
int minimum;
int maximum;
boolean matchNot;
boolean captureGroup;

final static String UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final static String LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
final static String DIGITS = "0123456789";
final static String[] SETS = {UPPERCASE, LOWERCASE, DIGITS};
final static String WORD = UPPERCASE + LOWERCASE + DIGITS + "_";

final static String WHITESPACE = " \r\n\t\f";

RegexGUI class:

Container contentPane;
JPanel panel;
GridBagLayout gridbag;
GridBagConstraints c;
JLabel regexPrompt, stringPrompt, result;
JTextField regexInput;
JTextArea stringInput;
JButton test;
static Regex input;
boolean match;

I would appreciate any help you guys can give me. I've tried looking up what might be causing this exception, but the only answer I can find is that groups is not initialized. I've searched through my code to try to figure out any way that the Segment constructor may be called before groups is initialized, but I can't see any way that would be possible.

Bethany Louise
  • 636
  • 7
  • 13
  • @3kings I've already read that post. I still couldn't figure out what's going wrong. – Bethany Louise May 04 '16 at 21:31
  • Then read it again :). You need to find out what is `null` and debug why. – Tunaki May 04 '16 at 21:32
  • "RegexGUI.input.groups.add(""); " Where is RegexGui.input instantiated? if it is, where is its groups field instantiated? – FredK May 04 '16 at 21:32
  • @Tunaki: `groups` has been initialized; it shouldn't be null. – Bethany Louise May 04 '16 at 21:33
  • @FredK: As I mentioned, it is instantiated here: `input = new Regex(regexInput.getText());`. This line is in `RegexGUI`. – Bethany Louise May 04 '16 at 21:34
  • @BethanyLouise Debug and you will know for sure what is `null`. – Tunaki May 04 '16 at 21:35
  • Try with the debugger: place a checkpoint some line before the line where you get the NPE, then click "Dubug application" (or something similar, depending on which IDE you're using) and then proceed step by step looking for variable instantiations (with F5 or F6, again, it depends on the IDE the correct keymap). – Lorenzo Barbagli May 04 '16 at 21:36

1 Answers1

5

Your code is a catch 22

This line:

input = new Regex(regexInput.getText());

Will create the Regex object, then assign it.

However, whilst creating the Regex instance you try to reference the Regex.input instance before its actually finished, so it hasnt yet actually been assigned and is in fact still null.

A reasonably quick fix would be to call the tokenize method after constructing the object. So remove the tokenize call from the constructor and then run something like:

input = new Regex(regexInput.getText());
input.tokenize(...);
cowls
  • 22,178
  • 6
  • 45
  • 76
  • Thank you so much! Calling `tokenize()` outside of the constructor works just fine. The only problem now is that it's throwing a StackOverflowError instead, but that's coming from elsewhere in the code, so I'll see if I can troubleshoot that myself. – Bethany Louise May 04 '16 at 21:38
  • Glad to hear, happy debugging with the next error! – cowls May 04 '16 at 21:43
  • If tokenizing is an essential part of constructing the regex, prefer to leave it in the constructor! Instead, do not add the empty string to groups within the Segment ctor, but within tokenize (`if(...) this.groups.add("")`) @cowls Still you had a good eye for -- +1... – Aconcagua May 04 '16 at 22:19