ANTLR Lexer规则似乎只作为解析器规则的一部分,而不是另一个lexer规则的一部分

问题描述 投票:0回答:1

如果我具有以下语法来分析由空格分隔的整数列表:

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}

但是,如果删除词法分析器INTLITERAL规则并将其放在解析器规则integerLiteral之下,则像这样

integerLiteral
    : (PLUS|MINUS)? DIGITS
    ;

现在看来一切正常!

[我认为,如果我能够理解为什么会这样,那么我将开始理解我所遇到的一些特质。

antlr antlr4
1个回答
0
投票

词法分析器以以下方式创建令牌:

  1. 尝试为单个令牌匹配尽可能多的字符
  2. 如果两个标记匹配相同的字符,则让第一个定义为“胜利”

鉴于上述2条规则的信息,您将看到您的规则:

DIGITS: DIGIT+;
INTLITERAL: (PLUS|MINUS)? DIGITS;

是问题。对于输入100,创建了DIGITS令牌:规则2在这里适用:两个规则都与100匹配,但是由于DIGITSINTLITERAL之前定义,因此创建了DIGITS令牌。

解决方案1

INTLITERAL移到DIGITS上方:

INTLITERAL: (PLUS|MINUS)? DIGITS;
DIGIT: '0'..'9';
DIGITS: DIGIT+;

但是现在请注意,DIGITDIGITS永远不会单独成为令牌,因为INTLITERAL将始终首先匹配。在这种情况下,您可以将这两个规则都设置为fragment,然后将它们放置在哪里都没有关系,因为fragment规则仅在其他词法分析器规则中使用(在解析器规则中不使用)

解决方案2

制作DIGITDIGITS片段

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+
© www.soinside.com 2019 - 2024. All rights reserved.