Use Optional
This commit is contained in:
parent
15926ff45d
commit
25af334f4d
27 changed files with 78 additions and 69 deletions
|
@ -18,7 +18,7 @@ final Parser<Map<String, String>> credentials = chain<String>([
|
||||||
match<String>(':'),
|
match<String>(':'),
|
||||||
string.opt(),
|
string.opt(),
|
||||||
]).map<Map<String, String>>(
|
]).map<Map<String, String>>(
|
||||||
(r) => {'username': r.value![0]!, 'password': r.value![2]!});
|
(r) => {'username': r.value![0], 'password': r.value![2]});
|
||||||
|
|
||||||
/// We can actually embed a parser within another parser.
|
/// We can actually embed a parser within another parser.
|
||||||
///
|
///
|
||||||
|
|
|
@ -24,7 +24,7 @@ Parser<num> calculatorGrammar() {
|
||||||
expr.space(),
|
expr.space(),
|
||||||
match<Null>(op).space() as Parser<num>,
|
match<Null>(op).space() as Parser<num>,
|
||||||
expr.space(),
|
expr.space(),
|
||||||
]).map((r) => f(r.value![0]!, r.value![2]!)),
|
]).map((r) => f(r.value![0], r.value![2])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ class _Advance<T> extends Parser<T> {
|
||||||
_Advance(this.parser, this.amount);
|
_Advance(this.parser, this.amount);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
||||||
if (result.successful) args.scanner.position += amount;
|
if (result.successful) args.scanner.position += amount;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -21,7 +21,7 @@ class _Any<T> extends Parser<T> {
|
||||||
_Any(this.parsers, this.backtrack, this.errorMessage, this.severity);
|
_Any(this.parsers, this.backtrack, this.errorMessage, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> _parse(ParseArgs args) {
|
ParseResult<T> _parse(ParseArgs args) {
|
||||||
var inactive = parsers
|
var inactive = parsers
|
||||||
.where((p) => !args.trampoline.isActive(p, args.scanner.position));
|
.where((p) => !args.trampoline.isActive(p, args.scanner.position));
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
part of lex.src.combinator;
|
part of lex.src.combinator;
|
||||||
|
|
||||||
class _Cache<T> extends Parser<T> {
|
class _Cache<T> extends Parser<T> {
|
||||||
final Map<int, ParseResult<T?>> _cache = {};
|
final Map<int, ParseResult<T>> _cache = {};
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
||||||
_Cache(this.parser);
|
_Cache(this.parser);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
return _cache.putIfAbsent(args.scanner.position, () {
|
return _cache.putIfAbsent(args.scanner.position, () {
|
||||||
return parser._parse(args.increaseDepth());
|
return parser._parse(args.increaseDepth());
|
||||||
}).change(parser: this);
|
}).change(parser: this);
|
||||||
|
|
|
@ -3,9 +3,9 @@ part of lex.src.combinator;
|
||||||
/// Expects to parse a sequence of [parsers].
|
/// Expects to parse a sequence of [parsers].
|
||||||
///
|
///
|
||||||
/// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class _Alt<T> extends Parser<T> {
|
||||||
_Alt(this.parser, this.errorMessage, this.severity);
|
_Alt(this.parser, this.errorMessage, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
return result.successful
|
return result.successful
|
||||||
? result
|
? result
|
||||||
|
@ -33,7 +33,7 @@ class _Alt<T> extends Parser<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Chain<T> extends ListParser<T?> {
|
class _Chain<T> extends ListParser<T> {
|
||||||
final Iterable<Parser<T>> parsers;
|
final Iterable<Parser<T>> parsers;
|
||||||
final bool failFast;
|
final bool failFast;
|
||||||
final SyntaxErrorSeverity severity;
|
final SyntaxErrorSeverity severity;
|
||||||
|
@ -41,7 +41,7 @@ class _Chain<T> extends ListParser<T?> {
|
||||||
_Chain(this.parsers, this.failFast, this.severity);
|
_Chain(this.parsers, this.failFast, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<List<T?>?> __parse(ParseArgs args) {
|
ParseResult<List<T>> __parse(ParseArgs args) {
|
||||||
var errors = <SyntaxError>[];
|
var errors = <SyntaxError>[];
|
||||||
var results = <T?>[];
|
var results = <T?>[];
|
||||||
var spans = <FileSpan>[];
|
var spans = <FileSpan>[];
|
||||||
|
@ -61,7 +61,10 @@ class _Chain<T> extends ListParser<T?> {
|
||||||
successful = false;
|
successful = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: To be looked at
|
||||||
|
//if (result.value != null) {
|
||||||
results.add(result.value);
|
results.add(result.value);
|
||||||
|
//}
|
||||||
|
|
||||||
if (result.span != null) {
|
if (result.span != null) {
|
||||||
spans.add(result.span!);
|
spans.add(result.span!);
|
||||||
|
@ -74,14 +77,14 @@ class _Chain<T> extends ListParser<T?> {
|
||||||
span = spans.reduce((a, b) => a.expand(b));
|
span = spans.reduce((a, b) => a.expand(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseResult<List<T?>?>(
|
return ParseResult<List<T>>(
|
||||||
args.trampoline,
|
args.trampoline,
|
||||||
args.scanner,
|
args.scanner,
|
||||||
this,
|
this,
|
||||||
successful,
|
successful,
|
||||||
errors,
|
errors,
|
||||||
span: span,
|
span: span,
|
||||||
value: List<T?>.unmodifiable(results),
|
value: List<T>.unmodifiable(results),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class _Check<T> extends Parser<T> {
|
||||||
_Check(this.parser, this.matcher, this.errorMessage, this.severity);
|
_Check(this.parser, this.matcher, this.errorMessage, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
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)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:matcher/matcher.dart';
|
||||||
import 'package:source_span/source_span.dart';
|
import 'package:source_span/source_span.dart';
|
||||||
import 'package:string_scanner/string_scanner.dart';
|
import 'package:string_scanner/string_scanner.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
import 'package:optional/optional.dart';
|
||||||
import '../error.dart';
|
import '../error.dart';
|
||||||
|
|
||||||
part 'any.dart';
|
part 'any.dart';
|
||||||
|
@ -67,9 +68,9 @@ class ParseArgs {
|
||||||
|
|
||||||
/// A parser combinator, which can parse very complicated grammars in a manageable manner.
|
/// A parser combinator, which can parse very complicated grammars in a manageable manner.
|
||||||
abstract class Parser<T> {
|
abstract class Parser<T> {
|
||||||
ParseResult<T?> __parse(ParseArgs args);
|
ParseResult<T> __parse(ParseArgs args);
|
||||||
|
|
||||||
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))
|
||||||
|
@ -86,7 +87,7 @@ abstract class Parser<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses text from a [SpanScanner].
|
/// Parses text from a [SpanScanner].
|
||||||
ParseResult<T?> parse(SpanScanner scanner, [int depth = 1]) {
|
ParseResult<T> parse(SpanScanner scanner, [int depth = 1]) {
|
||||||
var args = ParseArgs(Trampoline(), scanner, depth);
|
var args = ParseArgs(Trampoline(), scanner, depth);
|
||||||
return _parse(args);
|
return _parse(args);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +106,7 @@ abstract class Parser<T> {
|
||||||
|
|
||||||
// TODO: Type issue
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +129,7 @@ abstract class Parser<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms the parse result using a unary function.
|
/// Transforms the parse result using a unary function.
|
||||||
Parser<U> map<U>(U Function(ParseResult<T?>) f) {
|
Parser<U> map<U>(U Function(ParseResult<T>) f) {
|
||||||
return _Map<T, U>(this, f);
|
return _Map<T, U>(this, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +172,7 @@ abstract class Parser<T> {
|
||||||
Parser<T> or<U>(Parser<T> other) => any<T>([this, other]);
|
Parser<T> or<U>(Parser<T> other) => any<T>([this, other]);
|
||||||
|
|
||||||
/// Parses this sequence one or more times.
|
/// Parses this sequence one or more times.
|
||||||
ListParser<T?> plus() => times(1, exact: false);
|
ListParser<T> plus() => times(1, exact: false);
|
||||||
|
|
||||||
/// Safely escapes this parser when an error occurs.
|
/// Safely escapes this parser when an error occurs.
|
||||||
///
|
///
|
||||||
|
@ -207,11 +208,11 @@ abstract class Parser<T> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser<T?> surroundedByCurlyBraces({T? defaultValue}) => opt()
|
Parser<T> surroundedByCurlyBraces({required T defaultValue}) => opt()
|
||||||
.surroundedBy(match('{').space(), match('}').space())
|
.surroundedBy(match('{').space(), match('}').space())
|
||||||
.map((r) => r.value ?? defaultValue);
|
.map((r) => r.value ?? defaultValue);
|
||||||
|
|
||||||
Parser<T?> surroundedBySquareBrackets({T? defaultValue}) => opt()
|
Parser<T> surroundedBySquareBrackets({required T defaultValue}) => opt()
|
||||||
.surroundedBy(match('[').space(), match(']').space())
|
.surroundedBy(match('[').space(), match(']').space())
|
||||||
.map((r) => r.value ?? defaultValue);
|
.map((r) => r.value ?? defaultValue);
|
||||||
|
|
||||||
|
@ -336,7 +337,9 @@ class Trampoline {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isActive(Parser parser, int position) {
|
bool isActive(Parser parser, int position) {
|
||||||
if (!_active.containsKey(parser)) return false;
|
if (!_active.containsKey(parser)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var q = _active[parser]!;
|
var q = _active[parser]!;
|
||||||
if (q.isEmpty) return false;
|
if (q.isEmpty) return false;
|
||||||
//return q.contains(position);
|
//return q.contains(position);
|
||||||
|
|
|
@ -7,8 +7,8 @@ class _Compare<T> extends ListParser<T> {
|
||||||
_Compare(this.parser, this.compare);
|
_Compare(this.parser, this.compare);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<List<T>?> __parse(ParseArgs args) {
|
ParseResult<List<T>> __parse(ParseArgs args) {
|
||||||
ParseResult<List<T>?> result = parser._parse(args.increaseDepth());
|
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
||||||
if (!result.successful) return result;
|
if (!result.successful) return result;
|
||||||
|
|
||||||
result = result.change(
|
result = result.change(
|
||||||
|
|
|
@ -7,7 +7,7 @@ class _FoldErrors<T> extends Parser<T> {
|
||||||
_FoldErrors(this.parser, this.equal);
|
_FoldErrors(this.parser, this.equal);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
||||||
var errors = result.errors.fold<List<SyntaxError>>([], (out, e) {
|
var errors = result.errors.fold<List<SyntaxError>>([], (out, e) {
|
||||||
if (!out.any((b) => equal(e, b))) out.add(e);
|
if (!out.any((b) => equal(e, b))) out.add(e);
|
||||||
|
|
|
@ -16,7 +16,7 @@ class _Longest<T> extends Parser<T> {
|
||||||
_Longest(this.parsers, this.errorMessage, this.severity);
|
_Longest(this.parsers, this.errorMessage, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> _parse(ParseArgs args) {
|
ParseResult<T> _parse(ParseArgs args) {
|
||||||
var inactive = parsers
|
var inactive = parsers
|
||||||
.toList()
|
.toList()
|
||||||
.where((p) => !args.trampoline.isActive(p, args.scanner.position));
|
.where((p) => !args.trampoline.isActive(p, args.scanner.position));
|
||||||
|
@ -27,7 +27,7 @@ class _Longest<T> extends Parser<T> {
|
||||||
|
|
||||||
int replay = args.scanner.position;
|
int 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());
|
||||||
|
@ -59,10 +59,10 @@ class _Longest<T> extends Parser<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
int replay = args.scanner.position;
|
int 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());
|
||||||
|
|
|
@ -2,14 +2,14 @@ part of lex.src.combinator;
|
||||||
|
|
||||||
class _Map<T, U> extends Parser<U> {
|
class _Map<T, U> extends Parser<U> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
final U Function(ParseResult<T?>) f;
|
final U Function(ParseResult<T>) f;
|
||||||
|
|
||||||
_Map(this.parser, this.f);
|
_Map(this.parser, this.f);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<U?> __parse(ParseArgs args) {
|
ParseResult<U> __parse(ParseArgs args) {
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
return ParseResult<U?>(
|
return ParseResult<U>(
|
||||||
args.trampoline,
|
args.trampoline,
|
||||||
args.scanner,
|
args.scanner,
|
||||||
this,
|
this,
|
||||||
|
@ -34,12 +34,12 @@ class _Map<T, U> extends Parser<U> {
|
||||||
|
|
||||||
class _Change<T, U> extends Parser<U> {
|
class _Change<T, U> extends Parser<U> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
final ParseResult<U?> Function(ParseResult<T?>) f;
|
final ParseResult<U> Function(ParseResult<T>) f;
|
||||||
|
|
||||||
_Change(this.parser, this.f);
|
_Change(this.parser, this.f);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<U?> __parse(ParseArgs args) {
|
ParseResult<U> __parse(ParseArgs args) {
|
||||||
return f(parser._parse(args.increaseDepth())).change(parser: this);
|
return f(parser._parse(args.increaseDepth())).change(parser: this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ class _MaxDepth<T> extends Parser<T> {
|
||||||
_MaxDepth(this.parser, this.cap);
|
_MaxDepth(this.parser, this.cap);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
if (args.depth > cap) {
|
if (args.depth > cap) {
|
||||||
return ParseResult<T>(args.trampoline, args.scanner, this, false, []);
|
return ParseResult<T>(args.trampoline, args.scanner, this, false, []);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ class _Negate<T> extends Parser<T> {
|
||||||
_Negate(this.parser, this.errorMessage, this.severity);
|
_Negate(this.parser, this.errorMessage, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
||||||
|
|
||||||
if (!result.successful) {
|
if (!result.successful) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ class _Opt<T> extends Parser<T> {
|
||||||
_Opt(this.parser, this.backtrack);
|
_Opt(this.parser, this.backtrack);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var replay = args.scanner.position;
|
var replay = args.scanner.position;
|
||||||
var result = parser._parse(args.increaseDepth());
|
var result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ class _ListOpt<T> extends ListParser<T> {
|
||||||
_ListOpt(this.parser, this.backtrack);
|
_ListOpt(this.parser, this.backtrack);
|
||||||
|
|
||||||
@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());
|
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (!result.successful) args.scanner.position = replay;
|
if (!result.successful) args.scanner.position = replay;
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ class _Reduce<T> extends Parser<T> {
|
||||||
_Reduce(this.parser, this.combine);
|
_Reduce(this.parser, this.combine);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
ParseResult<List<T>?> result = parser._parse(args.increaseDepth());
|
ParseResult<List<T>> result = parser._parse(args.increaseDepth());
|
||||||
|
|
||||||
if (!result.successful)
|
if (!result.successful)
|
||||||
return ParseResult<T>(
|
return ParseResult<T>(
|
||||||
|
|
|
@ -15,14 +15,14 @@ class Reference<T> extends Parser<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
|
|
|
@ -12,12 +12,12 @@ class _Repeat<T> extends ListParser<T> {
|
||||||
this.backtrack, this.severity);
|
this.backtrack, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<List<T>?> __parse(ParseArgs args) {
|
ParseResult<List<T>> __parse(ParseArgs args) {
|
||||||
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;
|
int success = 0, replay = args.scanner.position;
|
||||||
ParseResult<T?> result;
|
ParseResult<T> result;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
result = parser._parse(args.increaseDepth());
|
result = parser._parse(args.increaseDepth());
|
||||||
|
@ -51,7 +51,7 @@ class _Repeat<T> extends ListParser<T> {
|
||||||
} else if (success > count && exact) {
|
} else if (success > count && exact) {
|
||||||
if (backtrack) args.scanner.position = replay;
|
if (backtrack) args.scanner.position = replay;
|
||||||
|
|
||||||
return ParseResult<List<T>?>(args.trampoline, args.scanner, this, false, [
|
return ParseResult<List<T>>(args.trampoline, args.scanner, this, false, [
|
||||||
SyntaxError(
|
SyntaxError(
|
||||||
severity,
|
severity,
|
||||||
tooMany,
|
tooMany,
|
||||||
|
|
|
@ -10,7 +10,7 @@ class _Safe<T> extends Parser<T> {
|
||||||
_Safe(this.parser, this.backtrack, this.errorMessage, this.severity);
|
_Safe(this.parser, this.backtrack, this.errorMessage, this.severity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var replay = args.scanner.position;
|
var replay = args.scanner.position;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -2,12 +2,12 @@ part of lex.src.combinator;
|
||||||
|
|
||||||
class _Value<T> extends Parser<T> {
|
class _Value<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
final T Function(ParseResult<T?>) f;
|
final T Function(ParseResult<T>) f;
|
||||||
|
|
||||||
_Value(this.parser, this.f);
|
_Value(this.parser, this.f);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ParseResult<T?> __parse(ParseArgs args) {
|
ParseResult<T> __parse(ParseArgs args) {
|
||||||
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
var result = parser._parse(args.increaseDepth()).change(parser: this);
|
||||||
return result.successful ? result.change(value: f(result)) : result;
|
return result.successful ? result.change(value: f(result)) : result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,6 @@ dependencies:
|
||||||
source_span: ^1.8.1
|
source_span: ^1.8.1
|
||||||
string_scanner: ^1.1.0
|
string_scanner: ^1.1.0
|
||||||
tuple: ^2.0.0
|
tuple: ^2.0.0
|
||||||
|
optional: ^6.0.0-nullsafety.2
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.3
|
test: ^1.17.3
|
|
@ -11,11 +11,11 @@ main() {
|
||||||
var numbers = number.plus();
|
var numbers = number.plus();
|
||||||
|
|
||||||
test('sort', () {
|
test('sort', () {
|
||||||
var parser = numbers.sort((a, b) => a!.compareTo(b!));
|
var parser = numbers.sort((a, b) => a.compareTo(b));
|
||||||
expect(parser.parse(scan('21,2,3,34,20')).value, [2, 3, 20, 21, 34]);
|
expect(parser.parse(scan('21,2,3,34,20')).value, [2, 3, 20, 21, 34]);
|
||||||
});
|
});
|
||||||
test('reduce', () {
|
test('reduce', () {
|
||||||
var parser = numbers.reduce((a, b) => a! + b!);
|
var parser = numbers.reduce((a, b) => a + b);
|
||||||
expect(parser.parse(scan('21,2,3,34,20')).value, 80);
|
expect(parser.parse(scan('21,2,3,34,20')).value, 80);
|
||||||
expect(parser.parse(scan('not numbers')).value, isNull);
|
expect(parser.parse(scan('not numbers')).value, isNull);
|
||||||
});
|
});
|
||||||
|
|
|
@ -139,7 +139,8 @@ abstract class Driver<
|
||||||
pipeline.handlers,
|
pipeline.handlers,
|
||||||
resolved.fold<Map<String, dynamic>>(
|
resolved.fold<Map<String, dynamic>>(
|
||||||
<String, dynamic>{}, (out, r) => out..addAll(r.allParams)),
|
<String, dynamic>{}, (out, r) => out..addAll(r.allParams)),
|
||||||
(resolved.isEmpty ? null : resolved.first.parseResult)!,
|
//(resolved.isEmpty ? null : resolved.first.parseResult),
|
||||||
|
resolved.first.parseResult,
|
||||||
pipeline,
|
pipeline,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,11 @@ dependencies:
|
||||||
ref: sdk-2.12.x_nnbd
|
ref: sdk-2.12.x_nnbd
|
||||||
path: packages/model
|
path: packages/model
|
||||||
angel_route:
|
angel_route:
|
||||||
git:
|
path: ../route
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
# git:
|
||||||
ref: sdk-2.12.x_nnbd
|
# url: https://github.com/dukefirehawk/angel.git
|
||||||
path: packages/route
|
# ref: sdk-2.12.x_nnbd
|
||||||
|
# path: packages/route
|
||||||
charcode: ^1.2.0
|
charcode: ^1.2.0
|
||||||
combinator:
|
combinator:
|
||||||
git:
|
git:
|
||||||
|
|
|
@ -311,7 +311,7 @@ class Router<T> {
|
||||||
if (parseResult != null) {
|
if (parseResult != null) {
|
||||||
if (parseResult.successful && scanner.isDone) {
|
if (parseResult.successful && scanner.isDone) {
|
||||||
var tailResult = parseResult.value?.tail ?? '';
|
var tailResult = parseResult.value?.tail ?? '';
|
||||||
print(tailResult);
|
//print(tailResult);
|
||||||
var result = RoutingResult<T>(
|
var result = RoutingResult<T>(
|
||||||
parseResult: parseResult,
|
parseResult: parseResult,
|
||||||
params: parseResult.value!.params,
|
params: parseResult.value!.params,
|
||||||
|
@ -334,13 +334,13 @@ class Router<T> {
|
||||||
|
|
||||||
/// Returns the result of [resolve] with [path] passed as
|
/// Returns the result of [resolve] with [path] passed as
|
||||||
/// both `absolute` and `relative`.
|
/// both `absolute` and `relative`.
|
||||||
Iterable<RoutingResult<T?>> resolveAbsolute(String path,
|
Iterable<RoutingResult<T>> resolveAbsolute(String path,
|
||||||
{String method = 'GET', bool strip = true}) =>
|
{String method = 'GET', bool strip = true}) =>
|
||||||
resolveAll(path, path, method: method, strip: strip);
|
resolveAll(path, path, method: method, strip: strip);
|
||||||
|
|
||||||
/// Finds every possible [Route] that matches the given path,
|
/// Finds every possible [Route] that matches the given path,
|
||||||
/// with the given method.
|
/// with the given method.
|
||||||
Iterable<RoutingResult<T?>> resolveAll(String absolute, String relative,
|
Iterable<RoutingResult<T>> resolveAll(String absolute, String relative,
|
||||||
{String method = 'GET', bool strip = true}) {
|
{String method = 'GET', bool strip = true}) {
|
||||||
if (_useCache == true) {
|
if (_useCache == true) {
|
||||||
return _cache.putIfAbsent('$method$absolute',
|
return _cache.putIfAbsent('$method$absolute',
|
||||||
|
|
|
@ -3,7 +3,7 @@ part of angel_route.src.router;
|
||||||
/// Represents a complex result of navigating to a path.
|
/// Represents a complex result of navigating to a path.
|
||||||
class RoutingResult<T> {
|
class RoutingResult<T> {
|
||||||
/// The parse result that matched the given sub-path.
|
/// The parse result that matched the given sub-path.
|
||||||
final ParseResult<RouteResult?> parseResult;
|
final ParseResult<RouteResult> parseResult;
|
||||||
|
|
||||||
/// A nested instance, if a sub-path was matched.
|
/// A nested instance, if a sub-path was matched.
|
||||||
final Iterable<RoutingResult<T>> nested;
|
final Iterable<RoutingResult<T>> nested;
|
||||||
|
@ -47,10 +47,10 @@ class RoutingResult<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All handlers on this sub-path and its children.
|
/// All handlers on this sub-path and its children.
|
||||||
List<T?> get allHandlers {
|
List<T> get allHandlers {
|
||||||
final handlers = <T?>[];
|
final handlers = <T>[];
|
||||||
|
|
||||||
void crawl(RoutingResult<T?> result) {
|
void crawl(RoutingResult<T> result) {
|
||||||
handlers.addAll(result.handlers);
|
handlers.addAll(result.handlers);
|
||||||
|
|
||||||
if (result.nested.isNotEmpty == true) {
|
if (result.nested.isNotEmpty == true) {
|
||||||
|
|
|
@ -7,11 +7,11 @@ environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
combinator:
|
combinator:
|
||||||
# path: ../combinator
|
path: ../combinator
|
||||||
git:
|
# git:
|
||||||
url: https://github.com/dukefirehawk/angel.git
|
# url: https://github.com/dukefirehawk/angel.git
|
||||||
ref: sdk-2.12.x_nnbd
|
# ref: sdk-2.12.x_nnbd
|
||||||
path: packages/combinator
|
# path: packages/combinator
|
||||||
string_scanner: ^1.0.0
|
string_scanner: ^1.0.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^1.11.5
|
build_runner: ^1.11.5
|
||||||
|
|
Loading…
Reference in a new issue