I'm using ANTLR4 to create a parse tree for my grammar, what I want to do is modify certain nodes in the tree. This will include removing certain nodes and inserting new ones. The purpose behind this is optimization for the language I am writing. I have yet to find a solution to this problem. What would be the best way to go about this?
相关问题
- Correctly parse PDF paragraphs with Python
- R: eval(parse()) error message: cannot ope
- Highlight parent path to the root
- Avoid overlapping of nodes in tree layout in d3.js
- Get path of node in tree
相关文章
- How do I get from a type to the TryParse method?
- In ANTLR, how do you specify a specific number of
- Slow ANTLR4 generated Parser in Python, but fast i
- Parsing JSON in QML [duplicate]
- How do I generate an AST from a string of C++ usin
- Why does the C++ compiler give errors after lines
- JSoup will not fetch all items?
- Content is not allowed in prolog
Another approach would be to write a
ParseTreeVisitor
that converts the tree back to a string. (This can be trivial in some cases, because you are only callingTerminalNode.getText()
and concatenate inaggregateResult(..)
.)You then add the modifications to this visitor so that the resulting string representation contains the modifications you try to achieve.
Then parse the string and you get a parse tree with the desired modifications.
This is certainly hackish in some ways, since you parse the string twice. On the other hand the solution does not rely on antlr implementation details.
While there is currently no real support or tools for tree rewriting, it is very possible to do. It's not even that painful.
The
ParseTreeListener
or yourMyBaseListener
can be used with aParseTreeWalker
to walk your parse tree.From here, you can remove nodes with
ParserRuleContext.removeLastChild()
, however when doing this, you have to watch out forParseTreeWalker.walk
:You must replace removed nodes with something if the walker has visited parents of those nodes, I usually pick empty
ParseRuleContext
objects (this is because of the cached value ofn
in the method above). This prevents theParseTreeWalker
from throwing a NPE.When adding nodes, make sure to set the mutable parent on the
ParseRuleContext
to the new parent. Also, because of the cachedn
in the method above, a good strategy is to detect where the changes need to be before you hit where you want your changes to go in thewalk
, so theParseTreeWalker
will walk over them in the same pass (other wise you might need multiple passes...)Your pseudo code should look like this:
I've used this method to write a transpiler that compiled a synchronous internal language into asynchronous javascript. It was pretty painful.