Closed andrewdep closed 12 years ago
Parse trees in general reflect the grammar's productions. To transform a parse tree into an AST you can traverse the tree and transform nodes as appropriate. I don't think there's a good automatic way to elide nodes from a tree since you'd need to know about the language's semantics, although declarative approaches (e.g. syntax-directed translation with semantic actions) help out.
If it helps, I was able to visually simplify the tree by:
My apologies I thought I responded to this earlier but for some reason I guess I didn't. James is pretty much spot on, language.js provides a CST (concrete syntax tree), which you can optionally choose to operate on to turn into an AST, so this behavior is "correct" (while understandably perhaps frustrating). The main problem with seemingly correct generic approaches like "flatten all nodes that have one child" is that its very much context dependent on what you're doing with the tree. For example, many
So one approach is what James suggested of mutating the tree yourself or ignoring what you don't care about (I believe this to be the best approach and what I do when I work with this). A more proactive approach would be for me to add some sort of syntax for the language description to mark certain nodes as "throwaway" (or "implementation details"), but then the problem is that once again, every one would want a slightly different subset, so we'd have people modifying the language definition in confusing ways.
I always imagined that the way to "talk" to the tree would be through query selectors (like you are traversing the "DOM" of the syntax file). In this manner, you can ignore the node types you don't care about (pseudo code):
result.select("//*/Class/*/Method[starts-with(contents(),'init')]") // grab all methods that start with init...
There are libraries out there today that let you move through any json (js object) in this manner so there's theoretically nothing preventing this approach right now.
Thanks for the guidance, guys. I've got what I need now. :)
The JavaScript grammar produces parse trees that can be very difficult to work with. Take this simple JavaScript:
It parses to the tree below (output via util.inspect in nodejs). The JavaScript grammar has rules like this:
And so on... so, while 30 is a numeric literal, I end up with all these nested nodes that don't actually exist in that part of the source code (ConditionalExpression -> LogicalOrExpression -> LogicalAndExpression -> BitwiseOrExpression -> and so on) - 30 is not a ConditionalExpression, it's not a LogicalOrExpression, it's not a LogicalAndExpression... you get the idea. I have to either make my code smart enough to ignore these particular types when they are incomplete (which is a pain), or prune them out of my tree (which is also a pain)... and both of those are a performance hit. Surely this is a common issue with peg parsers that has a standard solution? I'm not familiar enough with PEG parsers yet to know the answer, but it would be nice if I had an option to generate a parser that would not add misleading/pointless intermediate elements.