将Parser [Any]转换为Stricter Type

时间:2014-06-23 20:25:13

标签: scala parsing

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,但没有收到帮助我的完整答案。

1 个答案:

答案 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],直接转换或评估输入字符串。正如我对你说的那样。