我们有以下代码。可在https://scastie.scala-lang.org/JIJ230HAQZ2pqD5qdXSRRw获取
当输入为1+1
,但由于某些原因不能匹配1-1
时,它会产生语法错误。
你能帮帮我吗?
import scala.util.parsing.combinator._
class OurParsers extends RegexParsers {
def expression: Parser[Expression] = addSub
def addSub = (add | sub)
def add: Parser[Expression] = productDivision ~ rep("+" ~> productDivision) ^^ {
case p ~ Nil => p
case p ~ prods => Sum(p, prods)
}
def sub: Parser[Expression] = productDivision ~ rep("-" ~> productDivision) ^^ {
case p ~ Nil => p
case p ~ prods => Subtract(p, prods)
}
def productDivision: Parser[Expression] = term ~ rep("*" ~> term) ^^ {
case t ~ Nil => t
case t ~ terms => Product(t, terms)
}
def term: Parser[Expression] = number | "(" ~> expression <~ ")"
def number: Parser[Number] = """(+|-)?[0-9]+(.[0-9]+)?""".r ^^ {
case num => Number(num.toDouble)
}
}
trait Expression {
def execute: Double
}
case class Sum(val operand1: Expression, val operands: List[Expression]) extends Expression {
def execute =
operand1.execute + operands.map(_.execute).reduce(_+_)
}
case class Subtract(val operand1: Expression, val operands: List[Expression]) extends Expression {
def execute =
operand1.execute - operands.map(_.execute).reduce(_-_)
}
case class Product(val operand1: Expression, val operands: List[Expression]) extends Expression {
def execute =
operand1.execute * operands.map(_.execute).reduce(_*_)
}
case class Division(val operand1: Expression, val operands: List[Expression]) extends Expression {
def execute =
operand1.execute / operands.map(_.execute).reduce(_/_)
}
case class Number(val value: Double) extends Expression {
def execute = value
}
val parsers = new OurParsers
val result = parsers.parseAll(parsers.expression, "1-1")
result match {
case result: parsers.Failure => throw new Exception("syntax error")
case _ => {
val exp = result.get // get the expression from the tree
println("tree: " + exp.toString)
val value = exp.execute // execute the expression
println(value.toString) // return string representation of result
}
}
原因是-
既可以是数字的一部分,也可以是二进制运算。在到达sub
之前,将-
绑定为number
的一部分。因此,当您想要term
-
term
时,您得到了term
term
序列。
你必须改变你的语法来避免这个问题,或者继续写像1-(1)
这样的东西,因为-(1)
不会被解析为数字(尽管它建议你不会将-
解析为一元操作,所以语法改变可能会更好)。