1

誰かが次の動作を理解するのを手伝ってくれますか: parseAll (parseIf, "If bla blablaa")結果はis expected. 代わりに、私は常に取得しstring matching regex 'is\b' expected but 'b' foundます。" If bla is blablaa"(先頭の空白に注意してください)同じ動作になるため、空白と関係があると思います。StandardTokenParsers で試してみたところ、すべてうまくいきました。残念ながら、STP は正規表現をサポートしていません。フォローアップの質問: RegexParsers を変更して、文字のシーケンスではなく文字列のシーケンスを使用するにはどうすればよいですか? これにより、エラー報告がはるかに簡単になります。

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)
4

1 に答える 1

0

この問題は非常に奇妙です。あなたがコール|し、両方が失敗した場合、最後に失敗した側が選択され、左側の側が優先されます。

で直接解析しようとするとgiverRole、期待どおりの結果が得られます。ただし、失敗する前に成功した一致を追加すると、表示されている結果が生成されます。

logその理由はかなり微妙です。すべてのパーサーにステートメントを散りばめただけでわかりました。それを理解するには、 がスペースをスキップする方法RegexParserを理解する必要があります。具体的には、 ではスペースがスキップされacceptます。failureを呼び出さないためaccept、スペースをスキップしません。

の障害は でkwIs発生しbますが、スキップされたスペースとして、 の障害は の後のスペースfailureで発生します。ここ:If

If bla blablaa
   ^ kwIs fails here
  ^ failure fails here

したがって、kwIs前述のルールにより、上のエラー メッセージが優先されます。

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

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

別の解決策は、暗黙的な正規表現の受け入れを使用する代わりにacceptIforを使用acceptMatchすることです。この場合、調整されたエラー メッセージを提供できます。

于 2011-11-12T20:15:47.427 に答える