From 572631746157766359a878c7b52d0c26ae731496 Mon Sep 17 00:00:00 2001 From: kintel Date: Fri, 12 Feb 2010 13:20:15 +0000 Subject: Support for if-else statements git-svn-id: http://svn.clifford.at/openscad/trunk@436 b57f626f-c46c-0410-a088-ec61d464b74c diff --git a/doc/TODO.txt b/doc/TODO.txt index a301d6e..246d771 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -95,6 +95,7 @@ o Language Frontend ignore all top level objects (they are used as module testcase) and search in a module search path. - allow 0/1 f/t FALSE/TRUE as boolean values + - allow any expression to be evaluated as boolean (e.g. 1 = true, 0 = false) o DXF Import - Support for POLYLINE entity - Support for SPLINE entity diff --git a/examples/example022.scad b/examples/example022.scad new file mode 100644 index 0000000..ac8cb1c --- /dev/null +++ b/examples/example022.scad @@ -0,0 +1,35 @@ +// size is a vector [w, h, d] +module roundedBox(size, radius, sidesonly) +{ + rot = [ [0,0,0], [90,0,90], [90,90,0] ]; + if (sidesonly) { + cube(size - [2*radius,0,0], true); + cube(size - [0,2*radius,0], true); + for (x = [radius-size[0]/2, -radius+size[0]/2], + y = [radius-size[1]/2, -radius+size[1]/2]) { + translate([x,y,0]) cylinder(r=radius, h=size[2], center=true); + } + } + else { + cube([size[0], size[1]-radius*2, size[2]-radius*2], center=true); + cube([size[0]-radius*2, size[1], size[2]-radius*2], center=true); + cube([size[0]-radius*2, size[1]-radius*2, size[2]], center=true); + + for (axis = [0:2]) { + for (x = [radius-size[axis]/2, -radius+size[axis]/2], + y = [radius-size[(axis+1)%3]/2, -radius+size[(axis+1)%3]/2]) { + rotate(rot[axis]) + translate([x,y,0]) + cylinder(h=size[(axis+2)%3]-2*radius, r=radius, center=true); + } + } + for (x = [radius-size[0]/2, -radius+size[0]/2], + y = [radius-size[1]/2, -radius+size[1]/2], + z = [radius-size[2]/2, -radius+size[2]/2]) { + translate([x,y,z]) sphere(radius); + } + } +} + +translate([-15,0,0])roundedBox([20,30,40], 5, true); +translate([15,0,0]) roundedBox([20,30,40], 5, false); diff --git a/src/control.cc b/src/control.cc index d0b96a1..5b7e1b1 100644 --- a/src/control.cc +++ b/src/control.cc @@ -149,12 +149,21 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation if (type == IF) { - if (inst->argvalues.size() > 0 && inst->argvalues[0].type == Value::BOOL && inst->argvalues[0].b) - foreach (ModuleInstantiation *v, inst->children) { - AbstractNode *n = v->evaluate(inst->ctx); + const IfElseModuleInstantiation *ifelse = dynamic_cast(inst); + if (ifelse->argvalues.size() > 0 && ifelse->argvalues[0].type == Value::BOOL && ifelse->argvalues[0].b) { + foreach (ModuleInstantiation *v, ifelse->children) { + AbstractNode *n = v->evaluate(ifelse->ctx); if (n != NULL) node->children.append(n); } + } + else { + foreach (ModuleInstantiation *v, ifelse->else_children) { + AbstractNode *n = v->evaluate(ifelse->ctx); + if (n != NULL) + node->children.append(n); + } + } } return node; diff --git a/src/lexer.l b/src/lexer.l index b051a5d..5a5c0e9 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -96,6 +96,8 @@ extern const char *parser_source_path; "module" return TOK_MODULE; "function" return TOK_FUNCTION; +"if" return TOK_IF; +"else" return TOK_ELSE; "true" return TOK_TRUE; "false" return TOK_FALSE; diff --git a/src/module.cc b/src/module.cc index 51d191e..c165131 100644 --- a/src/module.cc +++ b/src/module.cc @@ -61,6 +61,12 @@ ModuleInstantiation::~ModuleInstantiation() delete v; } +IfElseModuleInstantiation::~IfElseModuleInstantiation() +{ + foreach (ModuleInstantiation *v, else_children) + delete v; +} + QString ModuleInstantiation::dump(QString indent) const { QString text = indent; diff --git a/src/module.h b/src/module.h index 35cc872..20ea1af 100644 --- a/src/module.h +++ b/src/module.h @@ -22,12 +22,19 @@ public: const class Context *ctx; ModuleInstantiation() : tag_root(false), tag_highlight(false), tag_background(false), ctx(NULL) { } - ~ModuleInstantiation(); + virtual ~ModuleInstantiation(); QString dump(QString indent) const; class AbstractNode *evaluate(const Context *ctx) const; }; +class IfElseModuleInstantiation : public ModuleInstantiation { +public: + virtual ~IfElseModuleInstantiation(); + + QVector else_children; +}; + class AbstractModule { public: diff --git a/src/parser.y b/src/parser.y index 7bee0c1..a0e4ac9 100644 --- a/src/parser.y +++ b/src/parser.y @@ -62,12 +62,15 @@ public: class Value *value; class Expression *expr; class ModuleInstantiation *inst; + class IfElseModuleInstantiation *ifelse; class ArgContainer *arg; class ArgsContainer *args; } %token TOK_MODULE %token TOK_FUNCTION +%token TOK_IF +%token TOK_ELSE %token TOK_ID %token TOK_STRING @@ -96,6 +99,9 @@ public: %type vector_expr %type module_instantiation +%type if_statement +%type ifelse_statement +%type children_instantiation %type module_instantiation_list %type single_module_instantiation @@ -161,29 +167,70 @@ statement: delete $4; } ';' ; -module_instantiation: - single_module_instantiation ';' { +/* Will return a dummy parent node with zero or more children */ +children_instantiation: + module_instantiation { + $$ = new ModuleInstantiation(); + if ($1) { + $$->children.append($1); + } else { + delete $1; + } + } | + '{' module_instantiation_list '}' { + $$ = $2; + } ; + +if_statement: + TOK_IF '(' expr ')' children_instantiation { + $$ = new IfElseModuleInstantiation(); + $$->modname = "if"; + $$->argnames.append(QString()); + $$->argexpr.append($3); + + if ($$) { + $$->children = $5->children; + } else { + for (int i = 0; i < $5->children.count(); i++) + delete $5->children[i]; + } + $5->children.clear(); + delete $5; + } ; + +ifelse_statement: + if_statement { $$ = $1; } | - single_module_instantiation '{' module_instantiation_list '}' { + if_statement TOK_ELSE children_instantiation { $$ = $1; if ($$) { - $$->children = $3->children; + $$->else_children = $3->children; } else { for (int i = 0; i < $3->children.count(); i++) delete $3->children[i]; } $3->children.clear(); delete $3; + } ; + +module_instantiation: + single_module_instantiation ';' { + $$ = $1; } | - single_module_instantiation module_instantiation { + single_module_instantiation children_instantiation { $$ = $1; if ($$) { - if ($2) - $$->children.append($2); + $$->children = $2->children; } else { - delete $2; + for (int i = 0; i < $2->children.count(); i++) + delete $2->children[i]; } + $2->children.clear(); + delete $2; + } | + ifelse_statement { + $$ = $1; } ; module_instantiation_list: -- cgit v0.10.1