Skip to content

Instantly share code, notes, and snippets.

@lfkdsk
Created July 1, 2019 12:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lfkdsk/7b3ed8c019334c8817ff1cbb41d9e052 to your computer and use it in GitHub Desktop.
Save lfkdsk/7b3ed8c019334c8817ff1cbb41d9e052 to your computer and use it in GitHub Desktop.
Parser Dart
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