Ivan
Ivan

Reputation: 41

How to translate the AST generated by ANTLR to its source code

I am writing an simple parser&rewriter tools for PL/SQL, and I've complete the parser and get the AST,but now I got two problems :

  1. How can I get certain nodes of the AST ,so as to change the value of them?
  2. After change the nodes ,how can i regenerate the SQL from the updated AST does the ANTLR AST provide similar interface to do this?

Example SQL: select a,b from t where a=2

After parser the sql and get the ast, I want to change the sql into

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

BTW, I generate the AST for C with ANTLR,

Thank you for any suggestion!

Upvotes: 4

Views: 1241

Answers (2)

user2074928
user2074928

Reputation: 51

The following code will walk the AST and print all AST nodes to stderr. The same tree walker is the basis for a tree transformer that can replace tree nodes.

Allocate new tree nodes with: (pANTLR3_BASE_TREE)(psr->adaptor->nilNode(psr->adaptor));

Delete AST nodes with: parentASTnode->deleteChild(parentASTnode, nodeIndex); [deleteChild does not free the deleted nodes]

Replace nodes with: parentASTnode->replaceChildren(parentASTnode, nStartChildIndex, nStopChildIndex, newASTnode); [you cannot insert nodes in the middle of an AST tree level, you can only replace nodes or add to the end of the parent nodes child list]

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;

Upvotes: 0

Ira Baxter
Ira Baxter

Reputation: 95334

See my SO answer on how to regenerate source code from an AST.

Its a lot more work than you think.

ANTLR provides some help in the form of string templates but you may find these a mixed blessing: while they can generate code text, they will generate precisely what is in the template, and you may want to regenerate the code according to its original layout, which the layout of the string template wants to override.

Upvotes: 3

Related Questions