我正在为PL / SQL编写一个简单的解析器和重写器工具,我已经完成了解析器并获得了AST,但现在我遇到了两个问题:
示例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,
感谢您的任何建议!
答案 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;