antlr / grammars-v4

Grammars written for ANTLR v4; expectation that the grammars are free of actions.
MIT License
10.11k stars 3.69k forks source link

chsharp preprocess crashes will null pointer in the constructor - because of the {{}} #1191

Open yonatanLehman opened 6 years ago

yonatanLehman commented 6 years ago

The CSharpPreprocessirParser.g4 contains the lines

@parser::members
{Stack<Boolean> conditions = new Stack<Boolean>() {{ conditions.push(true); }};
public HashSet<String> ConditionalSymbols = new HashSet<String>() {{ ConditionalSymbols.add("DEBUG"); }};

As I understand it this is added to the preprocess parser code. The problem is when I do

CommonTokenStream tokens1 = new CommonTokenStream(lexer);
CSharpPreprocessorParser preprocessparser = new CSharpPreprocessorParser(tokens1);

It crashes in the constructor of CSharpPreprocessorParser. The reason being that the code in the double braches is accessing a null pointer (conditions and ConditionalSymbols)

I patched around this by doing the initialization in functions added from the constructor like so:

Stack<Boolean> conditions = new Stack<Boolean>(); /* {{ conditions.push(true);  }} */
private void setupConditions() {
    conditions.push(true);
}
public HashSet<String> ConditionalSymbols = new HashSet<String>() /* {{ ConditionalSymbols.add("DEBUG"); }}*/;
private void setupConditionalSymbols() {
    ConditionalSymbols.add("DEBUG");
}

public CSharpPreprocessorParser(TokenStream input) {
    super(input);
    conditions = new Stack<Boolean>();
    setupConditions();
    setupConditionalSymbols();
    _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}

Am I do something wrong or is this a problem? I'm using InteliJ 2017.2 with Java JRE 1.8.

KvanTTT commented 6 years ago

What C# code do you try to parse?

yonatanLehman commented 6 years ago

It's some internal code. BTW = a simpler way to solve the problem is to replace the code as follows (I can do this in the .g4)

Stack<Boolean> conditions = new Stack<Boolean>() {{ push(true);  }}
HashSet<String> ConditionalSymbols = new HashSet<String>() {{ add("DEBUG"); }}

Looking at examples of the use of {{ }} this seems to be the correct way to do it (i.e. call the method directly and not via the global which has not yet been assigned).