diff options
Diffstat (limited to 'src/parse.cpp')
-rw-r--r-- | src/parse.cpp | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/src/parse.cpp b/src/parse.cpp index 2c59c56..3184f8a 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -23,6 +23,50 @@ using namespace std; +ATuple* +parseTuple(PEnv& penv, const ATuple* e) +{ + ATuple* ret = new ATuple(e->loc); + FOREACHP(ATuple::const_iterator, i, e) + ret->push_back(penv.parse(*i)); + return ret; +} + +AST* +PEnv::parse(const AST* exp) +{ + const ATuple* tup = exp->to<const ATuple*>(); + if (tup) { + if (tup->empty()) throw Error(exp->loc, "call to empty list"); + if (!tup->head()->to<const ATuple*>()) { + MF mf = mac(*tup->head()->to<const ALexeme*>()); + const AST* expanded = (mf ? mf(*this, exp) : exp); + const ATuple* expanded_tup = expanded->to<const ATuple*>(); + const PEnv::Handler* h = handler(true, *expanded_tup->head()->to<const ALexeme*>()); + if (h) + return h->func(*this, expanded, h->arg); + } + ATuple* parsed_tup = parseTuple(*this, tup); + return new ACall(parsed_tup); // Parse as regular call + } + const ALexeme* lex = exp->to<const ALexeme*>(); + assert(lex); + if (isdigit((*lex)[0])) { + const std::string& s = *lex; + if (s.find('.') == string::npos) + return new ALiteral<int32_t>(strtol(s.c_str(), NULL, 10), exp->loc); + else + return new ALiteral<float>(strtod(s.c_str(), NULL), exp->loc); + } else if ((*lex)[0] == '\"') { + return new AString(exp->loc, lex->substr(1, lex->length() - 2)); + } else { + const PEnv::Handler* h = handler(false, *lex); + if (h) + return h->func(*this, exp, h->arg); + } + return sym(*lex, exp->loc); +} + /*************************************************************************** * Macro Functions * @@ -69,7 +113,7 @@ template<typename C> inline AST* parseCall(PEnv& penv, const AST* exp, void* arg) { - return new C(penv.parseTuple(exp->to<const ATuple*>())); + return new C(parseTuple(penv, exp->to<const ATuple*>())); } template<typename T> @@ -85,7 +129,7 @@ parseFn(PEnv& penv, const AST* exp, void* arg) const ATuple* texp = exp->to<const ATuple*>(); ATuple::const_iterator a = texp->begin(); THROW_IF(++a == texp->end(), exp->loc, "Unexpected end of `fn' form"); - ATuple* prot = penv.parseTuple((*a++)->to<const ATuple*>()); + ATuple* prot = parseTuple(penv, (*a++)->to<const ATuple*>()); AFn* ret = tup<AFn>(exp->loc, penv.sym("fn"), prot, 0); while (a != texp->end()) ret->push_back(penv.parse(*a++)); |