解决ANTLR词法分析器规则歧义的正确方法是什么?

Ana*_*Ana 6 grammar antlr

请参阅以下网址提供的源代码:https://gist.github.com/1684022.

我定义了两个令牌:

ID  :   ('a'..'z' | 'A'..'Z') ('0'..'9' | 'a'..'z' | 'A'..'Z' | ' ')*;

PITCH   
    :   (('A'|'a') '#'?)
    |   (('B'|'b') '#'?) 
    |   (('C'|'c') '#'?);
Run Code Online (Sandbox Code Playgroud)

显然,字母"A"将是一种模糊性.

我进一步定义:

note    :   PITCH;
name    :   ID;
main    :   name ':' note '\n'?
Run Code Online (Sandbox Code Playgroud)

现在,如果我输入"A:A"作为解析器的输入,我总是会收到错误.解析器需要PITCH或ID,具体取决于是先定义ID还是PITCH:

mismatched input 'A' expecting ID
Run Code Online (Sandbox Code Playgroud)

解决这个问题的正确方法是什么,以便按预期工作?


如上所述,虽然直观地解释了解析应该如何工作,但ANTLR并没有做"正确的事".也就是说,即使main规则说a name/ ID应该首先出现,但是词法分析者似乎对此一无所知并将"A"标识为a,PITCH因为它遵循"最长匹配"/"首先出现"规则而不是更合理"什么规则说"规则.

通过匹配ID和PITCH,然后像dasblinkenlight所说的那样重新组合它们是假冒/破解它的唯一解决方案吗?

das*_*ght 5

以下是我将重新考虑这个语法以使其工作的方法:

ID  :   (('a'..'z' | 'A'..'Z') ('0'..'9' | 'a'..'z' | 'A'..'Z' | ' ')+)
    |   ('d'..'z' | 'D'..'Z');

PITCH : 'a'..'c' | 'A'..'C';

SHARP : '#';

note    :   PITCH SHARP?;

name    :   ID | PITCH;

main    :   name ':' note '\n'? EOF
Run Code Online (Sandbox Code Playgroud)

这将长名称与单字符间距名称分开,后者在解析器中"重新统一".此外,"sharp"令牌也有自己的名称,并在解析器中被识别为可选令牌.