diff options
-rw-r--r-- | context.cc | 6 | ||||
-rw-r--r-- | expr.cc | 40 | ||||
-rw-r--r-- | func.cc | 36 | ||||
-rw-r--r-- | module.cc | 69 | ||||
-rw-r--r-- | openscad.cc | 9 | ||||
-rw-r--r-- | openscad.h | 46 | ||||
-rw-r--r-- | parser.y | 17 | ||||
-rw-r--r-- | value.cc | 57 |
8 files changed, 239 insertions, 41 deletions
@@ -37,7 +37,7 @@ void Context::args(const QVector<QString> &argnames, const QVector<Expression*> } } -Value Context::lookup_variable(QString name) +Value Context::lookup_variable(QString name) const { if (variables.contains(name)) return variables[name]; @@ -46,7 +46,7 @@ Value Context::lookup_variable(QString name) return Value(); } -Value Context::evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) +Value Context::evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const { if (functions_p->contains(name)) return functions_p->value(name)->evaluate(this, argnames, argvalues); @@ -55,7 +55,7 @@ Value Context::evaluate_function(QString name, const QVector<QString> &argnames, return Value(); } -AbstractNode *Context::evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) +AbstractNode *Context::evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const { if (modules_p->contains(name)) return modules_p->value(name)->evaluate(this, argnames, argvalues); @@ -31,7 +31,7 @@ Expression::~Expression() delete children[i]; } -Value Expression::evaluate(Context *context) +Value Expression::evaluate(const Context *context) const { switch (type) { @@ -50,6 +50,8 @@ Value Expression::evaluate(Context *context) case 'C': return const_value; case 'V': + return Value(children[0]->evaluate(context), children[1]->evaluate(context), children[2]->evaluate(context)); + case 'L': return context->lookup_variable(var_name); case 'F': { @@ -59,7 +61,41 @@ Value Expression::evaluate(Context *context) return context->evaluate_function(call_funcname, call_argnames, argvalues); } default: - return Value(); + abort(); + } +} + +QString Expression::dump() const +{ + switch (type) + { + case '*': + case '/': + case '%': + case '+': + case '-': + return QString("(%1%2%3)").arg(children[0]->dump(), QString(type), children[1]->dump()); + case 'I': + return QString("(-%1)").arg(children[0]->dump()); + case 'C': + return const_value.dump(); + case 'V': + return QString("[%1, %2, %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump()); + case 'L': + return var_name; + case 'F': + { + QString text = call_funcname + QString("("); + for (int i=0; i < children.size(); i++) { + if (i > 0) + text += QString(", "); + if (!call_argnames[i].isEmpty()) + text += call_argnames[i] + QString(" = "); + text += children[i]->dump(); + } + } + default: + abort(); } } @@ -19,28 +19,49 @@ */ #include "openscad.h" -#include <math.h> AbstractFunction::~AbstractFunction() { } -Value AbstractFunction::evaluate(Context*, const QVector<QString>&, const QVector<Value>&) +Value AbstractFunction::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&) const { return Value(); } +QString AbstractFunction::dump(QString indent, QString name) const +{ + return QString("%1abstract function %2();\n").arg(indent, name); +} + Function::~Function() { for (int i=0; i < argexpr.size(); i++) delete argexpr[i]; + delete expr; } -Value Function::evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) +Value Function::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const { Context c(ctx); c.args(argnames, argexpr, call_argnames, call_argvalues); - return expr.evaluate(&c); + if (expr) + return expr->evaluate(&c); + return Value(); +} + +QString Function::dump(QString indent, QString name) const +{ + QString text = QString("%1function %2(").arg(indent, name); + for (int i=0; i < argnames.size(); i++) { + if (i > 0) + text += QString(", "); + text += argnames[i]; + if (argexpr[i]) + text += QString(" = ") + argexpr[i]->dump(); + } + text += QString(")\n%1\t%2;\n").arg(indent, expr->dump()); + return text; } QHash<QString, AbstractFunction*> builtin_functions; @@ -49,11 +70,16 @@ BuiltinFunction::~BuiltinFunction() { } -Value BuiltinFunction::evaluate(Context*, const QVector<QString>&, const QVector<Value> &call_argvalues) +Value BuiltinFunction::evaluate(const Context*, const QVector<QString>&, const QVector<Value> &call_argvalues) const { return eval_func(call_argvalues); } +QString BuiltinFunction::dump(QString indent, QString name) const +{ + return QString("%1builtin function %2();\n").arg(indent, name); +} + Value builtin_sin(const QVector<Value> &args) { if (args[0].is_nan || args[0].is_vector) @@ -24,17 +24,43 @@ AbstractModule::~AbstractModule() { } -AbstractNode *AbstractModule::evaluate(Context*, const QVector<QString>&, const QVector<Value>&) +AbstractNode *AbstractModule::evaluate(const Context*, const QVector<QString>&, const QVector<Value>&) const { return NULL; } +QString AbstractModule::dump(QString indent, QString name) const +{ + return QString("%1abstract module %2();\n").arg(indent, name); +} + ModuleInstanciation::~ModuleInstanciation() { foreach (Expression *v, argexpr) delete v; } +QString ModuleInstanciation::dump(QString indent) const +{ + QString text = indent; + if (!label.isEmpty()) + text += label + QString(": "); + text += modname + QString("("); + for (int i=0; i < argnames.size(); i++) { + if (i > 0) + text += QString(", "); + if (!argnames[i].isEmpty()) + text += argnames[i] + QString(" = "); + text += argexpr[i]->dump(); + } + text += QString(") {\n"); + for (int i = 0; i < children.size(); i++) { + children[i]->dump(indent + QString("\t")); + } + text += QString("%1}\n").arg(indent); + return text; +} + Module::~Module() { foreach (Expression *v, assignments) @@ -45,7 +71,7 @@ Module::~Module() delete v; } -AbstractNode *Module::evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) +AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const { Context c(ctx); c.args(argnames, argexpr, call_argnames, call_argvalues); @@ -55,6 +81,45 @@ AbstractNode *Module::evaluate(Context *ctx, const QVector<QString> &call_argnam return NULL; } +QString Module::dump(QString indent, QString name) const +{ + QString text = QString("%1module %2(").arg(indent, name); + for (int i=0; i < argnames.size(); i++) { + if (i > 0) + text += QString(", "); + text += argnames[i]; + if (argexpr[i]) + text += QString(" = ") + argexpr[i]->dump(); + } + text += QString(") {\n"); + { + QHashIterator<QString, Expression*> i(assignments); + while (i.hasNext()) { + i.next(); + text += QString("%1\t%2 = %3;\n").arg(indent, i.key(), i.value()->dump()); + } + } + { + QHashIterator<QString, AbstractFunction*> i(functions); + while (i.hasNext()) { + i.next(); + text += i.value()->dump(indent + QString("\t"), i.key()); + } + } + { + QHashIterator<QString, AbstractModule*> i(modules); + while (i.hasNext()) { + i.next(); + text += i.value()->dump(indent + QString("\t"), i.key()); + } + } + for (int i = 0; i < children.size(); i++) { + text += children[i]->dump(indent + QString("\t")); + } + text += QString("%1}\n").arg(indent); + return text; +} + QHash<QString, AbstractModule*> builtin_modules; void initialize_builtin_modules() diff --git a/openscad.cc b/openscad.cc index f824c32..cec520a 100644 --- a/openscad.cc +++ b/openscad.cc @@ -20,9 +20,6 @@ #include "openscad.h" -extern int parserdebug; -int parserparse(void); - int main() { int rc = 0; @@ -34,8 +31,10 @@ int main() ctx.functions_p = &builtin_functions; ctx.modules_p = &builtin_modules; - // parserdebug = 1; - rc = parserparse(); + AbstractModule *root_module = parse(stdin, 0); + QString text = root_module->dump("", "*"); + printf("%s", text.toAscii().data()); + delete root_module; destroy_builtin_functions(); destroy_builtin_modules(); @@ -23,6 +23,9 @@ #include <QHash> #include <QVector> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> class Value; class Expression; @@ -49,6 +52,7 @@ public: Value(double v1) : x(v1), y(0), z(0), is_vector(false), is_nan(false) { } Value(double v1, double v2, double v3) : x(v1), y(v2), z(v3), is_vector(true), is_nan(false) { } Value(const Value &v) : x(v.x), y(v.y), z(v.z), is_vector(v.is_vector), is_nan(v.is_nan) { } + Value(const Value &v1, const Value &v2, const Value &v3); Value& operator = (const Value &v); Value operator + (const Value &v) const; @@ -57,6 +61,8 @@ public: Value operator / (const Value &v) const; Value operator % (const Value &v) const; Value inv() const; + + QString dump() const; }; class Expression @@ -73,21 +79,24 @@ public: // Math operators: * / % + - // Invert (prefix '-'): I // Constant value: C - // Variable: V + // Create Vector: V + // Lookup Variable: L // Function call: F char type; Expression(); ~Expression(); - Value evaluate(Context *context); + Value evaluate(const Context *context) const; + QString dump() const; }; class AbstractFunction { public: virtual ~AbstractFunction(); - virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const; + virtual QString dump(QString indent, QString name) const; }; class BuiltinFunction : public AbstractFunction @@ -99,7 +108,8 @@ public: BuiltinFunction(eval_func_t f) : eval_func(f) { } virtual ~BuiltinFunction(); - virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const; + virtual QString dump(QString indent, QString name) const; }; class Function : public AbstractFunction @@ -108,12 +118,13 @@ public: QVector<QString> argnames; QVector<Expression*> argexpr; - Expression expr; + Expression *expr; Function() { } virtual ~Function(); - virtual Value evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + virtual Value evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const; + virtual QString dump(QString indent, QString name) const; }; extern QHash<QString, AbstractFunction*> builtin_functions; @@ -124,7 +135,8 @@ class AbstractModule { public: virtual ~AbstractModule(); - virtual AbstractNode *evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const; + virtual QString dump(QString indent, QString name) const; }; class ModuleInstanciation @@ -134,9 +146,12 @@ public: QString modname; QVector<QString> argnames; QVector<Expression*> argexpr; + QVector<ModuleInstanciation*> children; ModuleInstanciation() { } ~ModuleInstanciation(); + + virtual QString dump(QString indent) const; }; class Module : public AbstractModule @@ -149,12 +164,13 @@ public: QHash<QString, AbstractFunction*> functions; QHash<QString, AbstractModule*> modules; - QVector<ModuleInstanciation> children; + QVector<ModuleInstanciation*> children; Module() { } virtual ~Module(); - virtual AbstractNode *evaluate(Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); + virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const; + virtual QString dump(QString indent, QString name) const; }; extern QHash<QString, AbstractModule*> builtin_modules; @@ -164,17 +180,17 @@ extern void destroy_builtin_modules(); class Context { public: - Context *parent; + const Context *parent; QHash<QString, Value> variables; QHash<QString, AbstractFunction*> *functions_p; QHash<QString, AbstractModule*> *modules_p; - Context(Context *parent) : parent(parent) { } + Context(const Context *parent) : parent(parent) { } void args(const QVector<QString> &argnames, const QVector<Expression*> &argexpr, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues); - Value lookup_variable(QString name); - Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues); - AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues); + Value lookup_variable(QString name) const; + Value evaluate_function(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const; + AbstractNode *evaluate_module(QString name, const QVector<QString> &argnames, const QVector<Value> &argvalues) const; }; class AbstractNode @@ -183,5 +199,7 @@ public: QVector<AbstractNode*> children; }; +extern AbstractModule *parse(FILE *f, int debug); + #endif @@ -21,15 +21,16 @@ %{ #include "openscad.h" -#include <stdio.h> -extern int parserdebug; int parserlex(void); void yyerror(char const *s); int lexerget_lineno(void); int lexerlex(void); +QVector<Module*> module_stack; +Module *module; + %} %union { @@ -117,3 +118,15 @@ void yyerror (char const *s) exit(1); } +AbstractModule *parse(FILE *f, int debug) +{ + module_stack.clear(); + module = new Module(); + module_stack.append(module); + + parserdebug = debug; + parserparse(); + + return module; +} + @@ -19,9 +19,35 @@ */ #include "openscad.h" -#include <math.h> -Value& Value::operator = (const Value &v) { +Value::Value(const Value &v1, const Value &v2, const Value &v3) +{ + if (v1.is_nan || v1.is_vector) + goto create_nan; + if (v2.is_nan || v2.is_vector) + goto create_nan; + if (v3.is_nan || v3.is_vector) + goto create_nan; + + x = v1.x; + y = v1.y; + z = v1.z; + + is_vector = true; + is_nan = false; + return; + +create_nan: + x = 0; + y = 0; + z = 0; + + is_vector = false; + is_nan = true; +} + +Value& Value::operator = (const Value &v) +{ x = v.x; y = v.y; z = v.z; @@ -30,7 +56,8 @@ Value& Value::operator = (const Value &v) { return *this; } -Value Value::operator + (const Value &v) const { +Value Value::operator + (const Value &v) const +{ if (is_nan || v.is_nan) return Value(); if (is_vector && v.is_vector) @@ -40,7 +67,8 @@ Value Value::operator + (const Value &v) const { return Value(); } -Value Value::operator - (const Value &v) const { +Value Value::operator - (const Value &v) const +{ if (is_nan || v.is_nan) return Value(); if (is_vector && v.is_vector) @@ -50,7 +78,8 @@ Value Value::operator - (const Value &v) const { return Value(); } -Value Value::operator * (const Value &v) const { +Value Value::operator * (const Value &v) const +{ if (is_nan || v.is_nan) return Value(); if (is_vector && v.is_vector) { @@ -68,19 +97,22 @@ Value Value::operator * (const Value &v) const { return Value(x * v.x); } -Value Value::operator / (const Value &v) const { +Value Value::operator / (const Value &v) const +{ if (is_nan || v.is_nan || is_vector || v.is_vector) return Value(); return Value(x / v.x); } -Value Value::operator % (const Value &v) const { +Value Value::operator % (const Value &v) const +{ if (is_nan || v.is_nan || is_vector || v.is_vector) return Value(); return Value(fmod(x, v.x)); } -Value Value::inv() const { +Value Value::inv() const +{ if (is_nan) return Value(); if (is_vector) @@ -88,3 +120,12 @@ Value Value::inv() const { return Value(-x); } +QString Value::dump() const +{ + if (is_nan) + return QString("NaN"); + if (is_vector) + return QString("[%1 %2 %3]").arg(x, y, z); + return QString("%1").arg(x); +} + |