【问题标题】:Recursive Descent precedence parsing missing prefix expression递归下降优先级解析缺少前缀表达式
【发布时间】:2014-08-08 13:58:25
【问题描述】:

我正在构建一个简单的语言解析器,但遇到了较低优先级前缀表达式的问题。这是一个示例语法:

E = E5
E5 = E4 'OR' E4 | E4
E4 = E3 'AND' E3 | E3
E3 = 'NOT' E3 | E2
E2 = E1 '==' E1 | E1
E1 = '(' E ')' | 'true' | 'false'

但是,如果 NOT 用作更高优先级中缀运算符的 RHS,则此语法不能正常工作,即:

true == NOT false

这是由于 == 运算符需要 RHS 上的 E1,这不能是 NOT 运算。

我不确定表达这种语法的正确方法?是否仍然可以使用这种简单的递归下降方法,或者我需要转向更具特色的算法(调车场或优先攀登)。

【问题讨论】:

  • 请注意,true == (NOT false) 会解析,因为显式括号规则会从顶层重新开始计算。
  • 也许使用波兰符号? E = E5 E5 = 'OR' E4 E4 | E4 E4 = 'AND' E3 E3 | E3 E3 = 'NOT' E3 | E2 E2 = '==' E1 E1 | E1 E1 = '(' E ')' | 'true' | 'false'
  • 如果我理解正确,您不希望 E == E 像不是 (E == E) 那样解析,而是 E == not E 像 E == (笔记)。这是可能的,但很奇怪。如果这确实是您想要的,请在问题中更清楚地说明。
  • 这确实很奇怪,但这是解析E == not E的唯一合乎逻辑的有效方式。
  • 注意 - 我已经在stackoverflow.com/questions/24337000进行了澄清和扩展

标签: algorithm parsing operator-precedence recursive-descent


【解决方案1】:

假设以下输入和预期的解析是正确的:

  1. 测试 1
    • 输入:true == NOT false
    • 输出:(true == (NOT false))
  2. 测试 2
    • 输入:NOT true == false
    • 输出:(NOT (true == false))
  3. 测试 3
    • 输入:NOT true == NOT false
    • 输出:(NOT (true == (NOT false)))

这是一个可以解决问题的 (ANTLR4) 语法:

grammar Expr;

e : e5;
e5 : e4 'OR' e5 | e4;
e4 : e3 'AND' e4 | e3;
e3 : 'NOT' e3 | e2;
e2 : e1 '==' e3 | e1;
e1 : '(' e ')' | 'true' | 'false';

S : [ \t\r\n] -> skip;

解析创建的 ANTLR:

1

2

3

【讨论】:

  • 漂亮的总结和漂亮的图表!我可以看到它是如何工作的,它告诉我我过度简化了这个例子——如果有多个高于 NOT 的中缀优先级,这就会失败。我会接受答案,但我还在这里打开了一个新的 stackoverflow 问题,其中包含更高级的示例:stackoverflow.com/questions/24337000
【解决方案2】:

您的语言也(不必要地)模棱两可。修复也可以帮助您解决此问题。

这里,D 是“析取”的简写,C 是合取,N 是否定,P 是初级,E 是相等。

D = C | C 'OR'  D
C = N | N 'AND' C
N = E |   'NOT' N
E = P | P '=='  P
P = '(' E ')' | 'true' | 'false'

【讨论】:

  • 好奇:怎么会模棱两可?您的解决方案会有所帮助,只是它会更改优先级。 == 应该比NOT 绑定得更紧密,而你却把它颠倒过来了。 NOT 1==2 应解析为 NOT(==(1, 2)),但您的将解析为 ==((NOT 1), 2)
  • @ChrisLeishman:你的在解析true AND true AND true 时是模棱两可的,它不知道如何对它们进行分组。至于==绑定得更紧,你自己修就好了……不过我给你修好了。为什么投反对票? :(
  • 否决票是因为它改变了语法,使其不是我所追求的。但是你现在解决了这个问题。但是,您现在拥有的语法将不起作用E = P | P '==' P 意味着“==”的 RHS 上不能存在“NOT”术语(只有“(”、“真”或“假”)。
  • @ChrisLeishman:你有任何猜测如何自己解决吗?
  • 如果我这样做了,我就不会问了 :) 除了考虑使用不同的算法(也许是调车场或优先攀登)。
【解决方案3】:

也许使用波兰符号?

E = E5
E5 = 'OR' E4 E4 | E4
E4 = 'AND' E3 E3 | E3
E3 = 'NOT' E3 | E2
E2 = '==' E1 E1 | E1
E1 = '(' E ')' | 'true' | 'false'

【讨论】:

  • 这对解析所述语法没有帮助。 == 应该是中缀。
猜你喜欢
  • 2014-08-11
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 2016-04-26
  • 2015-08-07
相关资源
最近更新 更多