2012-08-01 15 views
3

我寫一個簡單的解析器&重寫工具PL/SQL的AST,我已經完成了解析器,並獲得AST,但現在我有兩個問題:如何翻譯由ANTLR產生它的源代碼

  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); 

BTW,我產生了AST與ANTLR C,

謝謝你的任何建議!

+0

「我生成與ANTLR C中的AST ... 「?這與PLSQL樹有什麼關係,或者你只是告訴你設法做了兩次? – 2012-08-01 04:02:49

+0

@IraBaxter:沒有說清楚,我使用ANTLR從grammer文件生成C目標,因爲我想在另一個C程序中使用這個解析器和重寫工具 – Ivan 2012-08-01 05:13:42

回答

3

見我上how to regenerate source code from an AST SO回答。

它比你想象的要多得多。

ANTLR以字符串模板的形式提供了一些幫助,但您可能會發現這些混合祝福:雖然它們可以生成代碼文本,但它們將精確地生成模板中的內容,並且您可能希望根據它的原始佈局 其中字符串模板的佈局想要覆蓋。

0

下面的代碼將走AST和打印所有AST節點的標準錯誤。 同樣的樹步行者是可以替換樹節點的樹變換器的基礎。

分配新樹節點與:(pANTLR3_BASE_TREE)(PSR->的接頭> nilNode(PSR->適配器));

刪除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;