ANTLR Lexer规则似乎只是解析器规则的一部分,而不是另一个Lexer规则的一部分
如果我有以下语法来解析由空格分隔的整数列表:ANTLR Lexer规则似乎只是解析器规则的一部分,而不是另一个Lexer规则的一部分,antlr,antlr4,Antlr,Antlr4,如果我有以下语法来解析由空格分隔的整数列表: grammar TEST; test : expression* EOF ; expression : integerLiteral ; integerLiteral : INTLITERAL ; PLUS: '+'; MINUS: '-'; DIGIT: '0'..'9'; DIGITS: DIGIT+; INTLITERAL: (PLUS|MINUS)? DIGITS; WS: [ \t
grammar TEST;
test
: expression* EOF
;
expression
: integerLiteral
;
integerLiteral
: INTLITERAL
;
PLUS: '+';
MINUS: '-';
DIGIT: '0'..'9';
DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
WS: [ \t\r\n] -> skip;
它不起作用!如果我通过100,我会得到:
line 1:0 extraneous input '100' expecting {<EOF>, INTLITERAL}
现在它似乎工作得很好
我觉得如果我能够理解为什么会这样,我就会开始理解我正在经历的一些特质。lexer以以下方式创建令牌: 尝试为单个标记匹配尽可能多的字符 如果两个令牌匹配相同的字符,则让第一个定义的令牌获胜 根据以上2条规则中的信息,您将看到您的规则:
DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
这就是问题所在。对于输入100,将创建一个DIGITS标记:规则2在此适用:两个规则都匹配100,但由于DIGITS是在INTLITERAL之前定义的,因此将创建DIGITS标记
解决方案1
将INTLITERAL移到数字上方:
但现在请注意,DIGIT和DIGITS本身永远不会成为标记,因为INTLITERAL总是首先匹配的。在本例中,您可以生成这两个规则片段,然后将它们放置在何处并不重要,因为片段规则只在其他lexer规则中使用,而不在解析器规则中使用
解决方案2
制作数字和数字片段
fragment DIGIT: '0'..'9';
fragment DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
解决方案3
或者更好的方法是,不要将运算符粘附在INTLITERAL上,而是在一元表达式中匹配它:
expression
: (MINUS | PLUS) expression
| expression (MINUS | PLUS) expression
| integerLiteral
;
integerLiteral
: INTLITERAL
;
PLUS: '+';
MINUS: '-';
fragment DIGIT: '0'..'9';
INTLITERAL: DIGIT+;
lexer以以下方式创建令牌: 尝试为单个标记匹配尽可能多的字符 如果两个令牌匹配相同的字符,则让第一个定义的令牌获胜 根据以上2条规则中的信息,您将看到您的规则:
DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
这就是问题所在。对于输入100,将创建一个DIGITS标记:规则2在此适用:两个规则都匹配100,但由于DIGITS是在INTLITERAL之前定义的,因此将创建DIGITS标记
解决方案1
将INTLITERAL移到数字上方:
但现在请注意,DIGIT和DIGITS本身永远不会成为标记,因为INTLITERAL总是首先匹配的。在本例中,您可以生成这两个规则片段,然后将它们放置在何处并不重要,因为片段规则只在其他lexer规则中使用,而不在解析器规则中使用
解决方案2
制作数字和数字片段
fragment DIGIT: '0'..'9';
fragment DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;
解决方案3
或者更好的方法是,不要将运算符粘附在INTLITERAL上,而是在一元表达式中匹配它:
expression
: (MINUS | PLUS) expression
| expression (MINUS | PLUS) expression
| integerLiteral
;
integerLiteral
: INTLITERAL
;
PLUS: '+';
MINUS: '-';
fragment DIGIT: '0'..'9';
INTLITERAL: DIGIT+;
啊。。。谢谢你的回答。我没有像你提供的那样清楚地解释清楚!是的,有很多无关的输入。。。这里的问题是这样的,但我总是觉得把问题当作重复的来结束,因为解决方案总是涉及一些特定于语法的提示。不客气@jross.ah。。。谢谢你的回答。我没有像你提供的那样清楚地解释清楚!是的,有很多无关的输入。。。这里的问题是这样的,但我总是觉得把问题当作重复的来结束,因为解决方案总是涉及一些特定于语法的提示。欢迎@jross。