blob: 0276452c5f64b7510024e7737a8708151c9f7500 [file] [log] [blame] [edit]
import 'package:meta/meta.dart';
import '../core/parser.dart';
import 'iterable.dart';
/// A function transforming one parser to another one.
typedef TransformationHandler = Parser<T> Function<T>(Parser<T> 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.
@useResult
Parser<T> transformParser<T>(Parser<T> parser, TransformationHandler handler) {
final mapping = Map<Parser, Parser>.identity();
for (final each in allParser(parser)) {
mapping[each] = each.copy().captureResultGeneric(handler);
}
final todo = [...mapping.values];
final seen = {...mapping.values};
while (todo.isNotEmpty) {
final parent = todo.removeLast();
for (final child in parent.children) {
if (mapping.containsKey(child)) {
parent.replace(child, mapping[child]!);
} else if (seen.add(child)) {
todo.add(child);
}
}
}
return mapping[parser]! as Parser<T>;
}