The docs for Node only mention following methods:
Equal
, GreaterThan
, GreaterThanOrEqual
, LessThan
, LessThanOrEqual
, NotEqual
, Slice
, Subscription
It does mention how to access child by index using Subscription
, but how can I find out the count of children node has to iterate over them?
Here is my use case:
Exp parsed = parse(#Exp, "2+(4+3)*48");
println("the number of root children is: " + size(parsed));
But it yields error, as size()
seems to only work with a List
.
Different answers, different aspects that are better or worse. Here are a few:
import ParseTree;
int getChildrenCount1(Tree parsed) {
return (0 | it + 1 | _ <- parsed.args);
}
getChildrenCount1
iterates over the raw children of a parse tree node. This includes whitespace and comment nodes (layout
) and keywords (literals
). You might want to filter for those, or compensate by division.
On the other hand, this seems a bit indirect. We could also just directly ask for the length of the children list:
import List;
import ParseTree;
int getChildrenCount2(Tree parsed) {
return size(parsed.args) / 2 + 1; // here we divide by two assuming every other node is a layout node
}
There is also the way of meta-data. Every parse tree node has a declarative description of the production directly there which can be queried and explored:
import ParseTree;
import List;
// immediately match on the meta-structure of a parse node:
int getChildrenCount3(appl(Production prod, list[Tree] args)) {
return size(prod.symbols);
}
This length of symbols should be the same as the length of args.
// To filter for "meaningful" children in a declarative way:
int getChildrenCount4(appl(prod(_, list[Symbol] symbols, _), list[Tree] args)) {
return (0 | it + 1 | sort(_) <- symbols);
}
The sort
filters for context-free non-terminals as declared with syntax
rules. Lexical children would match lex
and layout and literals with layouts
and lit
.
Without all that pattern matching:
int getChildrenCount4(Tree tree) {
return (0 | it + 1 | s <- tree.prod.symbols, isInteresting(s));
}
bool isInteresting(Symbol s) = s is sort || s is lex;