将数学表达式与控制流混合

时间:2017-02-01 19:34:08

标签: algorithm parsing compiler-construction abstract-syntax-tree

我想知道,当与控制流混合时,如何解析表达式。

我们假设这样的语法:

case 
  when a == Method() + 1 
    then Something(1) 
  when a == Other() - 2
    then 1
  else 0
end

我们在这里有两个条件表达式,Method() + 1Something(1)0。每个都可以通过Shunting-yard algorithm翻译为后缀,然后轻松翻译为AST。但是有可能扩展这个算法来处理控制 - 流量呢?还是有其他方法可以解决表达式和控制流的混合问题吗?

另一个例子:

a == b ? 1 : 2  

我怎样才能对这样的表达式进行分类:a between b and c,我可以说between是三个参数函数吗?或者这些表达有什么特别的名字吗?

2 个答案:

答案 0 :(得分:2)

分流码算法用于具有一元和二元运算符的表达式。你需要一些更强大的东西,如LL(1)或LALR(1)来解析控制流语句,一旦你有了它,它也将处理表达式。根本不需要Shunting-yard算法。

答案 1 :(得分:2)

您当然可以使用运算符优先级语法解析三元运算符。在

expr ? expr : expr
这里的二进制“运算符”是? expr :,它方便地以运算符令牌开始和结束(尽管是不同的)。为了使分流码适应于此,将的右优先级和的左优先级分配给?:运算符的优先级。 的左优先级和的右优先级是±∞,就像括号一样(实际上它们是)。

由于case语句基本上是重复应用三元运算符,使用略有不同的标记拼写,并产生类似的解决方案。 (此处case whenend纯属括号,而then和其余when对应?:。)

话虽如此,使用LALR(1)解析器生成器确实更简单,并且几乎可以肯定有一种可用于您正在编写的语言。

很明显,三元运算符和OP的case语句都是运算符语法:

  1. 三元运营商:

    ternary-expr: non-ternary-expr
                | non-ternary-expr '?' expr ':' ternary-expr
    

    通常,三元运算符将优先于任何其他运算符并且与右侧相关联,这就是上面的编写方式。在C和其他语言中,三元表达式具有与赋值表达式相同的优先级,这很容易添加。这导致了关系

    • X ·> ?
    • ? <· X
    • ? ·=· :
    • X ·> :
    • : <· X
  2. 案例陈述(许多可能的表述之一):

    case_statement: 'case' case_body 'else' expr 'end'
    case_body: 'when' expr 'then' expr
             | case_body 'when' expr 'then' expr
    

    以下是上述语法的优先关系:

    • case <· when
    • case ·=· else
    • when <· X(见下文)
    • when ·=· then
    • then ·> when
    • then ·> else
    • else <· X
    • else ·=· end
    • X ·> then
    • X ·> when
    • X ·> end
    上述关系中的

    X是指任何二元或一元运算符,任何值终结符()

    直接找到所有这些终端的左右优先功能;该模式与标准代数语法中的括号类似。