static malValuePtr readForm(Tokeniser& tokeniser) { MAL_CHECK(!tokeniser.eof(), "expected form, got EOF"); String token = tokeniser.peek(); MAL_CHECK(!std::regex_match(token, closeRegex), "unexpected '%s'", token.c_str()); if (token == "(") { tokeniser.next(); std::unique_ptr<malValueVec> items(new malValueVec); readList(tokeniser, items.get(), ")"); return mal::list(items.release()); } if (token == "[") { tokeniser.next(); std::unique_ptr<malValueVec> items(new malValueVec); readList(tokeniser, items.get(), "]"); return mal::vector(items.release()); } if (token == "{") { tokeniser.next(); malValueVec items; readList(tokeniser, &items, "}"); return mal::hash(items.begin(), items.end(), false); } return readAtom(tokeniser); }
int main(int argc, char** argv) { Tokeniser* intok; Parser* parser; ifstream* fin; bool verbose = false; string output; string infile; // @neo how does this shit work? int c, prev_ind; while((c = getopt(argc, argv, "vo:")) != EOF) { switch (c) { case 'v': verbose = true; break; case 'o': output = optarg; break; default: cout << "unknown argument: " << char(c) << endl; break; } } if(optind < argc) infile = argv[optind]; fin = new ifstream(infile); if(infile.length() == 0) { intok = new Tokeniser(&cin); } else { intok = new Tokeniser(fin); } ofstream* out = nullptr; if(output.length() > 0) out = new ofstream(output); queue<token> tokenstream; token t; do { t = intok->next(); tokenstream.push(t); if(verbose) cout << t << endl; if(out) *out << t.type << endl << t.str << endl; } while (t.type != token::eof); if(out) delete out; parser = new Parser(); queue<symbol*>* symbol_s = parser->create_symbol_stream(tokenstream); parser->do_parse(symbol_s); return 0; }
static void readList(Tokeniser& tokeniser, malValueVec* items, const String& end) { while (1) { MAL_CHECK(!tokeniser.eof(), "expected '%s', got EOF", end.c_str()); if (tokeniser.peek() == end) { tokeniser.next(); return; } items->push_back(readForm(tokeniser)); } }
static malValuePtr readAtom(Tokeniser& tokeniser) { struct ReaderMacro { const char* token; const char* symbol; }; ReaderMacro macroTable[] = { { "@", "deref" }, { "`", "quasiquote" }, { "'", "quote" }, { "~@", "splice-unquote" }, { "~", "unquote" }, }; struct Constant { const char* token; malValuePtr value; }; Constant constantTable[] = { { "false", mal::falseValue() }, { "nil", mal::nilValue() }, { "true", mal::trueValue() }, }; String token = tokeniser.next(); if (token[0] == '"') { return mal::string(unescape(token)); } if (token[0] == ':') { return mal::keyword(token); } if (token == "^") { malValuePtr meta = readForm(tokeniser); malValuePtr value = readForm(tokeniser); // Note that meta and value switch places return mal::list(mal::symbol("with-meta"), value, meta); } for (auto &constant : constantTable) { if (token == constant.token) { return constant.value; } } for (auto ¯o : macroTable) { if (token == macro.token) { return processMacro(tokeniser, macro.symbol); } } if (std::regex_match(token, intRegex)) { return mal::integer(token); } return mal::symbol(token); }