Skip to content

Instantly share code, notes, and snippets.

@olexale
Created May 27, 2023 11:03
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 olexale/ee9dbfcc37981a0cbbb9293cd57e84cf to your computer and use it in GitHub Desktop.
Save olexale/ee9dbfcc37981a0cbbb9293cd57e84cf to your computer and use it in GitHub Desktop.
scheme dart 1
Future<void> main() async {
// final program = '(define x 42)';
final program = '(begin (define circle-area (lambda (r) (* pi (* r r)))) (circle-area 10))';
print(parse(program));
}
dynamic parse(String program) => parseTokens(tokenize(program));
List<String> tokenize(String program) => program
.replaceAll('(', ' ( ')
.replaceAll(')', ' ) ')
.split(' ')
.where((token) => token.isNotEmpty)
.toList();
dynamic parseTokens(List<String> tokens) {
if (tokens.isEmpty) {
throw Exception('Unexpected EOF');
}
final token = tokens.removeAt(0);
if (token == '(') {
final elements = <dynamic>[];
while (tokens.first != ')') {
elements.add(parseTokens(tokens));
if (tokens.isEmpty) {
throw Exception('Unexpected EOF');
}
}
tokens.removeAt(0); // remove ')'
return elements;
} else if (token == ')') {
throw Exception('Unexpected ")"');
} else {
return _atom(token);
}
}
dynamic _atom(String token) {
// parse doubles
final d = double.tryParse(token);
if (d != null) {
return d;
}
// parse booleans
if (token == '#t') {
return true;
}
if (token == '#f') {
return false;
}
// parse strings
if (token.startsWith('"') && token.endsWith('"')) {
return token.substring(1, token.length - 1);
}
return Symbol(token);
}
class Symbol {
const Symbol(this.name);
final String name;
@override
String toString() => name;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Symbol && runtimeType == other.runtimeType && name == other.name;
@override
int get hashCode => name.hashCode;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment