2011-11-12 8 views
1

誰かが私に次のような動作を理解させる助けになるかもしれません: parseAll (parseIf, "If bla blablaa")is expectedになります。代わりに私はいつもstring matching regex 'is\b' expected but 'b' foundを得る。 " If bla is blablaa"(最初は空白に気付く)が同じ振る舞いをするので、空白と何か関係があると思います。私はStandardTokenParsersで試してみました。しかし、STPは残念ながら正規表現をサポートしていません。 フォローアップの質問:文字列の代わりに文字列のシーケンスを使用するようにRegexParserを変更する必要がありますか?そうすれば、エラー報告がもっと簡単になります。RegexParserのカスタムエラー

lazy val parseIf = roleGiverIf ~ giverRole 

lazy val roleGiverIf = 
    kwIf ~> identifier | failure("""A rule must begin with if""") 
lazy val giverRole = 
    kwIs ~> identifier | failure("""is expected""") 

lazy val keyword = 
    kwIf | kwAnd | kwThen | kwOf | kwIs | kwFrom | kwTo 

lazy val identifier = 
    not(keyword) ~ roleEntityLiteral 
// ... 

def roleEntityLiteral: Parser[String] = 
    """([^"\p{Cntrl}\\]|\\[\\/bfnrt]|\\u[a-fA-F0-9]{4})\S*""".r 
def kwIf: Parser[String] = "If\\b".r 
def kwIs: Parser[String] = "is\\b".r 

// ... 

parseAll(parseIf, "If bla blablaa") match { 
    case Success(parseIf, _) => println(parseIf) 
    case Failure(msg, _) => println("Failure: " + msg) 
    case Error(msg, _) => println("Error: " + msg) 

答えて

0

この問題は非常に奇妙です。 |に電話して両側に障害が発生すると、障害が発生した側が最後にが選択され、左側の方が優先されます。

giverRoleで直接解析しようとすると、期待する結果が得られます。しかし、失敗の前にマッチを成功させると、それはあなたが見ている結果を生み出します。

理由はやや微妙です - 私はすべてのパーサーにlog文を振りかけるだけで見つけました。それを理解するには、を理解する必要がありますRegexParserは、スキップスペースです。具体的には、スペースはスキップされますacceptに。 failureacceptを呼び出さないため、スペースをスキップしません。

スキップ、failureの故障がIfの後にスペースにを起こるようkwIsの失敗はスペースとして、bに起こりますが。ここで:

If bla blablaa 
^kwIs fails here 
^failure fails here 

したがって、kwIsのエラーメッセージは、私が言及したルールによって優先されます。

この問題は、パーサーが何も照合せずにスペースをスキップするようにすることで回避できます。このパターンが常に一致することが重要です。そうしないと、さらに紛らわしいエラーメッセージが表示されます。ここで私は作品を考える提案があります:

"\\b|$".r ~ failure("is expected") 

別の解決策は、その場合、あなたは仕立てのエラーメッセージを提供することができ、受け入れる暗黙の正規表現を使用するのではなくacceptIfまたはacceptMatchを使用することです。

+0

私は正規表現と字句解析能力を持つパーサーを作成し、あなたが示唆するようにacceptIfを使用しました。しかし、上記の例は期待どおりに動作しないというのはまだ変です。あなたの助けをありがとう – awertos

+0

@awertos私は最終的に問題が何かを知った。最初の解決策は、私が思ったよりも適切でした。私は、エラーを適切な場所に表示するように変更しました。スペース以外の文字を消費しないようにしました。 –

関連する問題