blob: 5956e8646458956852bb192457395da755e19f44 [file] [log] [blame]
import 'package:meta/meta.dart';
import '../../context/context.dart';
import '../../context/result.dart';
import '../../core/parser.dart';
import '../utils/sequential.dart';
import 'list.dart';
export 'generated/sequence_2.dart';
export 'generated/sequence_3.dart';
export 'generated/sequence_4.dart';
export 'generated/sequence_5.dart';
export 'generated/sequence_6.dart';
export 'generated/sequence_7.dart';
export 'generated/sequence_8.dart';
export 'generated/sequence_9.dart';
extension SequenceParserExtension on Parser {
/// Returns a parser that accepts the receiver followed by [other]. The
/// resulting parser returns a list of the parse result of the receiver
/// followed by the parse result of [other]. Calling this method on an
/// existing sequence code does not nest this sequence into a new one, but
/// instead augments the existing sequence with [other].
///
/// For example, the parser `letter().seq(digit()).seq(letter())` accepts a
/// letter followed by a digit and another letter. The parse result of the
/// input string `'a1b'` is the list `['a', '1', 'b']`.
@useResult
Parser<List> seq(Parser other) => this is SequenceParser
? SequenceParser([...children, other])
: SequenceParser([this, other]);
/// Convenience operator returning a parser that accepts the receiver followed
/// by [other]. See [seq] for details.
@useResult
Parser<List> operator &(Parser other) => seq(other);
}
extension SequenceIterableExtension<R> on Iterable<Parser<R>> {
/// Converts the parser in this iterable to a sequence of parsers.
Parser<List<R>> toSequenceParser() => SequenceParser<R>(this);
}
/// A parser that parses a sequence of parsers.
class SequenceParser<R> extends ListParser<R, List<R>>
implements SequentialParser {
SequenceParser(super.children);
@override
Result<List<R>> parseOn(Context context) {
var current = context;
final elements = <R>[];
for (var i = 0; i < children.length; i++) {
final result = children[i].parseOn(current);
if (result.isFailure) {
return result.failure(result.message);
}
elements.add(result.value);
current = result;
}
return current.success(elements);
}
@override
int fastParseOn(String buffer, int position) {
for (var i = 0; i < children.length; i++) {
position = children[i].fastParseOn(buffer, position);
if (position < 0) {
return position;
}
}
return position;
}
@override
SequenceParser<R> copy() => SequenceParser<R>(children);
}