0

左再帰構文解析規則を使用する C# ターゲットを使用して ANTLR v4 の文法を作成しましたが、これらの規則を使用するサンプル コードを構文解析しようとするたびに、構文解析エンジンが間違った規則を選択します。

解析規則:

expr
    : expr COR term
    | expr CAND term
    | term
    ;

解析しようとしているコード:

...
print("Testing Program p00csx\n");
...

解析エンジンからの情報を使用する訪問者:

public override Int32 VisitExpr(CSXParser.ExprContext context)
    {
        if (context == null) return 0;
        switch (context.altNum)
        {
            case 1: //expr COR term
                VisitExpr(context.expr());
                Console.Write(context.COR());
                VisitTerm(context.term());
                break;
            case 2: //expr CAND term
                VisitExpr(context.expr());
                Console.Write(context.CAND());
                VisitTerm(context.term());
                break;
            case 3: //term
                VisitTerm(context.term());
                break;
        }
        return 0;
    }

この例では、print() の呼び出し内の文字列リテラルは「expr」に解決され、「term」などに解決され、「stringLit」が得られます。これは、上記の例のケース 3 です。ただし、代わりに、プログラムのテキストに COR ('||') がなくても、パーサーはケース 1 を選択しています。

ANTLR サイトによると、v4 はこれらのような左再帰式を処理できるため、何か間違ったことをしているに違いないと思います。私はANTLRを初めて使用しますが、おそらく問題は私が見落としていた単純なものです。どんな助けでも大歓迎です。私はドキュメントを読み、デバッガーを数日間実行しており、これを理解しようとしています。

ありがとう!

4

2 に答える 2

2

ParserRuleContext.altNum次の理由により、フィールドの使用を避ける必要があります。

  • 左再帰ルール用に初期化されることはないため、信頼性が低くなります。
  • それはメモリの膨大な浪費であり、削除したいと考えています。
  • 他のシナリオでの精度や使いやすさを検証するためのテストは実行していません。

代わりに、次のいずれかを試してください。

  1. context.expr()null を返すかどうかを最初にチェックして、代替案をテストします。もしそうなら、あなたはterm. Ifexpr()が null 以外を返す場合は、どちらが null 以外を返すcontext.COR()context.CAND()を調べて、使用された実際の演算子を特定できます。

  2. このように、最も外側の選択肢にラベルを付けます

    expr
        : expr COR term  # orExpr
        | expr CAND term # andExpr
        | term           # termExpr
        ;
    
于 2013-06-18T13:56:33.830 に答える
-1

左再帰をまったく削除することをお勧めします。

expr
scope
{
    LogicOperator op;
}
        : expr ((COR {expr.op = LogicOperator.Or;} | CAND {expr.op = LogicOperator.And;}) exp)*
        | term
        ;

ps論理演算子と優先順位を使用したANTLR3 文法

于 2013-06-18T13:54:21.460 に答える