语法/ ANTLRWorks中的嵌套括号/字符'('和')'警告:决策可以匹配输入,例如......使用多个备选方案

时间:2011-07-31 17:17:14

标签: nested char antlr grammar antlrworks

下面的语法解析( left part = right part # comment )# comment是可选的。

两个问题:

  1. 有时警告(ANTLRWorks 1.4.2): 决策可以使用多种替代方式匹配输入,例如“{Int,Word}”:1,2 (引用id2
    但有时候只是!
  2. 下一个扩展名应该是注释(id2)可以包含字符'('和')'。
  3. 语法:

    grammar NestedBrackets1a1;
    
    //==========================================================
    // Lexer Rules
    //==========================================================
    
    Int
      :  Digit+
      ;
    
    fragment Digit
      :  '0'..'9'
      ;
    
    Special
      : ( TCUnderscore | TCQuote )
      ;
    TCListStart   : '(' ; 
    TCListEnd     : ')' ;   
    fragment TCUnderscore  : '_' ;
    fragment TCQuote       : '"' ;
    
    // A word must start with a letter
    Word
      :  ( 'a'..'z' | 'A'..'Z' | Special ) ('a'..'z' | 'A'..'Z' | Special | Digit )*
      ;
    
    Space
      :  ( ' ' | '\t' | '\r' | '\n' ) { $channel = HIDDEN; }
      ;
    
    //==========================================================
    // Parser Rules
    //==========================================================
    
    assignment
      :  TCListStart id1 '=' id1 ( comment )? TCListEnd
      ;
    
    id1
      :  Word+
      ;
    
    comment
      : '#' ( id2 )*
      ;
    
    id2
      :  ( Word | Int )+
      ;
    

1 个答案:

答案 0 :(得分:0)

  

ANTLRStarter写道:

     

有时警告(ANTLRWorks 1.4.2):决策可以使用多个替代方案匹配输入,例如“{Int,Word}”:1,2(引用id2)   但有时候只是!

不,您发布的语法总是产生此警告。也许你并不总是注意到它(你的IDE插件或ANTLRWorks可能会在你没有打开的标签中显示它),但警告就在那里。通过从命令行创建词法分析器/解析器来说服自己:

java -cp antlr-3.4-complete.jar org.antlr.Tool NestedBrackets1a1.g

将产生:

warning(200): NestedBrackets1a1.g:49:19:
Decision can match input such as "{Int, Word}" using multiple alternatives: 1, 2

As a result, alternative(s) 2 were disabled for that input

这是因为*规则中( id2 )之后comment id2,而( Word | Int )+也是令牌的重复:"# foo bar"。假设您的输入为#Word后跟两个"foo"令牌。 ANTLR现在可以通过多种方式解析输入:"bar"可以匹配2个令牌( id2 )*id2,其中Word匹配单个"foo"一次只有令牌,但"bar"id2也可以是comment : '#' ( ( Word | Int )+ )* ; 规则的一次匹配。

查看合并后的规则:

( ( ... )+ )*

了解你是如何重复重复的:*?这通常是一个问题,就像你的情况一样。

通过将?替换为comment : '#' ( id2 )? ; id2 : ( Word | Int )+ ;

来解决此问题
+

或删除comment : '#' ( id2 )* ; id2 : ( Word | Int ) ;

TCListEnd
  

ANTLRStarter写道:

     

下一个扩展名应该是注释(id2)可以包含字符'('和')'。

这是一个问题,因为评论后跟),即)。我不建议让评论与Comment : '#' ~('\r' | '\n')* {skip();} ; 匹配。

修改

请注意,在对输入源进行标记时,通常会从源文件中删除注释。这样您就不需要在解析器规则中考虑它们了。你可以通过词法分析器规则中“跳过”这些标记来实现这一点:

{{1}}