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。