2017-01-17 8 views
0

私はスカラ座でのパーサコンビネータを理解しようとしていて、次のことを書かれている:この単純なregex-parserをブール式をキャッチする方法を教えてください。

import scala.util.parsing.combinator._ 

class SimpleParser extends RegexParsers { 

    def operand: Parser[String] = "[A-Za-z]+".r ^^ {_.toString} 

    def operator: Parser[String] = "OR|AND".r ^^ {_.toString} 

    def term: Parser[String] = (("(" ~> (operand ~ operator ~ operand) <~ ")")) ^^ { 
    case o1 ~ operator ~ o2 => o1 + " " + operator + " " + o2 
    case _ => " " 
    } 


    def expression: Parser[String] = (operand | term | (operand ~ operator ~ term))^^ { 
    case str:String => str 
    case operand ~ operator ~ term => operand + " " + operator + " " + term 
    } 
} 

object ParserTest extends SimpleParser{ 
    def main(args: Array[String]): Unit = { 
    println(parseAll(expression, "A").get) 
    println(parseAll(expression, "(A OR C)").get) 
    println(parseAll(expression, "A AND (A OR C)").get) 
    } 
} 

最後のものが原因としながら、最初の二つのプリントの作品は、見つける:

Exception in thread "main" java.lang.RuntimeException: No result when parsing failed at scala.sys.package$.error(package.scala:27) 
at scala.util.parsing.combinator.Parsers$NoSuccess.get(Parsers.scala:181) 
at scala.util.parsing.combinator.Parsers$NoSuccess.get(Parsers.scala:167) 
at ParserTest$.main(ParserTest.scala:31) 
at ParserTest.main(ParserTest.scala) 

私は最後の文を考えました"expression"の(operand〜operator〜term)パターンと一致します。誰かが私のパターンが間違っている理由を私に説明することができますか?

答えて

2

まず、parseAllの結果を正しく処理していません。あなたがいた場合、あなたはそれがメッセージ

[1.3] failure: end of input expected 

A AND (B OR C) 
^

ここでの問題は、あなたが間違った順序でexpression中にあなたのパーサーを持っているとFailureを返していました、最後の例でこれを参照してくださいね。

パーザの論理和を作成するときは(必ず|)、「greediest」パーサから始める必要があります。言い換えれば、ここで起こっていることは、それ自身が "A"を解析して解析を終了することに成功しているということです。しかし、parseAllは解析が成功したと判断しますが、まだ入力が残っているので、上記のエラーを返します。

、それがどのように見えるので、あなたは、3つのパーサの順序を逆にした場合:

def expression: Parser[String] = ((operand ~ operator ~ term) | term | operand)^^ 

彼らは正しく順序付けされ、すべての3例が働きます。

+0

ありがとうございます。私はそれを問題として考えなかった。 – stian

関連する問題