aboutsummaryrefslogtreecommitdiffstats
path: root/tuplr.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-03-06 02:57:57 +0000
committerDavid Robillard <d@drobilla.net>2009-03-06 02:57:57 +0000
commit2f1797c685202d88c93a73de8dfbb2c6d6da87b3 (patch)
tree597e07baacadcfe44cacb7ac05c64e9a427a35f0 /tuplr.hpp
parent7c1ea0948d9b43bfb7a86aa356eea04c1b9649ae (diff)
downloadresp-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.hpp58
1 files changed, 33 insertions, 25 deletions
diff --git a/tuplr.hpp b/tuplr.hpp
index d769982..ba4f9a9 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -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(