diff options
-rw-r--r-- | llvm.cpp | 4 | ||||
-rw-r--r-- | tuplr.hpp | 71 |
2 files changed, 33 insertions, 42 deletions
@@ -514,7 +514,7 @@ eval(CEnv& cenv, const string& name, istream& is) if (exp.type == SExp::LIST && exp.list.empty()) break; - result = parseExpression(cenv.penv, exp); // Parse input + result = cenv.penv.parse(exp); // Parse input result->constrain(cenv.tenv); // Constrain types cenv.tenv.solve(); // Solve and apply type constraints resultType = cenv.tenv.type(result); @@ -560,7 +560,7 @@ repl(CEnv& cenv) if (exp.type == SExp::LIST && exp.list.empty()) break; - AST* body = parseExpression(cenv.penv, exp); // Parse input + AST* body = cenv.penv.parse(exp); // Parse input body->constrain(cenv.tenv); // Constrain types cenv.tenv.solve(); // Solve and apply type constraints @@ -321,51 +321,42 @@ struct PEnv : private map<const string, ASymbol*> { ? i->second : insert(make_pair(s, new ASymbol(s, c))).first->second); } -}; - -/// The fundamental parser method -static AST* parseExpression(PEnv& penv, const SExp& exp); - -static ATuple -pmap(PEnv& penv, const SExp& e) -{ - assert(e.type == SExp::LIST); - ATuple ret(e.list.size(), e.loc); - size_t n = 0; - FOREACH(SExp::List::const_iterator, i, e.list) - ret[n++] = parseExpression(penv, *i); - return ret; -} - -static AST* -parseExpression(PEnv& penv, const SExp& exp) -{ - if (exp.type == SExp::LIST) { - if (exp.list.empty()) throw Error("call to empty list", exp.loc); - if (exp.list.front().type == SExp::ATOM) { - const PEnv::Handler* handler = penv.handler(true, exp.list.front().atom); - if (handler) // Dispatch to list parse function - return handler->func(penv, exp, handler->arg); + ATuple parseTuple(const SExp& e) { + ATuple ret(e.list.size(), e.loc); + size_t n = 0; + FOREACH(SExp::List::const_iterator, i, e.list) + ret[n++] = parse(*i); + return ret; + } + AST* parse(const SExp& exp) { + if (exp.type == SExp::LIST) { + if (exp.list.empty()) throw Error("call to empty list", exp.loc); + if (exp.list.front().type == SExp::ATOM) { + const PEnv::Handler* h = handler(true, exp.list.front().atom); + if (h) + return h->func(*this, exp, h->arg); + } + return new ACall(exp, parseTuple(exp)); // Parse as regular call + } else if (isdigit(exp.atom[0])) { + if (exp.atom.find('.') == string::npos) + return new ALiteral<int32_t>(strtol(exp.atom.c_str(), NULL, 10), exp.loc); + else + return new ALiteral<float>(strtod(exp.atom.c_str(), NULL), exp.loc); + } else { + const PEnv::Handler* h = handler(false, exp.atom); + if (h) + return h->func(*this, exp, h->arg); } - return new ACall(exp, pmap(penv, exp)); // Parse as regular call - } else if (isdigit(exp.atom[0])) { - if (exp.atom.find('.') == string::npos) - return new ALiteral<int32_t>(strtol(exp.atom.c_str(), NULL, 10), exp.loc); - else - return new ALiteral<float>(strtod(exp.atom.c_str(), NULL), exp.loc); - } else { - const PEnv::Handler* handler = penv.handler(false, exp.atom); - if (handler) // Dispatch to atom parse function - return handler->func(penv, exp, handler->arg); + return sym(exp.atom, exp.loc); } - return penv.sym(exp.atom, exp.loc); -} +}; + template<typename C> inline AST* parseCall(PEnv& penv, const SExp& exp, void* arg) { - return new C(exp, pmap(penv, exp)); + return new C(exp, penv.parseTuple(exp)); } template<typename T> @@ -380,8 +371,8 @@ parseFn(PEnv& penv, const SExp& exp, void* arg) { SExp::List::const_iterator a = exp.list.begin(); ++a; return new AClosure(exp.loc, penv.sym("fn"), - new ATuple(pmap(penv, *a++)), - parseExpression(penv, *a++)); + new ATuple(penv.parseTuple(*a++)), + penv.parse(*a++)); } |