2

C ターゲットでツリー文法を使用する antlr3 についていくつか質問があります。

インタープリター (関数、変数、ブール式、数学式は問題ありません) をほぼ完成させ、最後に最も難しいステートメント (if、switch など) を保持しました。

1) 単純なループ文を解釈したい:

repeat: ^(REPEAT DIGIT stmt);

私は多くの例を見てきましたが、ツリー ウォーカーについては何も見ていません (マクロ MARK() / REWIND(m) + @init / @after を含むトピックのみがここにありますが、機能していません (antlr エラーがあります: "unexpected node at offset 0 "))。Cでこのステートメントをどのように解釈できますか?

2) 単純な if ステートメントを使用した同じ質問:

if: ^(IF condition stmt elseifstmt* elsestmt?);

問題は、条件が false の場合にステートメントをスキップし、他の elseif/else ステートメントをテストすることです。

3) スクリプトを停止できるステートメントがいくつかあります (「break」や「exit」など)。ツリー ウォーカーを中断して次のトークンをスキップするにはどうすればよいですか?

4) レクサーまたはパーサーのエラーが検出されると、antlr はエラーを返します。しかし、自家製のエラーメッセージを作成したいと思います。パーサーがクラッシュした行番号を取得するにはどうすればよいですか?

詳細が必要な場合はお尋ねください。

どうもありがとうございました(そして私の下手な英語をお詫びします)

4

1 に答える 1

0

繰り返しステートメントについては、それを行う方法を見つけたと思います。antlr.org で、Java で作成された C 言語用の完全なインタープリターを見つけました。

ここに while ステートメントを入れます (少し異なりますが、方法は同じです)。

whileStmt
scope{
    Boolean breaked;
}
@after{
    CommonTree stmtNode=(CommonTree)$whileStmt.start.getChild(1);
    CommonTree exprNode=(CommonTree)$whileStmt.start.getChild(0);

    int test;

    $whileStmt::breaked=false;
    while($whileStmt::breaked==false){
            stream.push(stream.getNodeIndex(exprNode));
            test=expr().value;
            stream.pop();
            if (test==0) break;
            stream.push(stream.getNodeIndex(stmtNode));
            stmt();
            stream.pop();
        }

}
    : ^(WHILE . .)
    ;

このコードを C 言語に変換しようとしました。

repeat 
scope {
    int breaked;
    int tours;
}
@after
{
    int test;

    pANTLR3_BASE_TREE repeatstmt = (pANTLR3_BASE_TREE)$repeat.start->getChild($repeat.start,1);
    pANTLR3_BASE_TREE exprstmt = (pANTLR3_BASE_TREE)$repeat.start->getChild($repeat.start,0);

    $repeat::breaked = 0;
    test = 1;

    while($repeat::breaked == 0)
    {
        TW_FOLLOWPUSH(exprstmt);
        TW_FOLLOWPOP();
        test++;
        if(test == $repeat::tours)
            break;
        TW_FOLLOWPUSH(repeatstmt);
        CTX->repeat(CTX);
        TW_FOLLOWPOP();
    }   
}
    :   ^(REPEAT DIGIT stmt)
        {           
            $repeat::tours = $DIGIT.text->toInt32($DIGIT.text);
        }

しかし、何も起こりませんでした (stmt は 1 回だけ解析されます)。

これについて何か考えはありますか?

自家製のエラー メッセージについては、レクサーでマクロ GETLINE() を見つけました。ツリー ウォーカーがクラッシュしたときに機能しますが、antlr はレクサーまたはパーサー エラーのエラー メッセージを表示し続けます。

ありがとう。

于 2010-05-27T09:09:22.417 に答える