aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cpp')
-rw-r--r--src/parse.cpp122
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));
}