diff options
Diffstat (limited to 'src/parse.cpp')
-rw-r--r-- | src/parse.cpp | 122 |
1 files changed, 32 insertions, 90 deletions
diff --git a/src/parse.cpp b/src/parse.cpp index 81aaa83..3fb8375 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -16,7 +16,7 @@ */ /** @file - * @brief Parsing (build a code AST from a textual AST) + * @brief Expand built-in macros (i.e. def) */ #include "resp.hpp" @@ -24,7 +24,7 @@ using namespace std; const ATuple* -parseTuple(PEnv& penv, const ATuple* e) +parseList(PEnv& penv, const ATuple* e) { List<ATuple, const AST> ret; FOREACHP(ATuple::const_iterator, i, e) @@ -32,84 +32,19 @@ parseTuple(PEnv& penv, const ATuple* e) return ret.head; } -const AST* -PEnv::parse(const AST* exp) -{ - const ATuple* tup = exp->to_tuple(); - if (tup) { - THROW_IF(tup->empty(), exp->loc, "Call to empty list"); - const ALexeme* form = tup->head()->to_lexeme(); - if (form) { - if (isupper(form->cppstr.c_str()[0])) // Call constructor (any uppercase symbol) - return parseTuple(*this, tup); - - const PEnv::Handler* h = handler(form->cppstr); - if (h) - return h->func(*this, exp, h->arg); // Parse special form - } - - return parseTuple(*this, tup); // Parse regular call - } - - const ALexeme* lex = exp->to_lexeme(); - assert(lex); - if (isdigit(lex->cppstr[0])) { - const std::string& s = lex->cppstr; - if (s.find('.') == string::npos) - return new ALiteral<int32_t>(T_INT32, strtol(s.c_str(), NULL, 10), exp->loc); - else - return new ALiteral<float>(T_FLOAT, strtod(s.c_str(), NULL), exp->loc); - } else if (lex->cppstr[0] == '\"') { - return new AString(exp->loc, lex->cppstr.substr(1, lex->cppstr.length() - 2)); - } else if (lex->cppstr == "#t") { - return new ALiteral<bool>(T_BOOL, true, exp->loc); - } else if (lex->cppstr == "#f") { - return new ALiteral<bool>(T_BOOL, false, exp->loc); - } - return sym(lex->cppstr, exp->loc); -} - - -/*************************************************************************** - * Parser Functions * - ***************************************************************************/ - -inline const AST* -parseCall(PEnv& penv, const AST* exp, void* arg) -{ - return parseTuple(penv, exp->to_tuple()); -} - -inline const AST* -parseBool(PEnv& penv, const AST* exp, void* arg) -{ - return new ALiteral<bool>(T_BOOL, *reinterpret_cast<bool*>(arg), exp->loc); -} - inline const AST* parseFn(PEnv& penv, const AST* exp, void* arg) { - const ATuple* texp = exp->to_tuple(); - ATuple::const_iterator a = texp->begin(); - THROW_IF(++a == texp->end(), exp->loc, "Unexpected end of `fn' form"); - const ATuple* prot = parseTuple(penv, (*a++)->to_tuple()); - List<ATuple, const AST> ret(new ATuple(penv.sym("fn"), NULL, Cursor())); + const ATuple* tup = exp->to_tuple(); + ATuple::const_iterator a = tup->begin(); + THROW_IF(++a == tup->end(), exp->loc, "Unexpected end of `fn' form"); + THROW_IF(!(*a)->to_tuple(), (*a)->loc, "First argument of `fn' is not a list"); + const ATuple* prot = (*a++)->to_tuple(); + List<ATuple, const AST> ret(new ATuple(penv.sym("fn"), NULL, exp->loc)); ret.push_back(prot); - while (a != texp->end()) + while (a != tup->end()) ret.push_back(penv.parse(*a++)); - ret.head->loc = exp->loc; - return new ATuple(*ret.head); -} - -inline const AST* -parseQuote(PEnv& penv, const AST* exp, void* arg) -{ - const ATuple* texp = exp->to_tuple(); - THROW_IF(texp->list_len() != 2, exp->loc, "`quote' requires exactly 1 argument"); - const ALexeme* quotee = texp->list_ref(1)->to_lexeme(); - THROW_IF(!quotee, exp->loc, "`quote' argument is not a lexeme"); - ATuple* ret = tup<ATuple>(texp->loc, penv.sym("quote"), quotee, NULL); - return ret; + return ret.head; } inline const AST* @@ -121,8 +56,8 @@ parseDef(PEnv& penv, const AST* exp, void* arg) THROW_IF(i == tup->end(), tup->loc, "Unexpected end of `def' form"); const AST* arg1 = *(++i); THROW_IF(i == tup->end(), arg1->loc, "Unexpected end of `def' form"); - if (arg1->to_lexeme()) { - return parseCall(penv, exp, arg); + if (arg1->to_symbol()) { + return parseList(penv, tup); } else { // (def (f x) y) => (def f (fn (x) y)) const ATuple* pat = arg1->to_tuple(); @@ -135,7 +70,7 @@ parseDef(PEnv& penv, const AST* exp, void* arg) const AST* body = *(++i); List<ATuple, const AST> fnExp; - fnExp.push_back(new ALexeme(exp->loc, "fn")); + fnExp.push_back(penv.sym("fn")); fnExp.push_back(argsExp.head); for (; i != tup->end(); ++i) fnExp.push_back(*i); @@ -147,10 +82,28 @@ parseDef(PEnv& penv, const AST* exp, void* arg) ret.push_back(fnExp.head); ret.head->loc = exp->loc; - return parseCall(penv, ret.head, arg); + return parseList(penv, ret.head); } } +const AST* +PEnv::parse(const AST* exp) +{ + const ATuple* tup = exp->to_tuple(); + if (!tup) + return exp; + + THROW_IF(tup->empty(), exp->loc, "Call to empty list"); + + if (is_form(tup, "def")) + return parseDef(*this, exp, NULL); + else if (is_form(tup, "fn")) + return parseFn(*this, exp, NULL); + else + return parseList(*this, tup); +} + + /*************************************************************************** * Language Definition * @@ -168,15 +121,6 @@ initLang(PEnv& penv, TEnv& tenv) tenv.def(penv.sym("Quote"), new AType(penv.sym("Quote"), AType::PRIM)); tenv.def(penv.sym("String"), new AType(penv.sym("String"), AType::PRIM)); - // Special forms - penv.reg(".", PEnv::Handler(parseCall)); - penv.reg("def", PEnv::Handler(parseDef)); - penv.reg("def-type", PEnv::Handler(parseCall)); - penv.reg("fn", PEnv::Handler(parseFn)); - penv.reg("if", PEnv::Handler(parseCall)); - penv.reg("match", PEnv::Handler(parseCall)); - penv.reg("quote", PEnv::Handler(parseQuote)); - // Numeric primitives penv.primitives.insert("+"); penv.primitives.insert("-"); @@ -192,6 +136,4 @@ initLang(PEnv& penv, TEnv& tenv) penv.primitives.insert(">="); penv.primitives.insert("<"); penv.primitives.insert("<="); - FOREACH (PEnv::Primitives::const_iterator, i, penv.primitives) - penv.reg(*i, PEnv::Handler(parseCall)); } |