ANTLR3语法不匹配谓词规则(ANTLR3 grammar does not match rule

2019-09-28 13:15发布

我有一个组合的语法,我需要提供两个标识词法规则。 这两种标识可以同时使用。 标记位来自Identifer2之前语法。

第一标识符是静态的,而第二标识符规则一些标志的基础上变化。(使用谓词)。

我想第二标识符在语法规则相匹配。 但随着这两个标识符可以匹配一些常见的输入,它不会落在identifer2。

我创建了小的语法,使之可以理解的。 语法是:

@lexer::members
{
  private boolean flag;

  public void setFlag(boolean flag)
  {
    this.flag = flag;
  }
}


identifier1 :
 ID1
 ;

identifier2 :
ID2
; 


ID1 : (CHARS) *;


ID2 : (CHARS | ({flag}? '_'))* ;


fragment CHARS 
: 
  ('a' .. 'z')
;  

如果我尝试匹配identifer2规则为:

    ANTLRStringStream in = new ANTLRStringStream("abcabde");
    IdTestLexer lexer = new IdTestLexer(in);
    lexer.setFlag(true);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    IdTestParser parser = new IdTestParser(tokens);
    parser.identifier2();

它显示错误:线路1:0在“abcabde”失踪ID2

Answer 1:

ID1 : (CHARS) *;
ID2 : (CHARS | ({flag}? '_'))* ;

对于ANTLR这两个规则的意思是:

  • 如果输入的只是字符,它的ID1
  • 如果输入的字符混合和_flag == true ,这是ID2

请注意,如果flag == falseID2将永远不会被匹配。


词法分析器遵循两个基本规则是:

  • 它涵盖输入的最长子序列的令牌匹配
  • 如果多个令牌可以匹配相同的输入,使用至上的语法的一个

我相信你的核心问题是误解词法和语法分析器及其使用之间的区别。 你应该问自己的问题是: 什么时候应该“abcabde”作为匹配ID1 ,当为ID2

  • 始终ID1 -那么你的语法是正确的,因为它是现在。
  • 始终ID2 -那么你应该切换两个规则-但要注意,在这种情况下, ID1将永远不会被匹配。
  • 这取决于flag -那么你需要修改谓词按照你的逻辑,只需切换下划线是不够的。
  • 这取决于是否在输入标识使用 - 那么这是不是一件词法分析器可以决定的,你需要告诉两种标识符除了解析器,而不是词法分析器。 形式上,词法分析器使用常规的语言 ,而你需要上下文无关语言决定对这样的标识符。


文章来源: ANTLR3 grammar does not match rule with predicate