4

PL/SQL 用の単純なパーサーとリライター ツールを作成しています。パーサーを完成させて AST を取得しましたが、次の 2 つの問題が発生しました。

  1. AST の特定のノードを取得して、それらの値を変更するにはどうすればよいですか?
  2. ノードを変更した後、更新された AST から SQL を再生成するにはどうすればよいですか? ANTLR AST はこれを行うための同様のインターフェイスを提供しますか?

SQL の例:select a,b from t where a=2

SQLをパーサーしてastを取得した後、SQLを次のように変更したい

select fun(a),b from t where a = fun1(2);

ところで、ANTLR を使用して C の AST を生成します。

ご提案ありがとうございます。

4

2 に答える 2

3

AST からソース コードを再生成する方法については、SO の回答を参照してください。

あなたが思っているよりもずっと多くの仕事です。

ANTLR は文字列テンプレートの形式でいくつかのヘルプを提供しますが、これらはさまざまな利点があることに気付くかもしれません: コード テキストを生成できますが、テンプレートにあるものを正確に生成し、元のレイアウトに従ってコードを再生成したい場合があります。文字列テンプレートのレイアウトがオーバーライドしたいもの。

于 2012-08-01T04:01:46.043 に答える
0

次のコードは、AST をウォークし、すべての AST ノードを stderr に出力します。同じツリー ウォーカーが、ツリー ノードを置き換えることができるツリー トランスフォーマーの基礎となります。

新しいツリー ノードを割り当てます: (pANTLR3_BASE_TREE)(psr->adaptor->nilNode(psr->adaptor));

次の方法で AST ノードを削除します。parentASTnode->deleteChild(parentASTnode, nodeIndex); [deleteChild は削除されたノードを解放しません]

ノードを次のように置き換えます。parentASTnode->replaceChildren(parentASTnode, nStartChildIndex, nStopChildIndex, newASTnode); [ASTツリーレベルの途中にノードを挿入することはできません。ノードを置き換えるか、親ノードの子リストの最後に追加することしかできません]

void  printTree(pANTLR3_BASE_TREE t, int indent) 
{
    pANTLR3_BASE_TREE child = NULL;
    int     children = 0;
    char *  tokenText = NULL;
    string  ind = "";
    int     i = 0;

    if ( t != NULL ) 
      {
        children = t->getChildCount(t);
        for ( i = 0; i < indent; i++ )
          ind += "   ";

        for ( i = 0; i < children; i++ )
          {
            child = (pANTLR3_BASE_TREE)(t->getChild(t, i));
            tokenText = (char *)child->toString(child)->chars;
            fprintf(stderr, "%s%s\n", ind.c_str(), tokenText);
            if (tokenText == "<EOF>")
              break;
            printTree(child, indent+1);
          }
      }
}


// Run the parser
pANTLR3_BASE_TREE langAST = (psr->start_rule(psr)).tree; 

// Print the AST
printTree(langAST, 0);

// Get the Parser Errors
int nErrors = psr->pParser->rec->state->errorCount;
于 2013-03-22T20:17:06.533 に答える