blob: 76ce6d0f31ff39bc2112a782e10504e1298ca1d8 [file] [log] [blame]
import 'package:meta/meta.dart';
import '../../core/parser.dart';
import '../combinator/optional.dart';
import '../combinator/sequence.dart';
import '../misc/epsilon.dart';
import '../repeater/possessive.dart';
extension SeparatedByParserExtension<T> on Parser<T> {
/// Returns a parser that consumes the receiver one or more times separated
/// by the [separator] parser. The resulting parser returns a flat list of
/// the parse results of the receiver interleaved with the parse result of the
/// separator parser. The type parameter `R` defines the type of the returned
/// list.
///
/// If the optional argument [includeSeparators] is set to `false`, then the
/// separators themselves are not included in the parse result. If the
/// optional argument [optionalSeparatorAtStart] or [optionalSeparatorAtEnd]
/// is set to `true` the parser also accepts optional separators at the start
/// and/or end.
///
/// For example, the parser `digit().separatedBy(char('-'))` returns a parser
/// that consumes input like `'1-2-3'` and returns a list of the elements and
/// separators: `['1', '-', '2', '-', '3']`.
@Deprecated('Use `SeparatedRepeatingParserExtension.plusSeparated` for a '
'better optimized and strongly typed implementation that provides the '
'elements and separators separately')
@useResult
Parser<List<R>> separatedBy<R>(
Parser separator, {
bool includeSeparators = true,
bool optionalSeparatorAtStart = false,
bool optionalSeparatorAtEnd = false,
}) =>
seq4(
optionalSeparatorAtStart
? separator.optional()
: epsilonWith(null),
this,
seq2(separator, this).star(),
optionalSeparatorAtEnd ? separator.optional() : epsilonWith(null))
.map4(
(separatorAtStart, firstElement, otherElements, separatorAtEnd) {
final result = <R>[];
if (includeSeparators &&
optionalSeparatorAtStart &&
separatorAtStart != null) {
result.add(separatorAtStart);
}
result.add(firstElement as R);
for (var tuple in otherElements) {
if (includeSeparators) {
result.add(tuple.first);
}
result.add(tuple.second as R);
}
if (includeSeparators &&
optionalSeparatorAtEnd &&
separatorAtEnd != null) {
result.add(separatorAtEnd);
}
return result;
},
);
}