【问题标题】:ANTLR: Grammar with uppercase rules won't recognize inputANTLR:带有大写规则的语法无法识别输入
【发布时间】:2018-06-05 09:43:31
【问题描述】:

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

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

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

这是我写的第一个语法,识别输入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 v4 而不是您现在使用的旧 v3。

标签: parsing antlr rule


【解决方案1】:

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

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

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

【讨论】:

  • 非常感谢您的解释!那么,在不同的词法分析器规则中处理相同的字符时,我有哪些选择?或者在解析器规则中转换它们是否正确?
  • 当您需要上下文来确定输入的含义时,将其留给解析器。词法分析器用于将输入标记为对解析器本身是原子的部分。您可以为'a''b''c' 制作代币。如果'c' 对解析器有两种不同的含义,您需要将其含义(此处为“alfa”或“beta”)的决定留给解析器。
【解决方案2】:

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

grammar Example;

start   : (α D β) EOF;

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

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

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

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

【讨论】:

  • 迈克,你是如何得到这样一张漂亮的图表的?我希望它适用于 Windows。
  • 这是我 ANTLR4 extension 的一部分,用于 Visual Studio Code(它是一个跨平台编辑器)。
猜你喜欢
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多