【问题标题】:ANTLR Lexer rule only seems to work as part of parser rule, and not part of another lexer ruleANTLR 词法分析器规则似乎只作为解析器规则的一部分工作,而不是另一个词法分析器规则的一部分
【发布时间】:2020-09-14 21:09:05
【问题描述】:

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

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}

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

integerLiteral
    : (PLUS|MINUS)? DIGITS
    ;

现在它似乎工作得很好!

我觉得如果我能够理解为什么会这样,我就会开始理解我正在经历的一些特质。

【问题讨论】:

    标签: antlr antlr4


    【解决方案1】:

    词法分析器以下列方式创建标记:

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

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

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

    是问题所在。对于输入 100,创建了一个 DIGITS 令牌:此处适用规则 2:两个规则都匹配 100,但由于 DIGITS 是在 INTLITERAL 之前定义的,因此会创建一个 DIGITS 令牌。

    解决方案 1

    INTLITERAL移到DIGITS上方:

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

    但现在请注意,DIGITDIGITS 永远不会单独成为标记,因为 INTLITERAL 将始终首先匹配。在这种情况下,您可以将这两个规则都设为fragments,然后将它们放在哪里都没有关系,因为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+;
    

    【讨论】:

    • 啊...感谢您的回答。我没有遇到你提供的解释那么清楚!
    • 是的,SO 上有很多extraneous input ... expecting 问题,但我从不习惯以重复的方式结束问题,因为解决方案总是涉及一些特定于语法的提示。不客气@jross。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-29
    相关资源
    最近更新 更多