diff options
author | David Robillard <d@drobilla.net> | 2009-07-04 05:02:09 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-07-04 05:02:09 +0000 |
commit | 7164809b051050fb4f4877793b9739b6177bcab1 (patch) | |
tree | a0ac0ed6731ddf6e453c81a9391566202a6f6c09 /src/tuplr.hpp | |
parent | 9e12b8536648a30377040f407e06ea0713db91b4 (diff) | |
download | resp-7164809b051050fb4f4877793b9739b6177bcab1.tar.gz resp-7164809b051050fb4f4877793b9739b6177bcab1.tar.bz2 resp-7164809b051050fb4f4877793b9739b6177bcab1.zip |
Ditch Exp type and use AST even at lex time.
git-svn-id: http://svn.drobilla.net/resp/tuplr@182 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'src/tuplr.hpp')
-rw-r--r-- | src/tuplr.hpp | 98 |
1 files changed, 37 insertions, 61 deletions
diff --git a/src/tuplr.hpp b/src/tuplr.hpp index 087ce77..54d7098 100644 --- a/src/tuplr.hpp +++ b/src/tuplr.hpp @@ -62,37 +62,6 @@ struct Error { string msg; }; -/// Expression ::= Atom | (Expression*) -template<typename Atom> -struct Exp { - typedef std::vector< Exp<Atom> > Vec; - - Exp(Cursor c) : type(LIST), loc(c), _vec(new Vec()) {} - Exp(Cursor c, const Atom& a) : type(ATOM), loc(c), _atom(a) {} - - enum { ATOM, LIST } type; - - inline const Atom& atom() const { assert(type == ATOM); return _atom; } - - void push_back(const Exp<Atom>& exp) { assert(type == LIST); _vec->push_back(exp); } - - bool empty() const { assert(type == LIST); return _vec->empty(); } - const Exp<Atom>& front() const { assert(type == LIST); return _vec->front(); } - - typedef typename Vec::const_iterator const_iterator; - const_iterator begin() const { assert(type == LIST); return _vec->begin(); } - const_iterator end() const { assert(type == LIST); return _vec->end(); } - - Cursor loc; - -private: - Atom _atom; - Vec* _vec; -}; - -template<typename Atom> -extern ostream& operator<<(ostream& out, const Exp<Atom>& exp); - /// Lexical Address struct LAddr { LAddr(unsigned u=0, unsigned o=0) : up(u), over(o) {} @@ -143,10 +112,9 @@ struct Env : public list< vector< pair<K,V> > > { * Lexer: Text (istream) -> S-Expressions (SExp) * ***************************************************************************/ -class AString; -typedef Exp<AString*> SExp; ///< Textual S-Expression +class AST; +AST* readExpression(Cursor& cur, std::istream& in); -SExp readExpression(Cursor& cur, std::istream& in); /*************************************************************************** @@ -290,9 +258,9 @@ private: /// Tuple (heterogeneous sequence of fixed length), e.g. "(a b c)" struct ATuple : public AST { ATuple(Cursor c) : AST(c), _len(0), _vec(0) {} - ATuple(Cursor c, const ATuple& t) : AST(c), _len(t._len) { + ATuple(const ATuple& exp) : AST(exp.loc), _len(exp._len) { _vec = (AST**)malloc(sizeof(AST*) * _len); - memcpy(_vec, t._vec, sizeof(AST*) * _len); + memcpy(_vec, exp._vec, sizeof(AST*) * _len); } ATuple(Cursor c, AST* ast, va_list args) : AST(c), _len(0), _vec(0) { if (!ast) return; @@ -306,6 +274,7 @@ struct ATuple : public AST { newvec[_len++] = ast; _vec = newvec; } + const AST* front() const { assert(_len > 0); return _vec[0]; } const AST* at(size_t i) const { assert(i < _len); return _vec[i]; } AST*& at(size_t i) { assert(i < _len); return _vec[i]; } size_t size() const { return _len; } @@ -456,7 +425,7 @@ struct AFn : public ATuple { /// Function call/application, e.g. "(func arg1 arg2)" struct ACall : public ATuple { - ACall(const SExp& e, const ATuple& t) : ATuple(e.loc, t) {} + ACall(const ATuple* exp) : ATuple(*exp) {} ACall(Cursor c, AST* ast, va_list args) : ATuple(c, ast, args) {} void constrain(TEnv& tenv, Constraints& c) const; AST* cps(TEnv& tenv, AST* cont); @@ -466,7 +435,7 @@ struct ACall : public ATuple { /// Definition special form, e.g. "(def x 2)" struct ADef : public ACall { - ADef(const SExp& e, const ATuple& t) : ACall(e, t) {} + ADef(const ATuple* exp) : ACall(exp) {} ADef(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {} const ASymbol* sym() const { const ASymbol* sym = at(1)->to<const ASymbol*>(); @@ -485,7 +454,7 @@ struct ADef : public ACall { /// Conditional special form, e.g. "(if cond thenexp elseexp)" struct AIf : public ACall { - AIf(const SExp& e, const ATuple& t) : ACall(e, t) {} + AIf(const ATuple* exp) : ACall(exp) {} AIf(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {} void constrain(TEnv& tenv, Constraints& c) const; AST* cps(TEnv& tenv, AST* cont); @@ -494,7 +463,7 @@ struct AIf : public ACall { /// Primitive (builtin arithmetic function), e.g. "(+ 2 3)" struct APrimitive : public ACall { - APrimitive(const SExp& e, const ATuple& t) : ACall(e, t) {} + APrimitive(const ATuple* exp) : ACall(exp) {} bool value() const { ATuple::const_iterator i = begin(); for (++i; i != end(); ++i) @@ -515,8 +484,8 @@ struct APrimitive : public ACall { /// Parse Time Environment (really just a symbol table) struct PEnv : private map<const string, ASymbol*> { PEnv() : symID(0) {} - typedef AST* (*PF)(PEnv&, const SExp&, void*); ///< Parse Function - typedef SExp (*MF)(PEnv&, const SExp&); ///< Macro Function + typedef AST* (*PF)(PEnv&, const AST*, void*); ///< Parse Function + typedef AST* (*MF)(PEnv&, const AST*); ///< Macro Function struct Handler { Handler(PF f, void* a=0) : func(f), arg(a) {} PF func; void* arg; }; map<const string, Handler> aHandlers; ///< Atom parse functions map<const string, Handler> lHandlers; ///< List parse functions @@ -548,36 +517,43 @@ struct PEnv : private map<const string, ASymbol*> { return sym; } } - ATuple parseTuple(const SExp& e) { - ATuple ret(e.loc); - FOREACH(SExp::const_iterator, i, e) - ret.push_back(parse(*i)); + ATuple* parseTuple(const ATuple* e) { + ATuple* ret = new ATuple(e->loc); + FOREACH(ATuple::const_iterator, i, *e) + ret->push_back(parse(*i)); return ret; } - AST* parse(const SExp& exp) { - if (exp.type == SExp::LIST) { - if (exp.empty()) throw Error(exp.loc, "call to empty list"); - if (exp.front().type == SExp::ATOM) { - MF mf = mac(*exp.front().atom()); - SExp expanded = (mf ? mf(*this, exp) : exp); - - const PEnv::Handler* h = handler(true, *expanded.front().atom()); + AST* 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->front()->to<const ATuple*>()) { + const AString* str = tup->front()->to<const AString*>(); + assert(str); + MF mf = mac(*str); + const AST* expanded = (mf ? mf(*this, exp) : exp); + const ATuple* expanded_tup = expanded->to<const ATuple*>(); + const PEnv::Handler* h = handler(true, *expanded_tup->front()->to<const AString*>()); if (h) return h->func(*this, expanded, h->arg); } - return new ACall(exp, parseTuple(exp)); // Parse as regular call - } else if (isdigit((*exp.atom())[0])) { - const std::string& s = *exp.atom(); + ATuple* parsed_tup = parseTuple(tup); // FIXME: leak + return new ACall(parsed_tup); // Parse as regular call + } + const AString* str = exp->to<const AString*>(); + assert(str); + if (isdigit((*str)[0])) { + const std::string& s = *str; if (s.find('.') == string::npos) - return new ALiteral<int32_t>(strtol(s.c_str(), NULL, 10), exp.loc); + 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); + return new ALiteral<float>(strtod(s.c_str(), NULL), exp->loc); } else { - const PEnv::Handler* h = handler(false, *exp.atom()); + const PEnv::Handler* h = handler(false, *str); if (h) return h->func(*this, exp, h->arg); } - return sym(*exp.atom(), exp.loc); + return sym(*exp->to<const AString*>(), exp->loc); } unsigned symID; }; |