Created
July 1, 2019 12:52
-
-
Save lfkdsk/7b3ed8c019334c8817ff1cbb41d9e052 to your computer and use it in GitHub Desktop.
Parser Dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library ebnf_dart; | |
import 'package:dartz/dartz.dart'; | |
Exception mzero() { | |
return Exception('mzero parser fails'); | |
} | |
mixin Parser<Tok, A> { | |
A parse(IList<Tok> input) { | |
throw mzero(); | |
} | |
} | |
class Zero<Tok> with Parser<Tok, Monoid<Unit>> {} | |
class One<Tok> with Parser<Tok, Unit> { | |
@override | |
Unit parse(IList<Tok> input) { | |
if (input.length == 0) { | |
return unit; | |
} | |
throw mzero(); | |
} | |
} | |
typedef check = bool Function<Tok>(Tok a); | |
typedef satisfy = bool Function<Tok>(IList<Tok> a); | |
class Check<Tok> with Parser<Tok, Tok> { | |
check pre; | |
Check(this.pre); | |
// input is [t] | |
@override | |
Tok parse(IList<Tok> input) { | |
if (input.length == 0) { | |
throw mzero(); | |
} | |
if (input.length == 1 || pre(input.headOption)) { | |
return input.headOption | null; | |
} | |
throw mzero(); | |
} | |
} | |
class Satisfy<Tok> with Parser<Tok, IList<Tok>> { | |
satisfy pre; | |
Satisfy(this.pre); | |
@override | |
IList<Tok> parse(IList<Tok> xs) { | |
if (pre(xs)) { | |
return xs; | |
} | |
throw mzero(); | |
} | |
} | |
// parse (Push t x) ts = parse x (t:ts) | |
class Push<Tok, A> with Parser<Tok, A> { | |
Parser<Tok, A> x; | |
Option<Tok> t; | |
Push(this.x, this.t); | |
@override | |
A parse(IList<Tok> ts) { | |
return x.parse(cons(t | null, ts)); | |
} | |
} | |
class Plus<Tok, A, B> with Parser<Tok, Either<A, B>> { | |
Parser<Tok, A> parserA; | |
Parser<Tok, B> parserB; | |
Plus(this.parserA, this.parserB); | |
@override | |
Either<A, B> parse(IList<Tok> input) { | |
return left(parserA.parse(input)) | right(parserB.parse(input)); | |
} | |
} | |
class Times<Tok, A, B> with Parser<Tok, Tuple2<A, B>> { | |
Parser<Tok, A> parserA; | |
Parser<Tok, B> parserB; | |
Times(this.parserA, this.parserB); | |
@override | |
Tuple2<A, B> parse(IList<Tok> input) { | |
if (input == null || input.length == 0) { | |
final IList<Tok> empty = nil(); | |
return tuple2(parserA.parse(empty), parserB.parse(empty)); | |
} | |
Option<Tok> t = input.headOption; | |
Option<IList<Tok>> ts = input.tailOption; | |
Push<Tok, A> push = Push(parserA, t); | |
Times<Tok, A, B> times = Times(push, parserB); | |
Tuple2<A, B> left = times.parse(ts | nil()); | |
} | |
} | |
Option<A> parse<Tok, A>(Parser<Tok, A> parser, List<Tok> a) {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment