2016-05-05 43 views
1

嗨,我是斯卡拉的初学者;现在学习Scala解析器组合器,编写“MiniLogicParser”,这是一个用于命题逻辑公式的迷你解析器。我成功解析它的一部分,但不能转换为案例类。我尝试了一些代码类似下面,斯卡拉分析器与recusive结构的组合器

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行,发生类型不匹配。但是,我不明白如何解决这个错误。

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

回答

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))))) 
} 
0

Not -node的孩子的类型是Bool。然而,在第15行中,您想要传递给Notapply方法的值为formula,其类型为Any。可以限制提取(即,case语句来),以通过一个冒号之后加入的类型的信息是Bool类型的formula仅匹配值:

case ("!" ~ (formula: Bool[_])) 

因此,not方法是这样的:

def not : Parser[_] = NEG ~ formula ^^ {case ("!" ~ (formula: Bool[_])) => Not(formula)} 

不过,现在,例如,"!TRUE"不匹配了,因为"TRUE"尚未Bool类型。这可以通过你的解析器将字符串转换例如延伸到Bool,是固定的,

def TRUE = "TRUE" ^^ (_ => True)