递归下降解析:高优先级一元运算符

时间:2013-11-09 23:34:43

标签: parsing recursive-descent

我已经想出如何使用优先级实现二元运算符,就像这样(伪代码):

method plus
   times()

   while(consume(plus_t)) do
       times()
   end
end

method times
   number()

   while(consume(times_t))
       number()
   end
end

// plus() is the root operation

// omitted: number() consumes a number token

因此,当我解析4 + 5 * 6时,它会:

    1. 乘法
      1. 号码(4消费)
    2. plus_t消耗
    3. 乘法
      1. 号码(5消费)
      2. times_t消耗
      3. 号码(6消费)
  1. 但是,当我尝试添加minus方法时(前缀为-4缩写,而不是像4 - 5这样的中缀缩写):

    method minus
        consume(minus_t)
        plus()
    end
    

    优先级非常低,因此-4 + 5变为-(4 + 5)而不是(-4) + 5,这是不可取的。

    如何建立高优先级的一元运算符?

1 个答案:

答案 0 :(得分:3)

您没有说过在层次结构中添加minus方法的位置,但看起来您将其添加到plus之上并将其作为根。

如果您希望unary -的优先级高于+*,则需要将其置于最后。

在你的伪代码中,这样的东西应该有效:

method times
   minus()

   while(consume(times_t))
       minus()
   end
end

method minus
    if(consume(minus_t))
      // next number should have a unary minus attached
      number()
    else
      number()
    end
end

我现在正在学习解析器,所以我根据你的伪代码编写了一个完整的解析器,它是用LiveScript编写的,但应该很容易理解。

编辑:在jsfiddle.net上运行示例 - http://jsfiddle.net/Dogbert/7Pmwc/

parse = (string) ->
  index = 0

  is-digit = (d) -> '0' <= d <= '9'

  plus = ->
    str = times()
    while consume "+"
      str = "(+ #{str} #{times()})"
    str

  times = ->
    str = unary-minus()
    while consume "*"
      str = "(* #{str} #{unary-minus()})"
    str

  unary-minus = ->
    if consume "-"
      "(- #{number()})"
    else
      number()

  number = ->
    if is-digit peek()
      ret = peek()
      advance()
      while is-digit peek()
        ret += peek()
        advance()
      ret
    else
      throw "expected number at index = #{index}, got #{peek()}"

  peek = ->
    string[index]

  advance = ->
    index++

  consume = (what) ->
    if peek() == what
      advance()
      true

  plus()


console.log parse "4+5*6"
console.log parse "-4+5"
console.log parse "-4*-5+-4"

输出:

(+ 4 (* 5 6))
(+ (- 4) 5)
(+ (* (- 4) (- 5)) (- 4))

PS:您可能希望查看Operator-precedence Parsers以便相对轻松地解析复杂的优先级/关联性。