summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2009-06-21 08:59:53 (GMT)
committerclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2009-06-21 08:59:53 (GMT)
commit0e4681913485cb450493e9a35ae297d88f12b19d (patch)
tree22d3ee0037b6afe9b4b74a854e52c3a2cebd5a8b
parent1c2472067c3843342f56b5833c284106ab349417 (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.scad20
-rw-r--r--expr.cc16
-rw-r--r--func.cc2
-rw-r--r--module.cc26
-rw-r--r--openscad.cc2
-rw-r--r--openscad.h16
-rw-r--r--parser.y295
-rw-r--r--value.cc15
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);
+
diff --git a/expr.cc b/expr.cc
index ce0d462..80d5666 100644
--- a/expr.cc
+++ b/expr.cc
@@ -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();
diff --git a/func.cc b/func.cc
index 7bac786..9104653 100644
--- a/func.cc
+++ b/func.cc
@@ -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;
}
diff --git a/module.cc b/module.cc
index 522e562..d8c5f31 100644
--- a/module.cc
+++ b/module.cc
@@ -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;
diff --git a/openscad.h b/openscad.h
index 10f44fe..df89b57 100644
--- a/openscad.h
+++ b/openscad.h
@@ -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
diff --git a/parser.y b/parser.y
index b23b0d4..6a70805 100644
--- a/parser.y
+++ b/parser.y
@@ -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;
}
diff --git a/value.cc b/value.cc
index 7e562fa..9b4ca2e 100644
--- a/value.cc
+++ b/value.cc
@@ -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;
}
contact: Jan Huwald // Impressum