【问题标题】:Recursive Descent precedence parsing - matching lower precedence prefix expressions递归下降优先级解析 - 匹配较低优先级前缀表达式
【发布时间】:2014-08-11 18:51:48
【问题描述】:

注意:这是Recursive Descent precedence parsing missing prefix expression的更详细版本

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

E = E8
E8 = E7 'OR' E8 | E7
E7 = E6 'XOR' E7 | E6
E6 = E5 'AND' E6 | E5
E5 = 'NOT' E5 | E4
E4 = E3 '==' E4 | E3 '!=' E4 | E3
E3 = E2 '<' E3 | E2 '>' E3 | E2
E2 = E1 '+' E2 | E1 '-' E2 | E1 '*' E2 | E1 '+' E2 | E1
E1 = '(' E ')' | 'true' | 'false' | '0'..'9'

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

true == NOT false

这是由于 == 运算符需要 RHS 上的 E3,这不能是“NOT”操作。

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

以下是一些需要正确解析的示例:

  • 输入true == 1 &lt; 2,输出==(true, &lt;(1, 2))
  • 输入1 &lt; 2 == true,输出==(&lt;(1, 2), true)
  • 输入NOT true == false,输出NOT(==(true, false))
  • 输入true == NOT false,输出==(true, NOT(false))**不起作用
  • 输入true &lt; NOT false,输出&lt;(true, NOT(false))**不起作用

我已尝试更改级别E4E3E2 以在中缀表达式的RHS 上使用E5,如Recursive Descent precedence parsing missing prefix expression 中所建议的那样(即E3 '==' E5E3 '&lt;' E5 , 等等)。然而,这打破了这些级别之间的优先级,即 true == 1 &lt; 2 将错误地为 parsed as

【问题讨论】:

  • 嗯,我看不出有什么办法,除了用 NOT 添加额外的替代品。例如:E4 = E3 '==' E3 | E3 '!=' E3 | E3 '==' 'NOT' E3 | E3 '!=' 'NOT' E3 | E3
  • 这会很疯狂,因为NOT 不是唯一的前缀表达式(即还有-+ 等)
  • 是的,我同意。因此,我的句子“我看不到方法”的开头,以及我没有将建议作为答案发布的事实:)
  • 这是一种你自己定义的语言,对吧?根据上面的大纲,关系运算符(如==)比逻辑运算符(如AND)绑定更难。这使得A AND B == C AND D 之类的东西解析为A AND (B == C) AND D - 这就是你想要的吗?我认为您可能希望关系运算符位于顶部。
  • 标准做法是使前缀一元运算符具有第二高的优先级(而后缀一元应具有最高优先级)。由于这个确切的原因,以不同的方式定义它们没有多大意义。

标签: algorithm parsing operator-precedence recursive-descent


【解决方案1】:

当坚持你的语言定义方式时,你不能拥有

true == NOT false 

作为您的语言中的有效术语。因为那时

NOT false == true

会模棱两可:解析树可能是

    NOT
     | 
    ==
   /  \
false true

   ==
  /  \
 NOT true
  |
false

注意

true == NOT (false)

是您的语言中的有效术语。您的语言的一个可能更直观的定义是将NOT 级别从E5 降低到E2。那么

true == NOT false 
NOT false == true

都是有效的并且NOTfalse 绑定。第二个表达式的替代含义将表示为

NOT (false == true)

如果这些选项仍然不能满足您,您必须更改/扩展工具。例如。 yacc/bison 解析器允许明确定义运算符优先级;参见例如here

【讨论】:

  • 由于优先级,它并不模棱两可:== 总是尽可能地绑定得更近。所以NOT false == true必须解析为NOT(==(false, true))。有趣的问题是false == NOT true,因为它不可能首先应用==,因此必须解析为==(false, NOT(true))
  • 澄清一下:您想要什么(以及您的大脑可以做什么)和您的“工具”(您指定语言的方式)可以做什么是两件不同的事情。您指定语言的方式不允许解决上述歧义。你的头脑可以——还有其他工具;查看我的编辑。
  • 但也要再想想你的语言:你真的要允许NOT 1吗? (仅仅因为 C 语言允许这样做?)你真的希望最多允许连续三个 OR 操作数吗?
  • 我很乐意使用不同的算法或方法(工具并不那么重要)。另外,我确实想让NOT 1解析。这并不意味着它在语义上是正确的——实际上我会将其设为类型错误,因为 1 不是布尔值。但必须先对其进行解析才能确定。
猜你喜欢
  • 2014-08-08
  • 1970-01-01
  • 2019-06-10
  • 2011-04-19
  • 1970-01-01
  • 2010-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多