2016-05-05 11 views
1

こんにちは、私はScalaの初心者です。命題論理式のためのミニパーサである "MiniLogicParser"を書くScalaパーサーコンビネータを学ぶ。私は部分的にそれを解析するのに成功していますが、ケースクラスに変換することはできません。私はコンパイルがスカラパーサーコンビネータと再構成構造

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

は、私は一部のエラーメッセージを理解することができ、次のエラーメッセージで失敗し、以下のように

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

をいくつかのコードを試みたが、つまり、パース結果をcaseクラスに変換しようとした行15のために、型の不一致が発生しているということです。しかし、私はこのエラーを修正する方法を理解していません。

誰かが私にこれについてのヒントを教えてくれてうれしいです。

答えて

1

Boolに文字列を変換するために、あなたのパーサを拡張することによって固定することができ、私はあなたのパーサを少し適応してきました。

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行目のformulaの場合、Notapplyメソッドに渡す値はAnyです。あなたは、コロンの後に型情報を追加することにより、タイプBoolであるformulaの唯一のマッチ値を抽出(すなわち、case -statement)を制限することができます:

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

したがって、not方法は次のようになります。 "TRUE"は、まだタイプBoolのではありませんので、

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

しかし、今、例えば、"!TRUE"は、もはや一致しません。これは、例えば、

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