Scala编程第33章解释了Combinator Parsing:
它提供了这个例子:
import scala.util.parsing.combinator._
class Arith extends JavaTokenParsers {
def expr: Parser[Any] = term~rep("+"~term | "-"~term)
def term: Parser[Any] = factor~rep("*"~factor | "/"~factor)
def factor: Parser[Any] = floatingPointNumber | "("~expr~")"
}
如何将expr
映射到比Parser[Any]
更窄的类型?换句话说,
我想带def expr: Parser[Any]
并通过^^
将其映射为更严格的类型。
注意 - 我在Scala Google网上论坛中提出了这个问题 - https://groups.google.com/forum/#!forum/scala-user,但没有收到帮助我的完整答案。
答案 0 :(得分:3)
正如评论中已经说明的那样,您可以将类型缩小到您喜欢的任何类型。您只需在^^
之后指定它。
这是一个完整的示例,其中包含您给定代码的数据结构。
object Arith extends JavaTokenParsers {
trait Expression //The data structure
case class FNumber(value: Float) extends Expression
case class Plus(e1: Expression, e2: Expression) extends Expression
case class Minus(e1: Expression, e2: Expression) extends Expression
case class Mult(e1: Expression, e2: Expression) extends Expression
case class Div(e1: Expression, e2: Expression) extends Expression
def expr: Parser[Expression] = term ~ rep("+" ~ term | "-" ~ term) ^^ {
case term ~ rest => rest.foldLeft(term)((result, elem) => elem match {
case "+" ~ e => Plus(result, e)
case "-" ~ e => Minus(result, e)
})
}
def term: Parser[Expression] = factor ~ rep("*" ~ factor | "/" ~ factor) ^^ {
case factor ~ rest => rest.foldLeft(factor)((result, elem) => elem match {
case "*" ~ e => Mult(result, e)
case "/" ~ e => Div(result, e)
})
}
def factor: Parser[Expression] = floatingPointNumber ^^ (f => FNumber(f.toFloat)) | "(" ~> expr <~ ")"
def parseInput(input: String): Expression = parse(expr, input) match {
case Success(ex, _) => ex
case _ => throw new IllegalArgumentException //or change the result to Try[Expression]
}
}
现在我们可以开始解析一些东西了。
Arith.parseInput("(1.3 + 2.0) * 2")
//yields: Mult(Plus(FNumber(1.3),FNumber(2.0)),FNumber(2.0))
当然,您也可以使用Parser[String]
或Parser[Float]
,直接转换或评估输入字符串。正如我对你说的那样。