diff options
author | David Robillard <d@drobilla.net> | 2009-03-06 02:57:57 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-03-06 02:57:57 +0000 |
commit | 2f1797c685202d88c93a73de8dfbb2c6d6da87b3 (patch) | |
tree | 597e07baacadcfe44cacb7ac05c64e9a427a35f0 /tuplr.hpp | |
parent | 7c1ea0948d9b43bfb7a86aa356eea04c1b9649ae (diff) | |
download | resp-2f1797c685202d88c93a73de8dfbb2c6d6da87b3.tar.gz resp-2f1797c685202d88c93a73de8dfbb2c6d6da87b3.tar.bz2 resp-2f1797c685202d88c93a73de8dfbb2c6d6da87b3.zip |
More generic parser function mechanism that works for atoms too.
Use atom parser methods to parse literals.
Remove the last of the language and backend specific things from core code.
git-svn-id: http://svn.drobilla.net/resp/tuplr@56 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'tuplr.hpp')
-rw-r--r-- | tuplr.hpp | 58 |
1 files changed, 33 insertions, 25 deletions
@@ -31,6 +31,7 @@ typedef const void* CType; ///< Compiled type (opaque) typedef void* CFunction; ///< Compiled function (opaque) struct CEngine; ///< Backend data (opaque) +struct CArg; ///< Parser function argument (opaque) #define FOREACH(IT, i, c) for (IT i = (c).begin(); i != (c).end(); ++i) @@ -55,8 +56,6 @@ struct Error { Cursor loc; }; -struct CArg { CArg(int o=0, int a=0) : op(o), arg(a) {} int op; int arg; }; - template<typename Atom> struct Exp { // ::= Atom | (Exp*) Exp(Cursor c) : type(LIST), loc(c) {} @@ -245,7 +244,7 @@ struct ASTCall : public ASTTuple { /// Definition special form, e.g. "(def x 2)" struct ASTDefinition : public ASTCall { - ASTDefinition(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTDefinition(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; void lift(CEnv& cenv); CValue compile(CEnv& cenv); @@ -253,22 +252,22 @@ struct ASTDefinition : public ASTCall { /// Conditional special form, e.g. "(if cond thenexp elseexp)" struct ASTIf : public ASTCall { - ASTIf(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTIf(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); }; /// Primitive (builtin arithmetic function), e.g. "(+ 2 3)" struct ASTPrimitive : public ASTCall { - ASTPrimitive(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t), arg(ca) {} + ASTPrimitive(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t), arg(ca) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); - CArg arg; + CArg* arg; }; /// Cons special form, e.g. "(cons 1 2)" struct ASTConsCall : public ASTCall { - ASTConsCall(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTConsCall(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} AType* functionType(CEnv& cenv); void constrain(TEnv& tenv) const; void lift(CEnv& cenv); @@ -278,14 +277,14 @@ struct ASTConsCall : public ASTCall { /// Car special form, e.g. "(car p)" struct ASTCarCall : public ASTCall { - ASTCarCall(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTCarCall(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); }; /// Cdr special form, e.g. "(cdr p)" struct ASTCdrCall : public ASTCall { - ASTCdrCall(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTCdrCall(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); }; @@ -297,15 +296,17 @@ struct ASTCdrCall : public ASTCall { // Parse Time Environment (symbol table) struct PEnv : private map<const string, ASTSymbol*> { - typedef AST* (*PF)(PEnv&, const SExp&, CArg); // Parse Function - struct Parser { Parser(PF f, CArg a=CArg()) : func(f), arg(a) {} PF func; CArg arg; }; - map<string, Parser> parsers; - void reg(const string& s, const Parser& p) { - parsers.insert(make_pair(sym(s)->str(), p)); + typedef AST* (*PF)(PEnv&, const SExp&, CArg*); // Parse Function + struct Handler { Handler(PF f, CArg* a=0) : func(f), arg(a) {} PF func; CArg* arg; }; + map<const string, Handler> aHandlers; ///< Atom parse functions + map<const string, Handler> lHandlers; ///< List parse functions + void reg(bool list, const string& s, const Handler& h) { + (list ? lHandlers : aHandlers).insert(make_pair(sym(s)->str(), h)); } - const Parser* parser(const string& s) const { - map<string, Parser>::const_iterator i = parsers.find(s); - return (i != parsers.end()) ? &i->second : NULL; + const Handler* handler(bool list, const string& s) const { + const map<const string, Handler>& handlers = list ? lHandlers : aHandlers; + map<string, Handler>::const_iterator i = handlers.find(s); + return (i != handlers.end()) ? &i->second : NULL; } ASTSymbol* sym(const string& s, Cursor c=Cursor()) { const const_iterator i = find(s); @@ -334,8 +335,8 @@ 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::Parser* handler = penv.parser(exp.list.front().atom); - if (handler) // Dispatch to parse function + 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); } return new ASTCall(exp, pmap(penv, exp.list)); // Parse as regular call @@ -344,23 +345,30 @@ parseExpression(PEnv& penv, const SExp& exp) return new ASTLiteral<int32_t>(strtol(exp.atom.c_str(), NULL, 10)); else return new ASTLiteral<float>(strtod(exp.atom.c_str(), NULL)); - } else if (exp.atom == "true") { - return new ASTLiteral<bool>(true); - } else if (exp.atom == "false") { - return new ASTLiteral<bool>(false); + } 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 penv.sym(exp.atom, exp.loc); } template<typename C> inline AST* -parseAST(PEnv& penv, const SExp& exp, CArg arg=CArg()) +parseCall(PEnv& penv, const SExp& exp, CArg* arg) { return new C(exp, pmap(penv, exp.list), arg); } +template<typename T> +inline AST* +parseLiteral(PEnv& penv, const SExp& exp, CArg* arg) +{ + return new ASTLiteral<T>(*reinterpret_cast<T*>(arg)); +} + inline AST* -parseFn(PEnv& penv, const SExp& exp, CArg arg) +parseFn(PEnv& penv, const SExp& exp, CArg* arg) { SExp::List::const_iterator a = exp.list.begin(); ++a; return new ASTClosure( |