blob: 1e5648da246e9afff68913df2eefb0a01c16d68f [file] [log] [blame]
part of petitparser.reflection;
/// A function transforming one parser to another one.
typedef Parser TransformationHandler(Parser parser);
/// Transforms all parsers reachable from [parser] with the given [handler].
/// The identity function returns a copy of the the incoming parser.
///
/// The implementation first creates a copy of each parser reachable in the
/// input grammar; then the resulting grammar is traversed until all references
/// to old parsers are replaced with the transformed ones.
Parser transformParser(Parser parser, TransformationHandler handler) {
Map<Parser, Parser> mapping = new Map.identity();
for (var each in allParser(parser)) {
mapping[each] = handler(each.copy());
}
Set<Parser> seen = new Set.from(mapping.values);
List<Parser> todo = new List.from(mapping.values);
while (todo.isNotEmpty) {
var parent = todo.removeLast();
for (var child in parent.children) {
if (mapping.containsKey(child)) {
parent.replace(child, mapping[child]);
} else if (!seen.contains(child)) {
seen.add(child);
todo.add(child);
}
}
}
return mapping[parser];
}