如何将ANTLR生成的AST转换为源代码

时间:2012-08-01 03:26:12

标签: antlr3

我正在为PL / SQL编写一个简单的解析器和重写器工具,我已经完成了解析器并获得了AST,但现在我遇到了两个问题:

  1. 如何获取AST的某些节点,以便更改它们的值?
  2. 更改节点后,如何从更新的AST重新生成SQL ANTLR AST提供类似的界面吗?
  3. 示例SQL:select a,b from t where a=2

    解析sql后得到ast,我想把sql改成

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

    BTW,我用ANTLR为C生成AST,

    感谢您的任何建议!

2 个答案:

答案 0 :(得分:3)

how to regenerate source code from an AST上查看我的答案。

它比你想象的要多得多。

ANTLR以字符串模板的形式提供了一些帮助,但您可能会发现这些是混合的祝福:虽然它们可以生成代码文本,但它们将精确生成模板中的内容,并且您可能希望根据其重新生成代码原始布局, 字符串模板的布局要覆盖哪些。

答案 1 :(得分:0)

以下代码将遍历AST并将所有AST节点打印到stderr。 相同的树步行器是可以替换树节点的树变换器的基础。

使用以下命令分配新树节点:(pANTLR3_BASE_TREE)(psr-> adaptor-> nilNode(psr-> adapter));

使用以下命令删除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;