请参阅以下网址提供的源代码:https://gist.github.com/1684022。
我定义了两个令牌:
ID : ('a'..'z' | 'A'..'Z') ('0'..'9' | 'a'..'z' | 'A'..'Z' | ' ')*;
PITCH
: (('A'|'a') '#'?)
| (('B'|'b') '#'?)
| (('C'|'c') '#'?);
显然,字母“A”会含糊不清。
我进一步定义:
note : PITCH;
name : ID;
main : name ':' note '\n'?
现在,如果我输入“A:A”作为解析器的输入,我总是会收到错误。解析器需要PITCH或ID,具体取决于是先定义ID还是PITCH:
mismatched input 'A' expecting ID
解决此问题的正确方法是什么,以使其按预期工作?
如上所述,尽管直观地了解解析应该如何工作,但ANTLR并没有做“正确的事情”。也就是说,即使main
规则说name
/ ID
应该先出现,但词法分析员似乎对此一无所知并将“A”标识为PITCH
,因为它遵循“最长匹配”/“先到先得”的规则,而不是更合理的“规则所说的”规则。
通过匹配ID和PITCH,然后像dasblinkenlight所说的那样重新组合它们,唯一的解决方法是伪造/破解吗?
答案 0 :(得分: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
这将长名称与单字符间距名称分开,这些名称在解析器中“重新统一”。此外,“sharp”令牌也有自己的名称,并在解析器中被识别为可选令牌。