diff options
author | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-21 08:59:53 (GMT) |
---|---|---|
committer | clifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c> | 2009-06-21 08:59:53 (GMT) |
commit | 0e4681913485cb450493e9a35ae297d88f12b19d (patch) | |
tree | 22d3ee0037b6afe9b4b74a854e52c3a2cebd5a8b | |
parent | 1c2472067c3843342f56b5833c284106ab349417 (diff) |
Clifford Wolf:
Parser seams to be fully functional now
git-svn-id: http://svn.clifford.at/openscad/trunk@5 b57f626f-c46c-0410-a088-ec61d464b74c
-rw-r--r-- | example.scad | 20 | ||||
-rw-r--r-- | expr.cc | 16 | ||||
-rw-r--r-- | func.cc | 2 | ||||
-rw-r--r-- | module.cc | 26 | ||||
-rw-r--r-- | openscad.cc | 2 | ||||
-rw-r--r-- | openscad.h | 16 | ||||
-rw-r--r-- | parser.y | 295 | ||||
-rw-r--r-- | value.cc | 15 |
8 files changed, 334 insertions, 58 deletions
diff --git a/example.scad b/example.scad index 1a5445f..35fa12e 100644 --- a/example.scad +++ b/example.scad @@ -1,8 +1,20 @@ +function r_from_dia(d) = d / 2; + +module rotcy(rot, r, h) { + rot(rot) cylinder(r = r, h = h); +} + difference() { - sphere(r = 10); - cylinder(r = 5, h = 15); - rot([90 0 0]) cylinder(r = 5, h = 15); - rot([0 90 0]) cylinder(r = 5, h = 15); + sphere(r = r_from_dia(size)); + rotcy([ 0 0 0], cy_r, cy_h); + rotcy([90 0 0], cy_r, cy_h); + rotcy([ 0 90 0], cy_r, cy_h); } +size = 10; +hole = 2; + +cy_r = r_from_dia(hole); +cy_h = r_from_dia(size * 1.5); + @@ -53,6 +53,19 @@ Value Expression::evaluate(const Context *context) const return Value(children[0]->evaluate(context), children[1]->evaluate(context), children[2]->evaluate(context)); case 'L': return context->lookup_variable(var_name); + case 'M': + { + Value v = children[0]->evaluate(context); + if (v.is_nan || !v.is_vector) + return Value(); + if (var_name == QString("x")) + return Value(v.x); + if (var_name == QString("y")) + return Value(v.y); + if (var_name == QString("z")) + return Value(v.z); + return Value(); + } case 'F': { QVector<Value> argvalues; @@ -83,6 +96,8 @@ QString Expression::dump() const return QString("[%1, %2, %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump()); case 'L': return var_name; + case 'M': + return QString("(%1.%2)").arg(children[0]->dump(), var_name); case 'F': { QString text = call_funcname + QString("("); @@ -93,6 +108,7 @@ QString Expression::dump() const text += call_argnames[i] + QString(" = "); text += children[i]->dump(); } + return text + QString(")"); } default: abort(); @@ -60,7 +60,7 @@ QString Function::dump(QString indent, QString name) const if (argexpr[i]) text += QString(" = ") + argexpr[i]->dump(); } - text += QString(")\n%1\t%2;\n").arg(indent, expr->dump()); + text += QString(") = %1;\n").arg(expr->dump()); return text; } @@ -38,6 +38,8 @@ ModuleInstanciation::~ModuleInstanciation() { foreach (Expression *v, argexpr) delete v; + foreach (ModuleInstanciation *v, children) + delete v; } QString ModuleInstanciation::dump(QString indent) const @@ -53,14 +55,27 @@ QString ModuleInstanciation::dump(QString indent) const 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")); + if (children.size() == 0) { + text += QString(");\n"); + } else if (children.size() == 1) { + text += QString(")\n"); + text += children[0]->dump(indent + QString("\t")); + } else { + text += QString(") {\n"); + for (int i = 0; i < children.size(); i++) { + text += children[i]->dump(indent + QString("\t")); + } + text += QString("%1}\n").arg(indent); } - text += QString("%1}\n").arg(indent); return text; } +AbstractNode *ModuleInstanciation::evaluate(const Context*) const +{ + /* FIXME */ + return NULL; +} + Module::~Module() { foreach (Expression *v, assignments) @@ -69,6 +84,8 @@ Module::~Module() delete v; foreach (AbstractModule *v, modules) delete v; + foreach (ModuleInstanciation *v, children) + delete v; } AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues) const @@ -77,7 +94,6 @@ AbstractNode *Module::evaluate(const Context *ctx, const QVector<QString> &call_ c.args(argnames, argexpr, call_argnames, call_argvalues); /* FIXME */ - return NULL; } diff --git a/openscad.cc b/openscad.cc index cec520a..85e6708 100644 --- a/openscad.cc +++ b/openscad.cc @@ -32,7 +32,7 @@ int main() ctx.modules_p = &builtin_modules; AbstractModule *root_module = parse(stdin, 0); - QString text = root_module->dump("", "*"); + QString text = root_module->dump("", "**root**"); printf("%s", text.toAscii().data()); delete root_module; @@ -45,13 +45,17 @@ class Value { public: double x, y, z; + QString text; bool is_vector; + bool is_range; + bool is_string; bool is_nan; - Value() : x(0), y(0), z(0), is_vector(false), is_nan(true) { } - 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() : x(0), y(0), z(0), is_vector(false), is_range(false), is_string(false), is_nan(true) { } + Value(const QString &t) : x(0), y(0), z(0), text(t), is_vector(false), is_range(false), is_string(true), is_nan(true) { } + Value(double v1) : x(v1), y(0), z(0), is_vector(false), is_range(false), is_string(false), is_nan(false) { } + Value(double v1, double v2, double v3) : x(v1), y(v2), z(v3), is_vector(true), is_range(false), is_string(false), is_nan(false) { } + Value(const Value &v) : x(v.x), y(v.y), z(v.z), text(v.text), is_vector(v.is_vector), is_range(v.is_range), is_string(v.is_string), is_nan(v.is_nan) { } Value(const Value &v1, const Value &v2, const Value &v3); Value& operator = (const Value &v); @@ -81,6 +85,7 @@ public: // Constant value: C // Create Vector: V // Lookup Variable: L + // Lookup Member: M // Function call: F char type; @@ -151,7 +156,8 @@ public: ModuleInstanciation() { } ~ModuleInstanciation(); - virtual QString dump(QString indent) const; + QString dump(QString indent) const; + AbstractNode *evaluate(const Context *ctx) const; }; class Module : public AbstractModule @@ -26,16 +26,32 @@ int parserlex(void); void yyerror(char const *s); int lexerget_lineno(void); +int lexerlex_destroy(void); int lexerlex(void); QVector<Module*> module_stack; Module *module; +class ArgContainer { +public: + QString argname; + Expression *argexpr; +}; +class ArgsContainer { +public: + QVector<QString> argnames; + QVector<Expression*> argexpr; +}; + %} %union { char *text; double number; + class Expression *expr; + class ModuleInstanciation *inst; + class ArgContainer *arg; + class ArgsContainer *args; } %token TOK_MODULE @@ -48,6 +64,18 @@ Module *module; %left '*' '/' '%' %left '.' +%type <expr> expr + +%type <inst> module_instantciation +%type <inst> module_instantciation_list +%type <inst> single_module_instantciation + +%type <args> arguments_call +%type <args> arguments_decl + +%type <arg> argument_call +%type <arg> argument_decl + %debug %% @@ -59,51 +87,239 @@ input: statement: ';' | '{' input '}' | - node statement | - TOK_ID '=' expr ';' | - TOK_MODULE TOK_ID '(' arguments_decal ')' statement | - TOK_FUNCTION TOK_ID '(' arguments_decal ')' expr ; + module_instantciation { + module->children.append($1); + } | + TOK_ID '=' expr ';' { + module->assignments[$1] = $3; + free($1); + } | + TOK_MODULE TOK_ID '(' arguments_decl ')' { + Module *p = module; + module_stack.append(module); + module = new Module(); + p->modules[$2] = module; + module->argnames = $4->argnames; + module->argexpr = $4->argexpr; + free($2); + delete $4; + } statement { + module = module_stack.last(); + module_stack.pop_back(); + } | + TOK_FUNCTION TOK_ID '(' arguments_decl ')' '=' expr { + Function *func = new Function(); + func->argnames = $4->argnames; + func->argexpr = $4->argexpr; + func->expr = $7; + module->functions[$2] = func; + free($2); + delete $4; + } ; -node: - TOK_ID '(' arguments_call ')' | - TOK_ID ':' TOK_ID '(' arguments_call ')' ; +module_instantciation: + single_module_instantciation ';' { + $$ = $1; + } | + single_module_instantciation '{' module_instantciation_list '}' { + $$ = $1; + $$->children = $3->children; + $3->children.clear(); + delete $3; + } | + single_module_instantciation module_instantciation { + $$ = $1; + $$->children.append($2); + } ; +module_instantciation_list: + /* empty */ { + $$ = new ModuleInstanciation(); + } | + module_instantciation module_instantciation_list { + $$ = $2; + $$->children.append($1); + } ; + +single_module_instantciation: + TOK_ID '(' arguments_call ')' { + $$ = new ModuleInstanciation(); + $$->modname = QString($1); + $$->argnames = $3->argnames; + $$->argexpr = $3->argexpr; + free($1); + delete $3; + } | + TOK_ID ':' TOK_ID '(' arguments_call ')' { + $$ = new ModuleInstanciation(); + $$->label = QString($1); + $$->modname = QString($3); + $$->argnames = $5->argnames; + $$->argexpr = $5->argexpr; + free($1); + free($3); + delete $5; + } ; + expr: - TOK_ID | - expr '.' TOK_ID | - TOK_STRING | - TOK_NUMBER | - TOK_NUMBER ':' TOK_NUMBER | - TOK_NUMBER ':' TOK_NUMBER ':' TOK_NUMBER | - '[' TOK_NUMBER TOK_NUMBER TOK_NUMBER ']' | - '[' expr ',' expr ',' expr ']' | - expr '*' expr | - expr '/' expr | - expr '%' expr | - expr '+' expr | - expr '-' expr | - '+' expr | - '-' expr | - '(' expr ')' | - TOK_ID '(' arguments_call ')' ; - -arguments_decal: - argument_decal | - argument_decal ',' arguments_decal | - /* empty */ ; - -argument_decal: - TOK_ID | - TOK_ID '=' expr ; + TOK_ID { + $$ = new Expression(); + $$->type = 'L'; + $$->var_name = QString($1); + free($1); + } | + expr '.' TOK_ID { + $$ = new Expression(); + $$->type = 'M'; + $$->children.append($1); + $$->var_name = QString($3); + free($3); + } | + TOK_STRING { + $$ = new Expression(); + $$->type = 'C'; + $$->const_value = Value(QString($1)); + free($1); + } | + TOK_NUMBER { + $$ = new Expression(); + $$->type = 'C'; + $$->const_value = Value($1); + } | + TOK_NUMBER ':' TOK_NUMBER { + $$ = new Expression(); + $$->type = 'C'; + $$->const_value = Value($1, 1, $3); + $$->const_value.is_range = true; + } | + TOK_NUMBER ':' TOK_NUMBER ':' TOK_NUMBER { + $$ = new Expression(); + $$->type = 'C'; + $$->const_value = Value($1, $3, $5); + $$->const_value.is_range = true; + } | + '[' TOK_NUMBER TOK_NUMBER TOK_NUMBER ']' { + $$ = new Expression(); + $$->type = 'C'; + $$->const_value = Value($2, $3, $4); + } | + '[' expr ',' expr ',' expr ']' { + $$ = new Expression(); + $$->type = 'V'; + $$->children.append($2); + $$->children.append($4); + $$->children.append($6); + } | + expr '*' expr { + $$ = new Expression(); + $$->type = '*'; + $$->children.append($1); + $$->children.append($3); + } | + expr '/' expr { + $$ = new Expression(); + $$->type = '/'; + $$->children.append($1); + $$->children.append($3); + } | + expr '%' expr { + $$ = new Expression(); + $$->type = '%'; + $$->children.append($1); + $$->children.append($3); + } | + expr '+' expr { + $$ = new Expression(); + $$->type = '+'; + $$->children.append($1); + $$->children.append($3); + } | + expr '-' expr { + $$ = new Expression(); + $$->type = '-'; + $$->children.append($1); + $$->children.append($3); + } | + '+' expr { + $$ = $2; + } | + '-' expr { + $$ = new Expression(); + $$->type = 'I'; + $$->children.append($2); + } | + '(' expr ')' { + $$ = $2; + } | + TOK_ID '(' arguments_call ')' { + $$ = new Expression(); + $$->type = 'F'; + $$->call_funcname = QString($1); + $$->call_argnames = $3->argnames; + $$->children = $3->argexpr; + free($1); + delete $3; + } ; + +arguments_decl: + /* empty */ { + $$ = new ArgsContainer(); + } | + argument_decl { + $$ = new ArgsContainer(); + $$->argnames.append($1->argname); + $$->argexpr.append($1->argexpr); + delete $1; + } | + arguments_decl ',' argument_decl { + $$ = $1; + $$->argnames.append($3->argname); + $$->argexpr.append($3->argexpr); + delete $3; + } ; + +argument_decl: + TOK_ID { + $$ = new ArgContainer(); + $$->argname = QString($1); + $$->argexpr = NULL; + free($1); + } | + TOK_ID '=' expr { + $$ = new ArgContainer(); + $$->argname = QString($1); + $$->argexpr = $3; + free($1); + } ; arguments_call: - argument_call | - argument_call ',' arguments_call | - /* empty */ ; + /* empty */ { + $$ = new ArgsContainer(); + } | + argument_call { + $$ = new ArgsContainer(); + $$->argnames.append($1->argname); + $$->argexpr.append($1->argexpr); + delete $1; + } | + arguments_call ',' argument_call { + $$ = $1; + $$->argnames.append($3->argname); + $$->argexpr.append($3->argexpr); + delete $3; + } ; argument_call: - expr | - TOK_ID '=' expr ; + expr { + $$ = new ArgContainer(); + $$->argexpr = $1; + } | + TOK_ID '=' expr { + $$ = new ArgContainer(); + $$->argname = QString($1); + $$->argexpr = $3; + free($1); + } ; %% @@ -122,11 +338,12 @@ AbstractModule *parse(FILE *f, int debug) { module_stack.clear(); module = new Module(); - module_stack.append(module); parserdebug = debug; parserparse(); + lexerlex_destroy(); + return module; } @@ -34,6 +34,8 @@ Value::Value(const Value &v1, const Value &v2, const Value &v3) z = v1.z; is_vector = true; + is_range = false; + is_string = false; is_nan = false; return; @@ -43,6 +45,8 @@ create_nan: z = 0; is_vector = false; + is_range = false; + is_string = false; is_nan = true; } @@ -124,8 +128,13 @@ 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); + if (is_vector) { + QString text; + text.sprintf("[%f %f %f]", x, y, z); + return text; + } + QString text; + text.sprintf("%f", x); + return text; } |