Beginning with this grammar: https://stackoverflow.com/a/166268/2126252/ I would understand a simple grammar that accepts and evaluates a simple language as follows:
{ if a==c { a if a==b { b } else { c } } }
So, if a==c , it executes a and evaluates if a==b , if it is true, it executes b otherwise c . Really simple.
The parser grammar and tree grammar are as follows:
TreeEvaluator.g (Combined Grammar for AST)
grammar TreeEvaluator; options { output = AST; } tokens { CONDBLOCK; CODEBLOCK; DEFAULT; } compilationUnit : block EOF -> block; condition : cif elif* celse? -> ^(IF cif elif* celse?); cif : IF expr block -> ^(CONDBLOCK expr block); elif : ELIF expr block -> ^(CONDBLOCK expr block); celse : ELSE block -> ^(DEFAULT block); expr : ID EQ^ ID; block : LCUR instruction* RCUR -> ^(CODEBLOCK instruction*); instruction : ID | condition; IF : 'if'; ELIF: 'elif'; ELSE: 'else'; LCUR: '{'; RCUR: '}'; EQ : '=='; ID : ('a'..'z'|'A'..'Z')+; WS : (' '|'\t'|'\f'|'\r'|'\n')+ {skip();};
AstTreeEvaluatorParser.g (tree parser)
tree grammar AstTreeEvaluatorParser; options { output = AST; tokenVocab = TreeEvaluator; ASTLabelType = CommonTree; } @members { private static final class Evaluation { boolean matched = false; boolean done = false; } private java.util.HashMap<String, Integer> vars = new java.util.HashMap<String, Integer>(); public void addVar(String name, int value){ vars.put(name, value); } } compilationUnit : block+; block : ^(CODEBLOCK instruction*); instruction : ifStat | ID; ifStat @init { Evaluation eval = new Evaluation(); } : ^(IF condition[eval]* defcond[eval]?) ; condition [Evaluation eval] : ^(CONDBLOCK exp {if ($exp.value) eval.matched = true;} evalblock[eval]) ; defcond [Evaluation eval] : ^(DEFAULT {eval.matched = true;} evalblock[eval])
The problem is that the DFA generated to predict the evalblock rule, this DFA has a SpecialStateTransition() method that refers to the eval parameter (as specified in the rule), but this parameter is not visible in the generated Java class.
I do not understand why, and if there is a way to avoid this problem.
source share