ANTLR:具有大写规则的语法将无法识别输入

ANTLR: Grammar with uppercase rules won't recognize input

我对 ANTLR 很陌生,我需要解释它在识别输入字符串时的行为。据我了解,以大写字母开头的规则是词法分析器规则,而以小写字母开头的规则是解析器规则。
我有以下语言,我需要相应地编写语法:

所以 L 应该接受由以下组成的所有字符串:

这是我写的第一个语法,在识别输入时我没有遇到问题bbbcbcbcbcdaaacacacaaaa:

start   : (alfa 'd' beta);

alfa    : ('b'|'c') | ('b'|'c') alfa;
beta    : ('a'|'c') | ('a'|'c') beta;

WS      : (' '|'\n'|'\t'|'\r')->skip;

但是如果我像下面这样改变它,同样的字符串就不再被识别了(下面你可以看到ANTLRWorks的调试器结果):

start   : (alfa 'd' beta);

alfa    : ALFA_VALS | ALFA_VALS alfa;
beta    : BETA_VALS | BETA_VALS beta;

ALFA_VALS: ('b'|'c');
BETA_VALS: ('a'|'c');
WS      : (' '|'\n'|'\t'|'\r')->skip;

此外,如果我将ALFA_VALSBETA_VALS分别更改为alfa_valsbeta_vals,则不会出现任何问题。

有人可以为我提供有关此行为的解释吗?因为我找不到解决这个问题的具体方法。
非常感谢!

ANTLR 词法分析器匹配输入的最长可能子序列,或者如果它可以使用多个词法分析器规则匹配相同的输入,它使用第一个匹配的规则。

词法分析器不知道上下文和解析器状态,仅根据输入的字符做出决定。

如果您以这种方式在词法分析器中定义 ALFA_VALSBETA_VALS,输入 'c'始终 匹配为 ALFA_VALS令牌。

我可以建议一个稍微不同的方法吗?您的正确递归定义对于 ANTLR 来说是相当不典型的(虽然在自下而上的解析器中经常使用)。而是使用您的语言中定义的更简单的表达式:

grammar Example;

start   : (α D β) EOF;

α: (B | C)+;
β: (A | C)+;

A: 'a';
B: 'b';
C: 'c';
D: 'd';

WS: (' '|'\n'|'\t'|'\r') -> skip;

这为您提供了这个更简单、更自然的解析树: