【问题标题】:Grammars: How to add a level of precedence语法:如何添加优先级
【发布时间】:2020-05-07 20:47:28
【问题描述】:

假设我有以下用于简单计算器语言的上下文无关语法:

S->TS'
S'->OP1 TE'|e
T->FT'
T'->OP2 FT'|e
F->id|(S)
OP1->+|-
OP2->*|/

正如我们所见,* 和 / 比 + 和 - 具有更高的优先级。 但是,如何添加另一个优先级?示例是指数,^, (ex:3^2=9) 还是其他?请解释你的程序和你是如何到达那里的原因,以便我可以为其他操作员做。

【问题讨论】:

    标签: grammar operator-precedence context-free-grammar


    【解决方案1】:

    这是一个更易读的语法:

    expr: sum
    
    sum : sum add_op term
        | term
    
    term: term mul_op factor
        | factor
    
    factor: ID
          | '(' expr ')'
    
    add_op: '+' | '-'
    mul_op: '*' | '/'
    

    这可以使用相同的模式轻松扩展:

    expr: bool
    
    bool: bool or_op conj
        | conj
    
    conj: conj and_op comp
        | comp
    
    /* This one doesn't allow associativity. No a < b < c in this language */ 
    comp: sum comp_op sum
    
    sum : sum add_op term
        | term
    
    term: term mul_op factor
        | factor
    
    /* Here we'll add an even higher precedence operators */
    /* Unlike the other operators, though, this one is right associative */
    factor: atom exp_op factor
        | atom
    
    atom: ID
        | '(' expr ')'
    
    /* I left out the operator definitions. I hope they are obvious. If not,
     * let me know and I'll put them back in
     */
    

    我希望那里的模式或多或少很明显。

    这些语法在递归下降解析器中不起作用,因为递归下降解析器在左递归中窒息。您已经通过左递归消除算法运行了语法,您也可以对上面的语法执行此操作。但是请注意,消除左递归或多或少会消除左递归和右递归之间的差异,因此在使用递归下降语法识别解析后,您需要根据您对运算符关联性的了解来修复它,因为关联性不再是语法固有的。

    对于这些简单的产生式,消除左递归非常简单,只需两步。我们从一些非终端开始:

    foo: foo foo_op bar
       | bar
    

    然后我们翻转它以使其具有正确的关联性:

    foo: bar foo_op foo
       | bar
    

    (如果运算符最初是右结合的,如上面的取幂,则不需要此步骤。)

    然后我们需要左因子,因为 LL 解析要求非终结符的每个替代项都有一个唯一的前缀:

    foo : bar foo'
    foo': foo_op foo
        | ε
    

    对上面的每个递归产生式(即除exprcompatom 之外的所有递归产生式)都这样做会产生一个看起来像你开始使用的语法,只是有更多的运算符。

    顺便强调一下,这里没有神秘的魔法力量在起作用。当语法说,例如:

    term: term mul_op factor
        | factor
    

    它的意思是term(或乘积,如果您愿意)不能是乘法的右手参数,但它可以是左手参数。这也是说,如果您处于产品有效的地步,那么您实际上并不需要带有乘法运算符的东西。您可以改用factor。但显然你不能使用求和,因为factor 不会使用求和运算符解析表达式。 (它确实会解析括号内的任何内容。但这些都是括号内的内容。)

    这就是语法中隐含关联性和优先级的意义。

    【讨论】:

      猜你喜欢
      • 2021-07-12
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2015-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多