Antlr4中的条件词法分析器规则

时间:2017-07-25 21:38:42

标签: antlr4

鉴于这个语法:

grammar ColonTest;

main        : statement* EOF;
statement   : NUM_LITERAL expression SEMICOLON;
expression  : primary (MULT_OP primary)*;
primary     : WORD+;

NUM_LITERAL : [0-9]+;
SEMICOLON   : ';';
MULT_OP     : '*' | '/'; // | ':';
WORD        : ('a'..'z' | 'A'..'Z')+;
WS          : [ \t\r\n]+ -> skip;
COLON       : ':' -> skip;

和这个输入:

1 : statement;
2 : splitted statement
  : into two lines;
3 : a * b / c;
4 : a * b : c;

在第4行中,由于“COLON”词法分析器规则,跳过第二个冒号。但我需要这个冒号,因为它是语言的一部分(假设它也应该是MULT_OP关键字的一部分)。怎么做到这一点?

编辑1:

删除COLON : ':' -> skip;并插入:

statement   : NUM_LITERAL ':' expression (':' expression)* SEMICOLON;

树看起来像这样:

wrong tree

所需的树应如下所示:

desired tree

编辑2:

这个怎么样?一些隐式令牌被定义 - 但现在它可以工作。

grammar MultiLine;

main        : statement* EOF;
statement   : NUM_LITERAL ':' expression SEMICOLON;
expression  : primary ((MULT_OP|':') primary)*;
primary     : WORD+;

NUM_LITERAL : [0-9]+;
SEMICOLON   : ';';
MULT_OP     : '*' | '/';
WORD        : ('a'..'z' | 'A'..'Z')+;
WS2         : [\r\n]+ [ \t]+ ':' -> skip; // removes all not needed colons
WS          : [ \t\r\n]+ -> skip;

我可以用其他方式改进代码吗?

2 个答案:

答案 0 :(得分:0)

:等标记可能不会被跳过。然后,将您的statement规则更改为:

statement : NUM_LITERAL expression (':' expression)* SEMICOLON;

答案 1 :(得分:0)

您需要做出决定:要么保留冒号,要么跳过它。你不能同时拥有两个相反的行动。但问题是为什么你想首先跳过冒号?即使您在初始数字之后不需要它,也不会在解析树中使用它。当你以后走完你的解析树时,你总是可以忽略那个令牌。