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

时间:2018-06-05 09:43:31

标签: parsing antlr rule

我对ANTLR很新,我需要在识别输入字符串时解释它的行为。根据我的理解,用大写字母表示的规则是词法规则,而以小写字母开头的规则是解析器规则。
我有以下语言,我需要相应地写出语法:
language
所以L应该接受由以下组成的所有字符串:

  • 非空字符串,带有b和/或c
  • d
  • 非空字符串,带有和/或c

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

start   : (alfa 'd' beta);

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

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

但是如果我像下面那样更改它,则不再识别相同的字符串(下面你可以看到ANTLRWorks的调试器结果):

enter image description here

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,则不会出现问题。

有人可以向我提供有关此行为的解释吗?因为我找不到解决这个问题的特定问题 非常感谢你!

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

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

grammar Example;

start   : (α D β) EOF;

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

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

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

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

enter image description here