3

expression IS NULLSQL に似た言語のパーサーを開発していますが、次のような言語のルールをいくつか作成するという問題がありますexpression IN (expression1, expression2, ...)

GitHub テスト プロジェクトhttps://github.com/anpv/SpracheTest/をアップロードしましたが、このバリアントは良くありません。
次のルールを使用しようとしました。

private static readonly Parser<AstNode> InOperator =
    from expr in Parse.Ref(() => Expression)
    from inKeyword in Parse.IgnoreCase("in").Token()
    from values in Parse
        .Ref(() => Expression)
        .DelimitedBy(Comma)
        .Contained(OpenParenthesis, CloseParenthesis)
    select new InOperator(expr, values);

private static readonly Parser<AstNode> IsNullOperator =
    from expr in Parse.Ref(() => Expression)
    from isNullKeyword in Parse
         .IgnoreCase("is")
         .Then(_ => Parse.WhiteSpace.AtLeastOnce())
         .Then(_ => Parse.IgnoreCase("null"))
    select new IsNullOperator(expr);

private static readonly Parser<AstNode> Equality =
    Parse
        .ChainOperator(Eq, IsNullOperator.Or(InOperator).Or(Additive), MakeBinary);

またはParseExceptionのようなコードをスローします。ScriptParser.ParseExpression("1 is null")ScriptParser.ParseExpression("1 in (1, 2, 3)"): "Parsing failure: Left recursion in the grammar."

Expression を先読みするにはどうすればよいですか、またはこの問題を解決するための他のバリアントは存在しますか?

4

1 に答える 1

7

その答えは、残念ながら、Sprache は左再帰文法を解析できないということです。この質問を調査しているときに、左再帰文法のバグのあるサポートがどのように削除されたかについて話しているソースコードのコメントに出くわしました(これは、質問を見つけた方法でもありました)-ソースコードを参照してください。

この問題に対処するには、構文解析の方法を再編成する必要があります。たとえば、単純な式パーサーを作成している場合、これは対処しなければならない一般的な問題です。Web を検索すると、特に式の文法から左再帰を削除する方法について多くの議論があります。

あなたの場合、次のようなことをする必要があると思います:

term := everything simple in an expression (like "1", "2", "3", etc.)
expression := term [ IN ( expression*) | IS NULL | "+" expression | "-" expression | etc.]

または同様の-基本的に-再帰を自分で巻き戻す必要があります。そうすることで、表現に関する問題を修正することができました。基本的なコンパイラの本には、おそらく文法を「正規化」する方法に関するセクションがあると思います。

パーサーから返されるオブジェクトを構築するのは少し面倒ですが、「select new Expression(arg1, arg2)」を実行する代わりにselectステートメントで関数呼び出しに変更し、関数が決定します引数の内容に応じて返される特定のオブジェクト。

于 2013-11-24T22:10:30.083 に答える