我正在使用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;结果
我错过了什么?
答案 0 :(得分:2)
似乎scala的RegexParser构建了递归下降解析器。
问题是你的解析器的基础语法不属于可用它解析的语法类(更正式地说,它是递归的)。
制作factor -> epxr ** expr
使您的语法保持递归(并且不再模糊)。
你应该添加另一个级别(非终端符号)来表示**
具有最高优先级,并仅使用原子表达式作为其参数来防止出现问题。
这就是这样的
atomicexpr -> number | (expr)
factor -> atomicexpr ( ** atomicexpr )?
请注意,这种结合成功的方式你将被迫添加括号。