【问题标题】:How to deal with unary minus and exponentiation in an expression parser如何在表达式解析器中处理一元减号和求幂
【发布时间】:2018-12-04 06:59:05
【问题描述】:

我知道求幂比一元减号具有更高的优先级。但是,如果我基于它构建一个表达式解析器,我仍然无法解析像 2—-3 这样的表达式。为了处理这些问题,我发现我还需要在要素生产规则中添加一元减处理,该规则比指数高一个优先级。这是通常如何处理一元减号和幂运算的方式吗?我没有在网上或书中找到任何关于这种特殊情况的内容。我想知道使幂运算和一元运算符具有相同的优先级是否有帮助?

我正在手工制作一个递归下降解析器,我尝试将幂和一元生产规则合并在一起,但它似乎不起作用。以下 EBNF 起作用的是什么

factor        = '(' expression ')' | variable | number | '-' factor
power         = factor { '^' factor } 
unaryTerm     = ['-' | '+'] power
term          = unaryTerm { factorOp unaryTerm }
expression    = term { termOp term }

 termOp        = '+' | '-'
 factorOp      = '*' | '/'

【问题讨论】:

    标签: expression context-free-grammar ebnf


    【解决方案1】:

    除非您有不寻常的要求,否则将一元减号和取幂放在同一个非终结符中可以正常工作,因为取幂是右关联的:(Yacc/bison 语法)

    atom: ID
        | '(' expr ')'
    factor
        : atom
        | '-' factor
        | atom '^' factor
    term: factor
        | term '*' factor
    expr: term
        | expr '+' term
        | expr '-' term
    

    确实,要使此语法有意义,实际上需要右关联的幂运算。考虑使用左关联运算符的替代方案。

    假设我们有两个运算符,⊕ 和 ≀,⊕ 具有比 ≀ 更紧密的关联性和绑定性,因此 ≀ a ⊕ b≀(a ⊕ b)

    由于 ⊕ 是左关联的,我们希望 a ⊕ b ⊕ c 被解析为 (a ⊕ b) ⊕ c。但是我们得到了一个奇怪的东西。 a ⊕ ≀ b ⊕ c(a ⊕ ≀b) ⊕ c) 相同还是与a ⊕ ≀(b ⊕ c)) 相同?这两种选择似乎都违反了简单的模式。 [注1]

    当然,可以为每种情况编写一个明确的语法,但是对于一个只是按照优先级图表的程序员来说,哪一个不会那么令人惊讶?最可能的结果是 ≀ 的样式要求。表达式总是被完全括号括起来,即使括号是多余的。 (C 风格指南中充满了这样的建议,许多编译器会责备你使用正确但“不直观”的表达式。)


    注意事项:

    1. 如果您使用优先级声明,您将得到a ⊕ ≀(b ⊕ c)),这可能是直观的,也可能不是直观的,这取决于您的直觉。

    【讨论】:

    • 你的 yacc 描述很有趣,你把一元和权力放在同一水平,我想这就是它的含义吗?看起来它会处理我认为应该产生-16而不是+16的情况-2^4?
    • @rhody:是的,这就是我所说的,我认为这也是你在最后一句话中所问的。使求幂绑定更紧密的全部意义在于使-2^4 成为-16
    • 我正在手工制作一个递归下降解析器,我尝试将幂和一元生产规则合并在一起,但它似乎不起作用。起作用的是以下 EBNF(无法渲染 ebnf,因此行用分号分隔): factor = '(' expression ')' |变量 |号码 | '-' 因素;功率 = 因子 { '^' 因子 } ;一元术语 = ['-' | '+'] 权力; term = unaryTerm { factorOp unaryTerm };表达式 = term { termOp term }; termOp = '+' | '-';因子操作 = '*' | '/';
    • @rhody:我认为这会对2^-2^4 产生不正确的结果,结果应该是1/(2^16) 而不是65536。您可以尝试power = ['+' | '-'] factor { '^' ['+' | '-'] factor }(同时消除unaryTermfactor 中的冗余一元运算符。)虽然我想我会选择 power = ['+' | '-'] factor [ '^' power]。 (故意用递归替换循环。)
    • 我会试一试,在这里感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2012-05-20
    • 1970-01-01
    • 2020-02-18
    • 2018-04-05
    相关资源
    最近更新 更多