ANTLR:如何调试错误识别的令牌

ANTLR: how to debug a misidentified token

我正在尝试在 Antlr4 中为一个简单的模板引擎实现一个语法。该引擎由 3 个不同的子句组成:

IF ANSWERED ( variable )

END IF

Variable

变量可以是任何大写或小写字母,包括空格。 IF ANSWEREDEND IF 都是大写。

到目前为止,我已经编写了以下 grammar/lexer 规则,但我的问题是 IF ANSWERED 一直被识别为变量,而不是 2 个标记 IFANSWERED.

grammar program;

/**grammar */
command: (ifStart | ifEnd | VARIABLE ) EOF;

ifStart: IF ANSWERED '(' VARIABLE ')';

ifEnd: 'END IF';

/** lexer */

IF: 'IF';
ANSWERED: 'ANSWERED';

TEXT: (LOWERCASE | UPPERCASE | NUMBER) ;
VARIABLE: (TEXT | [ \t\r\n])+;

fragment LOWERCASE: [a-z];
fragment UPPERCASE: [A-Z];
fragment NUMBER: [0-9];

如果我尝试解析 IF ANSWERED ( FirstName ),我会得到以下输出:

[@0,0:10='IF ANSWERED',**<VARIABLE>**,1:0]
[@1,11:11='(',<'('>,1:11]
[@2,12:25='Execution date',<VARIABLE>,1:12]
[@3,26:26=')',<')'>,1:26]
[@4,27:26='<EOF>',<EOF>,1:27]
line 1:0 mismatched input 'IF ANSWERED' expecting 'IF'

我读到 Antlr4 是贪婪的,并试图匹配最大可能的标记,但我不明白什么是正确的方法,或者如何思考问题以找到解决方案。

正确:ANTLR 的词法分析器是贪婪的,并尝试尽可能多地消费。这就是为什么 IF ANSWERED 被标记为 TEXT 标记而不是 2 个单独的关键字。您需要更改 TEXT 使其不匹配空格。

像这样的东西可以让你开始:

parse
 : command* EOF
 ;

command
 : (ifStatement | variable)+
 ;

ifStatement
 : IF ANSWERED '(' variable ')' command* END IF
 ;

variable
 : TEXT
 ;

IF       : 'IF';
END      : 'END';
ANSWERED : 'ANSWERED';
TEXT     : [a-zA-Z0-9]+;
SPACES   : [ \t\r\n]+ -> skip;