如何用regexparser创建电源操作?

时间:2014-12-27 15:29:37

标签: regex scala parsing

我正在使用Scala RegexParser构建一个简单的计算器,我正在尝试使用**创建电源操作规则,如下所示:

package com.pt.pedrorijo91.calc

import scala.util.parsing.combinator.RegexParsers
import scala.math.pow

class Arith extends RegexParsers {

  def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }

  def factor: Parser[Double] = number | "(" ~> expr <~ ")" | expr~"**"~expr ^^ { case x ~ "**" ~ y => pow(x,y)}

  def term  : Parser[Double] = factor ~ rep( "*" ~ factor | "/" ~ factor) ^^ {
    case number ~ list => list.foldLeft(number) {
      case (x, "*" ~ y) => x * y
      case (x, "/" ~ y) => x / y
    }
  }

  def expr  : Parser[Double] = term ~ rep("+" ~ term | "-" ~ term) ^^ {
    case number ~ list => list.foldLeft(number) {
      case (x, "+" ~ y) => x + y
      case (x, "-" ~ y) => x - y
    }
  }

}

我已在factor方法中插入了电源规则,但如果我尝试解析"2 ** 3",则会进入无限循环。

如果我使用expr~"\*\*"~expr代替number~"**"~number,则在解析时会收到以下消息:

  

字符串匹配正则表达式\d+(\.\d*)?' expected but *&#39;结果

我错过了什么?

1 个答案:

答案 0 :(得分:2)

似乎scala的RegexParser构建了递归下降解析器。

问题是你的解析器的基础语法不属于可用它解析的语法类(更正式地说,它是递归的)。

制作factor -> epxr ** expr使您的语法保持递归(并且不再模糊)。

你应该添加另一个级别(非终端符号)来表示**具有最高优先级,并仅使用原子表达式作为其参数来防止出现问题。

这就是这样的

atomicexpr -> number | (expr)

factor -> atomicexpr ( ** atomicexpr )?

请注意,这种结合成功的方式你将被迫添加括号。