Updated combinator
This commit is contained in:
parent
082b7876b4
commit
26d9936a3f
26 changed files with 85 additions and 69 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
# 2.0.2
|
||||||
|
* Resolve static analysis warnings
|
||||||
|
|
||||||
# 2.0.1
|
# 2.0.1
|
||||||
* Updated README
|
* Updated README
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# angel3_combinator
|
# angel3_combinator
|
||||||
[![version](https://img.shields.io/badge/pub-v2.0.1-brightgreen)](https://pub.dartlang.org/packages/angel3_combinator)
|
[![version](https://img.shields.io/badge/pub-v2.0.2-brightgreen)](https://pub.dartlang.org/packages/angel3_combinator)
|
||||||
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
||||||
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
include: package:pedantic/analysis_options.yaml
|
||||||
analyzer:
|
analyzer:
|
||||||
strong-mode:
|
strong-mode:
|
||||||
implicit-casts: false
|
implicit-casts: false
|
||||||
|
|
|
@ -49,7 +49,8 @@ void main() {
|
||||||
print(error.toolString);
|
print(error.toolString);
|
||||||
print(error.span!.highlight(color: true));
|
print(error.span!.highlight(color: true));
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
print(result.value);
|
print(result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,8 @@ void main() {
|
||||||
stderr.writeln(error.toolString);
|
stderr.writeln(error.toolString);
|
||||||
stderr.writeln(error.span!.highlight(color: true));
|
stderr.writeln(error.span!.highlight(color: true));
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
print(result.value);
|
print(result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ final Parser<String> id =
|
||||||
// pattern.
|
// pattern.
|
||||||
//
|
//
|
||||||
// This is useful for parsing arrays or map literals.
|
// This is useful for parsing arrays or map literals.
|
||||||
main() {
|
void main() {
|
||||||
while (true) {
|
while (true) {
|
||||||
stdout.write('Enter a string (ex "a,b,c"): ');
|
stdout.write('Enter a string (ex "a,b,c"): ');
|
||||||
var line = stdin.readLineSync()!;
|
var line = stdin.readLineSync()!;
|
||||||
|
@ -22,7 +22,8 @@ main() {
|
||||||
print(error.toolString);
|
print(error.toolString);
|
||||||
print(error.span!.highlight(color: true));
|
print(error.span!.highlight(color: true));
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
print(result.value);
|
print(result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ Parser jsonGrammar() {
|
||||||
return expr.foldErrors();
|
return expr.foldErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
void main() {
|
||||||
var JSON = jsonGrammar();
|
var JSON = jsonGrammar();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -64,7 +64,8 @@ main() {
|
||||||
print(error.toolString);
|
print(error.toolString);
|
||||||
print(error.span!.highlight(color: true));
|
print(error.span!.highlight(color: true));
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
print(result.value);
|
print(result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ final Parser number = //
|
||||||
(minus.opt() & decimal) // minus?, decimal
|
(minus.opt() & decimal) // minus?, decimal
|
||||||
.map<num>((r) => num.parse(r.span!.text));
|
.map<num>((r) => num.parse(r.span!.text));
|
||||||
|
|
||||||
main() {
|
void main() {
|
||||||
while (true) {
|
while (true) {
|
||||||
stdout.write('Enter a number: ');
|
stdout.write('Enter a number: ');
|
||||||
var line = stdin.readLineSync()!;
|
var line = stdin.readLineSync()!;
|
||||||
|
@ -31,7 +31,8 @@ main() {
|
||||||
stderr.writeln(error.toolString);
|
stderr.writeln(error.toolString);
|
||||||
stderr.writeln(error.span!.highlight(color: true));
|
stderr.writeln(error.span!.highlight(color: true));
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
print(result.value);
|
print(result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ final Parser pairs = pair
|
||||||
|
|
||||||
final Parser queryString = pairs.opt();
|
final Parser queryString = pairs.opt();
|
||||||
|
|
||||||
main() {
|
void main() {
|
||||||
while (true) {
|
while (true) {
|
||||||
stdout.write('Enter a query string: ');
|
stdout.write('Enter a query string: ');
|
||||||
var line = stdin.readLineSync()!;
|
var line = stdin.readLineSync()!;
|
||||||
|
@ -38,7 +38,8 @@ main() {
|
||||||
print(error.toolString);
|
print(error.toolString);
|
||||||
print(error.span!.highlight(color: true));
|
print(error.span!.highlight(color: true));
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
print(result.value);
|
print(result.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,12 +45,13 @@ void main() {
|
||||||
|
|
||||||
while (q.isNotEmpty) {
|
while (q.isNotEmpty) {
|
||||||
var current = q.removeFirst();
|
var current = q.removeFirst();
|
||||||
if (current is! Tuple2)
|
if (current is! Tuple2) {
|
||||||
out.insert(0, current);
|
out.insert(0, current);
|
||||||
else {
|
} else {
|
||||||
var args = [];
|
var args = [];
|
||||||
for (int i = 0; i < (current.item1 as num); i++)
|
for (var i = 0; i < (current.item1 as num); i++) {
|
||||||
args.add(out.removeLast());
|
args.add(out.removeLast());
|
||||||
|
}
|
||||||
out.add(current.item2(args));
|
out.add(current.item2(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ part of lex.src.combinator;
|
||||||
/// You can provide a custom [errorMessage]. You can set it to `false` to not
|
/// You can provide a custom [errorMessage]. You can set it to `false` to not
|
||||||
/// generate any error at all.
|
/// generate any error at all.
|
||||||
Parser<T> any<T>(Iterable<Parser<T>> parsers,
|
Parser<T> any<T>(Iterable<Parser<T>> parsers,
|
||||||
{bool backtrack: true, errorMessage, SyntaxErrorSeverity? severity}) {
|
{bool backtrack = true, errorMessage, SyntaxErrorSeverity? severity}) {
|
||||||
return _Any(parsers, backtrack != false, errorMessage,
|
return _Any(parsers, backtrack != false, errorMessage,
|
||||||
severity ?? SyntaxErrorSeverity.error);
|
severity ?? SyntaxErrorSeverity.error);
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,14 @@ class _Any<T> extends Parser<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
var errors = <SyntaxError>[];
|
var errors = <SyntaxError>[];
|
||||||
int replay = args.scanner.position;
|
var replay = args.scanner.position;
|
||||||
|
|
||||||
for (var parser in inactive) {
|
for (var parser in inactive) {
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (result.successful)
|
if (result.successful) {
|
||||||
return result;
|
return result;
|
||||||
else {
|
} else {
|
||||||
if (backtrack) args.scanner.position = replay;
|
if (backtrack) args.scanner.position = replay;
|
||||||
if (parser is _Alt) errors.addAll(result.errors);
|
if (parser is _Alt) errors.addAll(result.errors);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ class _Any<T> extends Parser<T> {
|
||||||
@override
|
@override
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
// Never called
|
// Never called
|
||||||
throw ArgumentError("[Combinator] Invalid method call");
|
throw ArgumentError('[Combinator] Invalid method call');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -68,7 +68,7 @@ class _Any<T> extends Parser<T> {
|
||||||
buffer
|
buffer
|
||||||
..writeln('any(${parsers.length}) (')
|
..writeln('any(${parsers.length}) (')
|
||||||
..indent();
|
..indent();
|
||||||
int i = 1;
|
var i = 1;
|
||||||
|
|
||||||
for (var parser in parsers) {
|
for (var parser in parsers) {
|
||||||
buffer
|
buffer
|
||||||
|
|
|
@ -4,7 +4,7 @@ part of lex.src.combinator;
|
||||||
///
|
///
|
||||||
/// If [failFast] is `true` (default), then the first failure to parse will abort the parse.
|
/// If [failFast] is `true` (default), then the first failure to parse will abort the parse.
|
||||||
ListParser<T> chain<T>(Iterable<Parser<T>> parsers,
|
ListParser<T> chain<T>(Iterable<Parser<T>> parsers,
|
||||||
{bool failFast: true, SyntaxErrorSeverity? severity}) {
|
{bool failFast = true, SyntaxErrorSeverity? severity}) {
|
||||||
return _Chain<T>(
|
return _Chain<T>(
|
||||||
parsers, failFast != false, severity ?? SyntaxErrorSeverity.error);
|
parsers, failFast != false, severity ?? SyntaxErrorSeverity.error);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class _Chain<T> extends ListParser<T> {
|
||||||
var errors = <SyntaxError>[];
|
var errors = <SyntaxError>[];
|
||||||
var results = <T>[];
|
var results = <T>[];
|
||||||
var spans = <FileSpan>[];
|
var spans = <FileSpan>[];
|
||||||
bool successful = true;
|
var successful = true;
|
||||||
|
|
||||||
for (var parser in parsers) {
|
for (var parser in parsers) {
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
@ -64,7 +64,7 @@ class _Chain<T> extends ListParser<T> {
|
||||||
if (result.value != null) {
|
if (result.value != null) {
|
||||||
results.add(result.value!);
|
results.add(result.value!);
|
||||||
} else {
|
} else {
|
||||||
results.add("NULL" as T);
|
results.add('NULL' as T);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.span != null) {
|
if (result.span != null) {
|
||||||
|
@ -94,7 +94,7 @@ class _Chain<T> extends ListParser<T> {
|
||||||
buffer
|
buffer
|
||||||
..writeln('chain(${parsers.length}) (')
|
..writeln('chain(${parsers.length}) (')
|
||||||
..indent();
|
..indent();
|
||||||
int i = 1;
|
var i = 1;
|
||||||
|
|
||||||
for (var parser in parsers) {
|
for (var parser in parsers) {
|
||||||
buffer
|
buffer
|
||||||
|
|
|
@ -12,9 +12,9 @@ class _Check<T> extends Parser<T> {
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var matchState = {};
|
var matchState = {};
|
||||||
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
||||||
if (!result.successful)
|
if (!result.successful) {
|
||||||
return result;
|
return result;
|
||||||
else if (!matcher.matches(result.value, matchState)) {
|
} else if (!matcher.matches(result.value, matchState)) {
|
||||||
return result.change(successful: false).addErrors([
|
return result.change(successful: false).addErrors([
|
||||||
SyntaxError(
|
SyntaxError(
|
||||||
severity,
|
severity,
|
||||||
|
@ -23,8 +23,9 @@ class _Check<T> extends Parser<T> {
|
||||||
result.span,
|
result.span,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
} else
|
} else {
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -72,11 +72,13 @@ abstract class Parser<T> {
|
||||||
ParseResult<T> _parse(ParseArgs args) {
|
ParseResult<T> _parse(ParseArgs args) {
|
||||||
var pos = args.scanner.position;
|
var pos = args.scanner.position;
|
||||||
|
|
||||||
if (args.trampoline.hasMemoized(this, pos))
|
if (args.trampoline.hasMemoized(this, pos)) {
|
||||||
return args.trampoline.getMemoized<T>(this, pos);
|
return args.trampoline.getMemoized<T>(this, pos);
|
||||||
|
}
|
||||||
|
|
||||||
if (args.trampoline.isActive(this, pos))
|
if (args.trampoline.isActive(this, pos)) {
|
||||||
return ParseResult(args.trampoline, args.scanner, this, false, []);
|
return ParseResult(args.trampoline, args.scanner, this, false, []);
|
||||||
|
}
|
||||||
|
|
||||||
args.trampoline.enter(this, pos);
|
args.trampoline.enter(this, pos);
|
||||||
var result = __parse(args);
|
var result = __parse(args);
|
||||||
|
@ -103,7 +105,6 @@ abstract class Parser<T> {
|
||||||
/// Casts this parser to produce [dynamic] objects.
|
/// Casts this parser to produce [dynamic] objects.
|
||||||
Parser<dynamic> castDynamic() => _CastDynamic<T>(this);
|
Parser<dynamic> castDynamic() => _CastDynamic<T>(this);
|
||||||
|
|
||||||
// TODO: Type issue
|
|
||||||
/// Runs the given function, which changes the returned [ParseResult] into one relating to a [U] object.
|
/// Runs the given function, which changes the returned [ParseResult] into one relating to a [U] object.
|
||||||
Parser<U> change<U>(ParseResult<U> Function(ParseResult<T>) f) {
|
Parser<U> change<U>(ParseResult<U> Function(ParseResult<T>) f) {
|
||||||
return _Change<T, U>(this, f);
|
return _Change<T, U>(this, f);
|
||||||
|
@ -122,7 +123,7 @@ abstract class Parser<T> {
|
||||||
_Alt<T>(this, errorMessage, severity ?? SyntaxErrorSeverity.error);
|
_Alt<T>(this, errorMessage, severity ?? SyntaxErrorSeverity.error);
|
||||||
|
|
||||||
/// Removes multiple errors that occur in the same spot; this can reduce noise in parser output.
|
/// Removes multiple errors that occur in the same spot; this can reduce noise in parser output.
|
||||||
Parser<T> foldErrors({bool equal(SyntaxError a, SyntaxError b)?}) {
|
Parser<T> foldErrors({bool Function(SyntaxError a, SyntaxError b)? equal}) {
|
||||||
equal ??= (b, e) => b.span?.start.offset == e.span?.start.offset;
|
equal ??= (b, e) => b.span?.start.offset == e.span?.start.offset;
|
||||||
return _FoldErrors<T>(this, equal);
|
return _FoldErrors<T>(this, equal);
|
||||||
}
|
}
|
||||||
|
@ -177,8 +178,8 @@ abstract class Parser<T> {
|
||||||
///
|
///
|
||||||
/// The generated parser only runs once; repeated uses always exit eagerly.
|
/// The generated parser only runs once; repeated uses always exit eagerly.
|
||||||
Parser<T> safe(
|
Parser<T> safe(
|
||||||
{bool backtrack: true,
|
{bool backtrack = true,
|
||||||
String errorMessage = "error",
|
String errorMessage = 'error',
|
||||||
SyntaxErrorSeverity? severity}) =>
|
SyntaxErrorSeverity? severity}) =>
|
||||||
_Safe<T>(
|
_Safe<T>(
|
||||||
this, backtrack, errorMessage, severity ?? SyntaxErrorSeverity.error);
|
this, backtrack, errorMessage, severity ?? SyntaxErrorSeverity.error);
|
||||||
|
@ -191,14 +192,14 @@ abstract class Parser<T> {
|
||||||
/// Use this as a shortcut to parse arrays, parameter lists, etc.
|
/// Use this as a shortcut to parse arrays, parameter lists, etc.
|
||||||
Parser<List<T>> separatedBy(Parser other) {
|
Parser<List<T>> separatedBy(Parser other) {
|
||||||
var suffix = other.then(this).index(1).cast<T>();
|
var suffix = other.then(this).index(1).cast<T>();
|
||||||
return this.then(suffix.star()).map((r) {
|
return then(suffix.star()).map((r) {
|
||||||
var v = r.value;
|
var v = r.value;
|
||||||
if (v == null || v.length < 2) {
|
if (v == null || v.length < 2) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var preceding = v.isEmpty ? [] : (v[0] == null ? [] : [v[0]]);
|
var preceding = v.isEmpty ? [] : (v[0] == null ? [] : [v[0]]);
|
||||||
var out = List<T>.from(preceding);
|
var out = List<T>.from(preceding);
|
||||||
if (v[1] != null && v[1] != "NULL") {
|
if (v[1] != null && v[1] != 'NULL') {
|
||||||
v[1].forEach((element) {
|
v[1].forEach((element) {
|
||||||
out.add(element as T);
|
out.add(element as T);
|
||||||
});
|
});
|
||||||
|
@ -240,7 +241,7 @@ abstract class Parser<T> {
|
||||||
Parser<T> space() => trail(RegExp(r'[ \n\r\t]+'));
|
Parser<T> space() => trail(RegExp(r'[ \n\r\t]+'));
|
||||||
|
|
||||||
/// Consumes 0 or more instance(s) of this parser.
|
/// Consumes 0 or more instance(s) of this parser.
|
||||||
ListParser<T> star({bool backtrack: true}) =>
|
ListParser<T> star({bool backtrack = true}) =>
|
||||||
times(1, exact: false, backtrack: backtrack).opt();
|
times(1, exact: false, backtrack: backtrack).opt();
|
||||||
|
|
||||||
/// Shortcut for [chain]-ing two parsers together.
|
/// Shortcut for [chain]-ing two parsers together.
|
||||||
|
@ -260,10 +261,10 @@ abstract class Parser<T> {
|
||||||
///
|
///
|
||||||
/// You can provide custom error messages for when there are [tooFew] or [tooMany] occurrences.
|
/// You can provide custom error messages for when there are [tooFew] or [tooMany] occurrences.
|
||||||
ListParser<T> times(int count,
|
ListParser<T> times(int count,
|
||||||
{bool exact: true,
|
{bool exact = true,
|
||||||
String tooFew = 'Too few',
|
String tooFew = 'Too few',
|
||||||
String tooMany = 'Too many',
|
String tooMany = 'Too many',
|
||||||
bool backtrack: true,
|
bool backtrack = true,
|
||||||
SyntaxErrorSeverity? severity}) {
|
SyntaxErrorSeverity? severity}) {
|
||||||
return _Repeat<T>(this, count, exact, tooFew, tooMany, backtrack,
|
return _Repeat<T>(this, count, exact, tooFew, tooMany, backtrack,
|
||||||
severity ?? SyntaxErrorSeverity.error);
|
severity ?? SyntaxErrorSeverity.error);
|
||||||
|
@ -273,7 +274,7 @@ abstract class Parser<T> {
|
||||||
///
|
///
|
||||||
/// If [backtrack] is `true` (default), then a failed parse will not
|
/// If [backtrack] is `true` (default), then a failed parse will not
|
||||||
/// modify the scanner state.
|
/// modify the scanner state.
|
||||||
Parser<T> opt({bool backtrack: true}) => _Opt(this, backtrack);
|
Parser<T> opt({bool backtrack = true}) => _Opt(this, backtrack);
|
||||||
|
|
||||||
/// Sets the value of the [ParseResult].
|
/// Sets the value of the [ParseResult].
|
||||||
Parser<T> value(T Function(ParseResult<T?>) f) {
|
Parser<T> value(T Function(ParseResult<T?>) f) {
|
||||||
|
@ -302,7 +303,7 @@ abstract class ListParser<T> extends Parser<List<T>> {
|
||||||
ListParser<T> sort(Comparator<T> compare) => _Compare(this, compare);
|
ListParser<T> sort(Comparator<T> compare) => _Compare(this, compare);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ListParser<T> opt({bool backtrack: true}) => _ListOpt(this, backtrack);
|
ListParser<T> opt({bool backtrack = true}) => _ListOpt(this, backtrack);
|
||||||
|
|
||||||
/// Modifies this parser, returning only the values that match a predicate.
|
/// Modifies this parser, returning only the values that match a predicate.
|
||||||
Parser<List<T>> where(bool Function(T) f) =>
|
Parser<List<T>> where(bool Function(T) f) =>
|
||||||
|
|
|
@ -8,7 +8,7 @@ class _Compare<T> extends ListParser<T> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<List<T>> __parse(ParseArgs args) {
|
ParseResult<List<T>> __parse(ParseArgs args) {
|
||||||
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
if (!result.successful) return result;
|
if (!result.successful) return result;
|
||||||
|
|
||||||
result = result.change(
|
result = result.change(
|
||||||
|
|
|
@ -8,19 +8,18 @@ class _Index<T> extends Parser<T> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
Object? value;
|
Object? value;
|
||||||
|
|
||||||
if (result.successful) {
|
if (result.successful) {
|
||||||
var vList = result.value;
|
var vList = result.value;
|
||||||
if (vList == null) {
|
if (vList == null) {
|
||||||
throw ArgumentError("ParseResult is null");
|
throw ArgumentError('ParseResult is null');
|
||||||
}
|
}
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
value = vList.last;
|
value = vList.last;
|
||||||
} else {
|
} else {
|
||||||
if (index < vList.length) {
|
if (index < vList.length) {
|
||||||
//TODO: Look at this
|
|
||||||
// print(">>>>Index: $index, Size: ${vList.length}");
|
// print(">>>>Index: $index, Size: ${vList.length}");
|
||||||
// value =
|
// value =
|
||||||
// index == -1 ? result.value!.last : result.value!.elementAt(index);
|
// index == -1 ? result.value!.last : result.value!.elementAt(index);
|
||||||
|
|
|
@ -25,16 +25,16 @@ class _Longest<T> extends Parser<T> {
|
||||||
return ParseResult(args.trampoline, args.scanner, this, false, []);
|
return ParseResult(args.trampoline, args.scanner, this, false, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
int replay = args.scanner.position;
|
var replay = args.scanner.position;
|
||||||
var errors = <SyntaxError>[];
|
var errors = <SyntaxError>[];
|
||||||
var results = <ParseResult<T>>[];
|
var results = <ParseResult<T>>[];
|
||||||
|
|
||||||
for (var parser in inactive) {
|
for (var parser in inactive) {
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (result.successful && result.span != null)
|
if (result.successful && result.span != null) {
|
||||||
results.add(result);
|
results.add(result);
|
||||||
else if (parser is _Alt) errors.addAll(result.errors);
|
} else if (parser is _Alt) errors.addAll(result.errors);
|
||||||
|
|
||||||
args.scanner.position = replay;
|
args.scanner.position = replay;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class _Longest<T> extends Parser<T> {
|
||||||
return results.first;
|
return results.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorMessage != false)
|
if (errorMessage != false) {
|
||||||
errors.add(
|
errors.add(
|
||||||
SyntaxError(
|
SyntaxError(
|
||||||
severity,
|
severity,
|
||||||
|
@ -54,22 +54,23 @@ class _Longest<T> extends Parser<T> {
|
||||||
args.scanner.emptySpan,
|
args.scanner.emptySpan,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return ParseResult(args.trampoline, args.scanner, this, false, errors);
|
return ParseResult(args.trampoline, args.scanner, this, false, errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
int replay = args.scanner.position;
|
var replay = args.scanner.position;
|
||||||
var errors = <SyntaxError>[];
|
var errors = <SyntaxError>[];
|
||||||
var results = <ParseResult<T>>[];
|
var results = <ParseResult<T>>[];
|
||||||
|
|
||||||
for (var parser in parsers) {
|
for (var parser in parsers) {
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (result.successful)
|
if (result.successful) {
|
||||||
results.add(result);
|
results.add(result);
|
||||||
else if (parser is _Alt) errors.addAll(result.errors);
|
} else if (parser is _Alt) errors.addAll(result.errors);
|
||||||
|
|
||||||
args.scanner.position = replay;
|
args.scanner.position = replay;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +98,7 @@ class _Longest<T> extends Parser<T> {
|
||||||
buffer
|
buffer
|
||||||
..writeln('longest(${parsers.length}) (')
|
..writeln('longest(${parsers.length}) (')
|
||||||
..indent();
|
..indent();
|
||||||
int i = 1;
|
var i = 1;
|
||||||
|
|
||||||
for (var parser in parsers) {
|
for (var parser in parsers) {
|
||||||
buffer
|
buffer
|
||||||
|
|
|
@ -15,7 +15,7 @@ class _Match<T> extends Parser<T> {
|
||||||
@override
|
@override
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var scanner = args.scanner;
|
var scanner = args.scanner;
|
||||||
if (!scanner.scan(pattern))
|
if (!scanner.scan(pattern)) {
|
||||||
return ParseResult(args.trampoline, scanner, this, false, [
|
return ParseResult(args.trampoline, scanner, this, false, [
|
||||||
SyntaxError(
|
SyntaxError(
|
||||||
severity,
|
severity,
|
||||||
|
@ -23,6 +23,7 @@ class _Match<T> extends Parser<T> {
|
||||||
scanner.emptySpan,
|
scanner.emptySpan,
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
return ParseResult<T>(
|
return ParseResult<T>(
|
||||||
args.trampoline,
|
args.trampoline,
|
||||||
scanner,
|
scanner,
|
||||||
|
|
|
@ -37,7 +37,7 @@ class _ListOpt<T> extends ListParser<T> {
|
||||||
@override
|
@override
|
||||||
ParseResult<List<T>> __parse(ParseArgs args) {
|
ParseResult<List<T>> __parse(ParseArgs args) {
|
||||||
var replay = args.scanner.position;
|
var replay = args.scanner.position;
|
||||||
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (!result.successful) args.scanner.position = replay;
|
if (!result.successful) args.scanner.position = replay;
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@ class _Reduce<T> extends Parser<T> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (!result.successful)
|
if (!result.successful) {
|
||||||
return ParseResult<T>(
|
return ParseResult<T>(
|
||||||
args.trampoline,
|
args.trampoline,
|
||||||
args.scanner,
|
args.scanner,
|
||||||
|
@ -18,6 +18,7 @@ class _Reduce<T> extends Parser<T> {
|
||||||
false,
|
false,
|
||||||
result.errors,
|
result.errors,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
result = result.change(
|
result = result.change(
|
||||||
value: result.value?.isNotEmpty == true ? result.value : []);
|
value: result.value?.isNotEmpty == true ? result.value : []);
|
||||||
|
|
|
@ -8,23 +8,26 @@ class Reference<T> extends Parser<T> {
|
||||||
|
|
||||||
Reference._();
|
Reference._();
|
||||||
|
|
||||||
void set parser(Parser<T> value) {
|
set parser(Parser<T> value) {
|
||||||
if (_parser != null)
|
if (_parser != null) {
|
||||||
throw StateError('There is already a parser assigned to this reference.');
|
throw StateError('There is already a parser assigned to this reference.');
|
||||||
|
}
|
||||||
_parser = value;
|
_parser = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
if (_parser == null)
|
if (_parser == null) {
|
||||||
throw StateError('There is no parser assigned to this reference.');
|
throw StateError('There is no parser assigned to this reference.');
|
||||||
|
}
|
||||||
return _parser!._parse(args);
|
return _parser!._parse(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T> _parse(ParseArgs args) {
|
ParseResult<T> _parse(ParseArgs args) {
|
||||||
if (_parser == null)
|
if (_parser == null) {
|
||||||
throw StateError('There is no parser assigned to this reference.');
|
throw StateError('There is no parser assigned to this reference.');
|
||||||
|
}
|
||||||
return _parser!._parse(args);
|
return _parser!._parse(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,8 @@ class _Repeat<T> extends ListParser<T> {
|
||||||
var errors = <SyntaxError>[];
|
var errors = <SyntaxError>[];
|
||||||
var results = <T>[];
|
var results = <T>[];
|
||||||
var spans = <FileSpan>[];
|
var spans = <FileSpan>[];
|
||||||
int success = 0, replay = args.scanner.position;
|
var success = 0;
|
||||||
|
var replay = args.scanner.position;
|
||||||
ParseResult<T> result;
|
ParseResult<T> result;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -13,7 +13,7 @@ class _ToList<T> extends ListParser<T> {
|
||||||
return (result as ParseResult<List<T>>).change(parser: this);
|
return (result as ParseResult<List<T>>).change(parser: this);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<T> values = [];
|
var values = <T>[];
|
||||||
if (result.value != null) {
|
if (result.value != null) {
|
||||||
values.add(result.value!);
|
values.add(result.value!);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name: angel3_combinator
|
name: angel3_combinator
|
||||||
version: 2.0.1
|
version: 2.0.2
|
||||||
description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
|
description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
|
||||||
homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/combinator
|
homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/combinator
|
||||||
environment:
|
environment:
|
||||||
|
@ -11,4 +11,5 @@ dependencies:
|
||||||
string_scanner: ^1.1.0
|
string_scanner: ^1.1.0
|
||||||
tuple: ^2.0.0
|
tuple: ^2.0.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.4
|
test: ^1.17.4
|
||||||
|
pedantic: ^1.11.0
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:angel3_combinator/angel3_combinator.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
||||||
main() {
|
void main() {
|
||||||
var number = chain([
|
var number = chain([
|
||||||
match(RegExp(r'[0-9]+')).value((r) => int.parse(r.span!.text)),
|
match(RegExp(r'[0-9]+')).value((r) => int.parse(r.span!.text)),
|
||||||
match(',').opt(),
|
match(',').opt(),
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
import 'package:angel3_combinator/angel3_combinator.dart';
|
|
||||||
import 'package:string_scanner/string_scanner.dart';
|
|
||||||
import 'package:test/test.dart';
|
|
||||||
|
|
||||||
void main() {}
|
void main() {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue