具有可逆结构的scala解析器组合器

时间:2016-05-05 08:35:30

标签: scala

您好,我是Scala的初学者;现在学习Scala解析器组合,编写“MiniLogicParser”,一个用于命题逻辑公式的迷你解析器。我成功地解析了它,但无法转换为case类。我尝试了下面的代码,

import java.io._
import scala.util.parsing.combinator._

sealed trait Bool[+A]
case object True extends Bool[Nothing]
case class Var[A](label: A) extends Bool[A]
case class Not[A](child: Bool[A]) extends Bool[A]
case class And[A](children: List[Bool[A]]) extends Bool[A]

object LogicParser extends RegexParsers {
  override def skipWhitespace = true

  def formula = ( TRUE | not | and | textdata )
  def TRUE  = "TRUE"
  def not : Parser[_] = NEG ~ formula  ^^ {case ( "!"  ~ formula) => Not(formula)}
  def and : Parser[_] = LPARENTHESIS ~ formula ~ opt(CONJUNCT ~ formula) ~ RPARENTHESIS
  def NEG = "!"
  def CONJUNCT = "&&"
  def LPARENTHESIS = '('
  def RPARENTHESIS = ')'
  def textdata = "[a-zA-Z0-9]+".r

  def apply(input: String): Either[String, Any] = parseAll(formula, input) match {
      case Success(logicData, next)        => Right(logicData)
      case NoSuccess(errorMessage, next) => Left(s"$errorMessage on line ${next.pos.line} on column ${next.pos.column}")
    }
}

但是,编译失败并显示以下错误消息

[error] ... MiniLogicParser.scala:15 type mismatch;  
[error]  found : Any 
[error]  required: Bool[?]  
[error]  def not : Parser[_] = NEG ~ formula  ^^ {case ( "!"  ~ formula) => Not(formula)}

我可以部分理解错误信息;即,对于第15行,我试图将解析结果转换为case类,这意味着正在发生类型不匹配。但是,我不明白如何修复此错误。

如果有人给我任何暗示,我很高兴。

2 个答案:

答案 0 :(得分:1)

我已经适应了你的解析器。

import scala.util.parsing.combinator._
sealed trait Bool[+A]
case object True extends Bool[Nothing]
case class Var[A](label: A) extends Bool[A]
case class Not[A](child: Bool[A]) extends Bool[A]
case class And[A](l: Bool[A], r: Bool[A]) extends Bool[A]


object LogicParser extends RegexParsers with App {
  override def skipWhitespace = true

  def NEG = "!"
  def CONJUNCT = "&&"
  def LP = '('
  def RP = ')'

  def TRUE = literal("TRUE") ^^ { case _ => True }
  def textdata = "[a-zA-Z0-9]+".r ^^ { case x => Var(x) }

  def formula: Parser[Bool[_]] = textdata | and | not | TRUE
  def not = NEG ~ formula ^^ { case n ~ f => Not(f) }
  def and = LP ~> formula ~ CONJUNCT ~ formula <~ RP ^^ { case f1 ~ c ~ f2 => And(f1, f2) }

  def apply(input: String): Either[String, Any] = parseAll(formula, input) match {
    case Success(logicData, next) => Right(logicData)
    case NoSuccess(errorMessage, next) => Left(s"$errorMessage on line ${next.pos.line} on column ${next.pos.column}")
  }

  println(apply("TRUE"))            // Right(Var(TRUE))
  println(apply("(A && B)"))        // Right(And(Var(A),Var(B)))
  println(apply("((A && B) && C)")) // Right(And(And(Var(A),Var(B)),Var(C)))
  println(apply("!(A && !B)"))      // Right(Not(And(Var(A),Not(Var(B)))))
}

答案 1 :(得分:0)

>>> values = d.values() >>> sorted_values = sorted(values) >>> [sorted_values.index(item) for item in values] [0, 3, 2, 4, 1] - 节点的子节点类型为Not。但是,在第15行中,Bool,您希望传递给formula Not方法的值属于apply类型。您可以通过在冒号后添加类型信息来限制提取器(即Any - 语句)仅匹配case类型formula的值:

Bool

因此,case ( "!" ~ (formula: Bool[_])) 方法如下所示:

not

但是,现在,例如,def not : Parser[_] = NEG ~ formula ^^ {case ( "!" ~ (formula: Bool[_])) => Not(formula)} 不再匹配,因为"!TRUE"尚未属于"TRUE"类型。这可以通过扩展解析器将字符串转换为Bool来修复,例如

Bool