How can I determine which alternative node was chosen in ANTLR
Asked Answered
S

1

7

Suppose I have the following:

variableDeclaration: Identifier COLON Type SEMICOLON;
Type: T_INTEGER | T_CHAR | T_STRING | T_DOUBLE | T_BOOLEAN;

where those T_ names are just defined as "integer", "char" etc.

Now suppose I'm in the exitVariableDeclaration method of a test program called LittleLanguage. I can refer to LittleLanguageLexer.T_INTEGER (etc.) but I can't see how determine which of these types was found through the context.

I had thought it would be context.Type().getSymbol().getType() but that doesn't return the right value. I know that I COULD use context.Type().getText() but I really don't want to be doing string comparisons.

What am I missing?

Thanks

Secluded answered 18/10, 2015 at 13:57 Comment(0)
G
11

You are loosing information in the lexer by combining the tokens prematurely. Better to combine in a parser rule:

variableDeclaration: Identifier COLON type SEMICOLON;
type: T_INTEGER | T_CHAR | T_STRING | T_DOUBLE | T_BOOLEAN;

Now, type is a TerminalNode whose underlying token instance has a unique type:

variableDeclarationContext ctx = .... ;
TerminalNode typeNode = (TerminalNode) ctx.type().getChild(0);

switch(typeNode.getSymbol().getType()) {
  case YourLexer.T_INTEGER:
     ...
Gambell answered 19/10, 2015 at 6:16 Comment(7)
First of all, thanks for responding. Secondly, shoot me now --- while you described exactly why it was broken, the actual "bug" was that I wrote Type instead of type, forgetting that the first character determines whether the rule is handled by lexer or parser! I never intended it to be a lexer rule.Secluded
Having said that, I'm still having a problem. There is no "getSymbol()" method available. "type" shows up as a typeContext, not as a terminal node. There's no getSymbol() available at that point. I can type things like context.type().T_INTEGER().getSymbol() but then I have to know it's already an integer.Secluded
By the way, I do know that I can write things like "if context.type().TINTEGER() != null" but that seems like a very sloppy approach. There must be a way to ask the context for the actual tokenSecluded
Code updated: within any chosen instance of a context of type variableDeclarationContext, type() returns a TerminalNode, which wraps a single token that is the singular token instance that matched in the type rule. The token cannot be null.Gambell
In my VariableDeclarationContext , that type() method returns a value of type "TypeContext, not "TerminalNode". In other words, ctx.type() is NOT a TerminalNode on my systemSecluded
My bad -- fixed. The type context will have a single child node.Gambell
Thanks -- and I understand exactly why that works. Still not familiar enough with ANTRL to realize that TerminalNode extends ParseTree otherwise I probably would have gotten there eventually :-) Really appreciate the feedback.Secluded

© 2022 - 2024 — McMap. All rights reserved.