diff options
Diffstat (limited to 'tuplr.hpp')
-rw-r--r-- | tuplr.hpp | 71 |
1 files changed, 31 insertions, 40 deletions
@@ -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++)); } |