7

Scalaパーサーコンビネーターに基づいてパーサーをコーディングしました。

class SxmlParser extends RegexParsers with ImplicitConversions with PackratParsers {
    [...]
    lazy val document: PackratParser[AstNodeDocument] =
        ((procinst | element | comment | cdata | whitespace | text)*) ^^ {
            AstNodeDocument(_)
        }
    [...]
}
object SxmlParser {
    def parse(text: String): AstNodeDocument = {
        var ast = AstNodeDocument()
        val parser = new SxmlParser()
        val result = parser.parseAll(parser.document, new CharArrayReader(text.toArray))
        result match {
            case parser.Success(x, _) => ast = x
            case parser.NoSuccess(err, next) => {
                tool.die("failed to parse SXML input " +
                    "(line " + next.pos.line + ", column " + next.pos.column + "):\n" +
                    err + "\n" +
                    next.pos.longString)
            }
        }
        ast
    }
}

通常、結果の解析エラーメッセージはかなり良いものです。しかし時々それはちょうどになります

sxml: ERROR: failed to parse SXML input (line 32, column 1):
`"' expected but `' found
^

これは、引用符が閉じられておらず、パーサーがEOTに到達した場合に発生します。ここで見たいのは、(1)パーサーが「」を期待したときにパーサーがどのようなプロダクションであったか(複数あります)、および(2)入力のどこでこのプロダクションが解析を開始したか(これは、開始引用符が入力にあります)エラーメッセージを改善し、エラーが発生したときの実際の内部解析状態に関する詳細情報を含める方法を知っている人はいますか(おそらく、本番ルールのスタックトレースなど、より適切に識別するためにここで合理的に指定できるもの)エラーの場所)ところで、上記の「行32、列1」は実際にはEOT位置であるため、もちろんここでは役に立ちません。

4

2 に答える 2

3

(1) の対処法はまだわかりませんが、(2) も探していたときにこの Web ページを見つけました。

https://wiki.scala-lang.org/plugins/viewsource/viewpagesrc.action?pageId=917624

私はちょうど情報をコピーしています:

重要なトークンの入力位置 (行番号と列番号) を記録することは、便利な拡張機能です。これを行うには、次の 3 つのことを行う必要があります。

  • 各出力タイプを拡張する scala.util.parsing.input.Positional
  • Parsers.positioned() コンビネータを呼び出す
  • 行と列の位置を記録するテキスト ソースを使用する

最後に、ソースが位置を追跡していることを確認します。ストリームの場合は、単純に scala.util.parsing.input.StreamReader; を使用できます。文字列の場合は、scala.util.parsing.input.CharArrayReader を使用します。

私は現在それで遊んでいるので、後で簡単な例を追加しようとします

于 2010-06-25T13:19:17.840 に答える
1

このような場合、エラーに一致するように特別に設計されたプロダクション ルールを使用してerrfailureを使用できます。~!

于 2010-05-25T22:25:14.863 に答える