summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/TODO.txt1
-rw-r--r--examples/example022.scad35
-rw-r--r--src/control.cc15
-rw-r--r--src/lexer.l2
-rw-r--r--src/module.cc6
-rw-r--r--src/module.h9
-rw-r--r--src/parser.y63
7 files changed, 119 insertions, 12 deletions
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<const IfElseModuleInstantiation*>(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<ModuleInstantiation*> 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 <text> TOK_ID
%token <text> TOK_STRING
@@ -96,6 +99,9 @@ public:
%type <expr> vector_expr
%type <inst> module_instantiation
+%type <ifelse> if_statement
+%type <ifelse> ifelse_statement
+%type <inst> children_instantiation
%type <inst> module_instantiation_list
%type <inst> 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:
contact: Jan Huwald // Impressum