【问题标题】:Ambiguous Lexer rules in AntlrAntlr 中的模棱两可的 Lexer 规则
【发布时间】:2017-11-15 23:10:26
【问题描述】:

我有一个 antlr 语法,其中包含多个匹配同一个单词的词法分析器规则。在词法分析过程中无法解决,但通过语法,它变得明确。

例子:

conversion: NUMBER UNIT CONVERT UNIT;
NUMBER: [0-9]+;
UNIT: 'in' | 'meters' | ......;
CONVERT: 'in';

输入:1 in in meters

单词“in”匹配词法分析规则UNITCONVERT

如何在保持语法文件可读的同时解决这个问题?

【问题讨论】:

    标签: antlr antlr4


    【解决方案1】:

    当输入匹配两个词法分析器规则时,ANTLR 选择最长的或第一个,请参阅disambiguate。使用您的语法,in 将被解释为UNIT,而不是CONVERT,并且规则

    conversion: NUMBER UNIT CONVERT UNIT;
    

    无法工作,因为有三个 UNIT 令牌:

    $ grun Question question -tokens -diagnostics input.txt 
    [@0,0:0='1',<NUMBER>,1:0]
    [@1,1:1=' ',<WS>,channel=1,1:1]
    [@2,2:3='in',<UNIT>,1:2]
    [@3,4:4=' ',<WS>,channel=1,1:4]
    [@4,5:6='in',<UNIT>,1:5]
    [@5,7:7=' ',<WS>,channel=1,1:7]
    [@6,8:13='meters',<UNIT>,1:8]
    [@7,14:14='\n',<NL>,1:14]
    [@8,15:14='<EOF>',<EOF>,2:0]
    Question last update 0159
    line 1:5 missing 'in' at 'in'
    line 1:8 mismatched input 'meters' expecting <EOF>
    

    你可以做的是只有IDTEXT 标记并用标签区分它们,如下所示:

    grammar Question;
    
    question
    @init {System.out.println("Question last update 0132");}
        :   conversion NL EOF
        ;
    
    conversion
        :   NUMBER unit1=ID convert=ID unit2=ID
            {System.out.println("Quantity " + $NUMBER.text + " " + $unit1.text +
             " to convert " + $convert.text + " " + $unit2.text);}
        ;
    
    ID      : LETTER ( LETTER | DIGIT | '_' )* ; // or TEXT : LETTER+ ;     
    NUMBER  : DIGIT+ ;
    
    NL      : [\r\n] ;
    WS      : [ \t] -> channel(HIDDEN) ; // -> skip ;
    
    fragment LETTER : [a-zA-Z] ;
    fragment DIGIT  : [0-9] ;
    

    执行:

    $ grun Question question -tokens -diagnostics input.txt 
    [@0,0:0='1',<NUMBER>,1:0]
    [@1,1:1=' ',<WS>,channel=1,1:1]
    [@2,2:3='in',<ID>,1:2]
    [@3,4:4=' ',<WS>,channel=1,1:4]
    [@4,5:6='in',<ID>,1:5]
    [@5,7:7=' ',<WS>,channel=1,1:7]
    [@6,8:13='meters',<ID>,1:8]
    [@7,14:14='\n',<NL>,1:14]
    [@8,15:14='<EOF>',<EOF>,2:0]
    Question last update 0132
    Quantity 1 in to convert in meters
    

    标签可从访问者的规则上下文中获得,因此很容易区分相同类型的标记。

    【讨论】:

      【解决方案2】:

      根据您问题中的信息,很难说最好的解决方案是什么 - 例如,我不知道您的词法分析器规则是什么 - 我也无法说出您为什么有完全模棱两可的词法分析器规则。

      根据我使用 antlr 的经验,词法分析器规则通常不带有任何语义含义;它们只是匹配某种正则表达式的文本。所以,与其拥有VARIABLEMETHOD_NAME 等,我只拥有IDENTIFIER,然后在更高的层次上进行计算。

      换句话说,似乎(从我可以从您的问题中收集到的一点信息)您可能会受益于将 UNITCONVERT 替换为语法规则,或者仅使用一条规则:

      conversion: NUMBER TEXT TEXT TEXT
      

      并验证 ANTLR 侦听器/tree-walker/等中的文本值。

      编辑

      感谢您使用词法分析器规则更新您的问题。现在很清楚为什么它失败了 - 正如 BernardK 指出的那样,antlr 将始终选择第一个匹配的词法分析器规则。这意味着两个模棱两可的词法分析器规则中的第二个不可能匹配,并使您提出的设计不可行。

      我的观点是词法分析器规则不是执行单元验证等事情的正确层;他们擅长结构,而不是内容。评估解析树将比试图扭曲 antlr 语法实用得多。

      最后,您还可以对解析规则进行嵌入式操作,例如根据一组已知单位验证 ID 令牌的值。它可以工作,但会破坏语法的可重用性。

      【讨论】:

      • 我将词法分析器规则添加到示例中以使其更清晰。捕获词法分析器规则中的所有文本并在访问者中手动解析它违背了使用 Antlr 的目的。将词法分析器规则移至语法规则会起作用,但会使语法难以阅读:unit: 'm' 'e' 't' 'e' 'r' | ...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多