platform/packages/combinator/example/sexp.dart

85 lines
2.3 KiB
Dart
Raw Normal View History

2021-03-17 23:04:36 +00:00
import 'dart:collection';
import 'dart:io';
import 'dart:math';
2021-05-14 06:11:50 +00:00
import 'package:angel3_combinator/angel3_combinator.dart';
2021-03-17 23:04:36 +00:00
import 'package:string_scanner/string_scanner.dart';
import 'package:tuple/tuple.dart';
void main() {
var expr = reference();
var symbols = <String, dynamic>{};
void registerFunction(String name, int nArgs, Function(List<num>) f) {
2021-05-14 06:11:50 +00:00
symbols[name] = Tuple2(nArgs, f);
2021-03-17 23:04:36 +00:00
}
registerFunction('**', 2, (args) => pow(args[0], args[1]));
registerFunction('*', 2, (args) => args[0] * args[1]);
registerFunction('/', 2, (args) => args[0] / args[1]);
registerFunction('%', 2, (args) => args[0] % args[1]);
registerFunction('+', 2, (args) => args[0] + args[1]);
registerFunction('-', 2, (args) => args[0] - args[1]);
registerFunction('.', 1, (args) => args[0].toDouble());
registerFunction('print', 1, (args) {
print(args[0]);
return args[0];
});
2021-05-14 06:11:50 +00:00
var number =
match(RegExp(r'[0-9]+(\.[0-9]+)?'), errorMessage: 'Expected a number.')
.map((r) => num.parse(r.span!.text));
2021-03-17 23:04:36 +00:00
var id = match(
2021-05-14 06:11:50 +00:00
RegExp(
2021-03-17 23:04:36 +00:00
r'[A-Za-z_!\\$",\\+-\\./:;\\?<>%&\\*@\[\]\\{\}\\|`\\^~][A-Za-z0-9_!\\$",\\+-\\./:;\\?<>%&\*@\[\]\\{\}\\|`\\^~]*'),
errorMessage: 'Expected an ID')
2021-05-02 04:12:43 +00:00
.map((r) => symbols[r.span!.text] ??=
throw "Undefined symbol: '${r.span!.text}'");
2021-03-17 23:04:36 +00:00
var atom = number.castDynamic().or(id);
var list = expr.space().times(2, exact: false).map((r) {
try {
var out = [];
2021-05-14 06:11:50 +00:00
var q = Queue.from(r.value!.reversed);
2021-03-17 23:04:36 +00:00
while (q.isNotEmpty) {
var current = q.removeFirst();
if (current is! Tuple2)
out.insert(0, current);
else {
var args = [];
for (int i = 0; i < (current.item1 as num); i++)
args.add(out.removeLast());
out.add(current.item2(args));
}
}
return out.length == 1 ? out.first : out;
} catch (_) {
return [];
}
});
expr.parser = longest([
list,
atom,
expr.parenthesized(),
]); //list | atom | expr.parenthesized();
while (true) {
stdout.write('> ');
2021-03-18 00:00:56 +00:00
var line = stdin.readLineSync()!;
2021-05-14 06:11:50 +00:00
var result = expr.parse(SpanScanner(line));
2021-03-17 23:04:36 +00:00
if (result.errors.isNotEmpty) {
for (var error in result.errors) {
print(error.toolString);
print(error.message);
}
} else {
print(result.value);
}
}
}