summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--expr.cc197
-rw-r--r--lexer.l27
-rw-r--r--openscad.h21
-rw-r--r--parser.y105
-rw-r--r--value.cc78
5 files changed, 294 insertions, 134 deletions
diff --git a/expr.cc b/expr.cc
index cefa3b9..f0e45d7 100644
--- a/expr.cc
+++ b/expr.cc
@@ -22,7 +22,6 @@
Expression::Expression()
{
- type = 0;
const_value = NULL;
}
@@ -36,124 +35,138 @@ Expression::~Expression()
Value Expression::evaluate(const Context *context) const
{
- switch (type)
- {
- case '*':
+ if (type == "!")
+ return ! children[0]->evaluate(context);
+ if (type == "&&")
+ return children[0]->evaluate(context) && children[1]->evaluate(context);
+ if (type == "||")
+ return children[0]->evaluate(context) || children[1]->evaluate(context);
+ if (type == "*")
return children[0]->evaluate(context) * children[1]->evaluate(context);
- case '/':
+ if (type == "/")
return children[0]->evaluate(context) / children[1]->evaluate(context);
- case '%':
+ if (type == "%")
return children[0]->evaluate(context) % children[1]->evaluate(context);
- case '+':
+ if (type == "+")
return children[0]->evaluate(context) + children[1]->evaluate(context);
- case '-':
+ if (type == "-")
return children[0]->evaluate(context) - children[1]->evaluate(context);
- case '?':
- {
- Value v = children[0]->evaluate(context);
- if (v.type == Value::BOOL)
- return children[v.b ? 1 : 2]->evaluate(context);
- return Value();
+ if (type == "<")
+ return children[0]->evaluate(context) < children[1]->evaluate(context);
+ if (type == "<=")
+ return children[0]->evaluate(context) <= children[1]->evaluate(context);
+ if (type == "==")
+ return children[0]->evaluate(context) == children[1]->evaluate(context);
+ if (type == "!=")
+ return children[0]->evaluate(context) != children[1]->evaluate(context);
+ if (type == ">=")
+ return children[0]->evaluate(context) >= children[1]->evaluate(context);
+ if (type == ">")
+ return children[0]->evaluate(context) > children[1]->evaluate(context);
+ if (type == "?:") {
+ Value v = children[0]->evaluate(context);
+ if (v.type == Value::BOOL)
+ return children[v.b ? 1 : 2]->evaluate(context);
+ return Value();
+ }
+ if (type == "[]") {
+ Value v1 = children[0]->evaluate(context);
+ Value v2 = children[1]->evaluate(context);
+ if (v1.type == Value::VECTOR && v2.type == Value::NUMBER) {
+ int i = v2.num;
+ if (i < v1.vec.size())
+ return *v1.vec[i];
}
- case 'I':
+ return Value();
+ }
+ if (type == "I")
return children[0]->evaluate(context).inv();
- case 'C':
+ if (type == "C")
return *const_value;
- case 'R':
- {
- Value v1 = children[0]->evaluate(context);
- Value v2 = children[1]->evaluate(context);
- Value v3 = children[2]->evaluate(context);
- if (v1.type == Value::NUMBER && v2.type == Value::NUMBER && v3.type == Value::NUMBER) {
- Value r = Value();
- r.type = Value::RANGE;
- r.range_begin = v1.num;
- r.range_step = v2.num;
- r.range_end = v3.num;
- return r;
- }
- return Value();
+ if (type == "R") {
+ Value v1 = children[0]->evaluate(context);
+ Value v2 = children[1]->evaluate(context);
+ Value v3 = children[2]->evaluate(context);
+ if (v1.type == Value::NUMBER && v2.type == Value::NUMBER && v3.type == Value::NUMBER) {
+ Value r = Value();
+ r.type = Value::RANGE;
+ r.range_begin = v1.num;
+ r.range_step = v2.num;
+ r.range_end = v3.num;
+ return r;
}
- case 'V':
- {
- Value v;
- v.type = Value::VECTOR;
- for (int i = 0; i < children.size(); i++)
- v.vec.append(new Value(children[i]->evaluate(context)));
- return v;
- }
- case 'L':
+ return Value();
+ }
+ if (type == "V") {
+ Value v;
+ v.type = Value::VECTOR;
+ for (int i = 0; i < children.size(); i++)
+ v.vec.append(new Value(children[i]->evaluate(context)));
+ return v;
+ }
+ if (type == "L")
return context->lookup_variable(var_name);
- case 'N':
- {
- Value v = children[0]->evaluate(context);
+ if (type == "N")
+ {
+ Value v = children[0]->evaluate(context);
- if (v.type == Value::VECTOR && var_name == QString("x"))
- return *v.vec[0];
- if (v.type == Value::VECTOR && var_name == QString("y"))
- return *v.vec[1];
- if (v.type == Value::VECTOR && var_name == QString("z"))
- return *v.vec[2];
+ if (v.type == Value::VECTOR && var_name == QString("x"))
+ return *v.vec[0];
+ if (v.type == Value::VECTOR && var_name == QString("y"))
+ return *v.vec[1];
+ if (v.type == Value::VECTOR && var_name == QString("z"))
+ return *v.vec[2];
- if (v.type == Value::RANGE && var_name == QString("begin"))
- return Value(v.range_begin);
- if (v.type == Value::RANGE && var_name == QString("step"))
- return Value(v.range_step);
- if (v.type == Value::RANGE && var_name == QString("end"))
- return Value(v.range_end);
+ if (v.type == Value::RANGE && var_name == QString("begin"))
+ return Value(v.range_begin);
+ if (v.type == Value::RANGE && var_name == QString("step"))
+ return Value(v.range_step);
+ if (v.type == Value::RANGE && var_name == QString("end"))
+ return Value(v.range_end);
- return Value();
- }
- case 'F':
- {
- QVector<Value> argvalues;
- for (int i=0; i < children.size(); i++)
- argvalues.append(children[i]->evaluate(context));
- return context->evaluate_function(call_funcname, call_argnames, argvalues);
- }
- default:
- abort();
+ return Value();
}
+ if (type == "F") {
+ QVector<Value> argvalues;
+ for (int i=0; i < children.size(); i++)
+ argvalues.append(children[i]->evaluate(context));
+ return context->evaluate_function(call_funcname, call_argnames, argvalues);
+ }
+ abort();
}
QString Expression::dump() const
{
- switch (type)
- {
- case '*':
- case '/':
- case '%':
- case '+':
- case '-':
+ if (type == "*" || type == "/" || type == "%" || type == "+" || type == "-" ||
+ type == "<" || type == "<=" || type == "==" || type == "!=" || type == ">=" || type == ">")
return QString("(%1 %2 %3)").arg(children[0]->dump(), QString(type), children[1]->dump());
- case '?':
+ if (type == "?:")
return QString("(%1 ? %2 : %3)").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
- case 'I':
+ if (type == "[]")
+ return QString("(%1[%2])").arg(children[0]->dump(), children[1]->dump());
+ if (type == "I")
return QString("(-%1)").arg(children[0]->dump());
- case 'C':
+ if (type == "C")
return const_value->dump();
- case 'R':
+ if (type == "R")
return QString("[%1 : %2 : %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
- case 'V':
+ if (type == "V")
return QString("[%1, %2, %3]").arg(children[0]->dump(), children[1]->dump(), children[2]->dump());
- case 'L':
+ if (type == "L")
return var_name;
- case 'N':
+ if (type == "N")
return QString("(%1.%2)").arg(children[0]->dump(), 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();
- }
- return text + QString(")");
+ if (type == "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();
+ return text + QString(")");
}
+ abort();
}
diff --git a/lexer.l b/lexer.l
index dd35aa1..4ec72b7 100644
--- a/lexer.l
+++ b/lexer.l
@@ -55,29 +55,18 @@ extern const char *parser_input_buffer;
"$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; }
\"[^"]*\" { parserlval.text = strdup(yytext); return TOK_STRING; }
-"." return '.';
-"," return ',';
-";" return ';';
-"?" return '?';
-":" return ':';
-"=" return '=';
-"*" return '*';
-"/" return '/';
-"%" return '%';
-"+" return '+';
-"-" return '-';
-"(" return '(';
-")" return ')';
-"{" return '{';
-"}" return '}';
-"[" return '[';
-"]" return ']';
-
[\n\r\t ]
\/\/[^\n]*\n
"/*" BEGIN(comment);
<comment>"*/" BEGIN(INITIAL);
<comment>.|\n
-. { fprintf(stderr, "Unrecognized input character in line %d: %s\n", lexerget_lineno(), yytext); exit(1); }
+"<=" return LE;
+">=" return GE;
+"==" return EQ;
+"!=" return NE;
+"&&" return AND;
+"||" return OR;
+
+. { return yytext[0]; }
diff --git a/openscad.h b/openscad.h
index 4c7f68f..081a7a0 100644
--- a/openscad.h
+++ b/openscad.h
@@ -104,11 +104,23 @@ public:
Value(const Value &v);
Value& operator = (const Value &v);
+ Value operator ! () const;
+ Value operator && (const Value &v) const;
+ Value operator || (const Value &v) const;
+
Value operator + (const Value &v) const;
Value operator - (const Value &v) const;
Value operator * (const Value &v) const;
Value operator / (const Value &v) const;
Value operator % (const Value &v) const;
+
+ Value operator < (const Value &v) const;
+ Value operator <= (const Value &v) const;
+ Value operator == (const Value &v) const;
+ Value operator != (const Value &v) const;
+ Value operator >= (const Value &v) const;
+ Value operator > (const Value &v) const;
+
Value inv() const;
bool getnum(double &v) const;
@@ -131,8 +143,11 @@ public:
QString call_funcname;
QVector<QString> call_argnames;
- // Math operators: * / % + -
- // Condition (?: operator): ?
+ // Boolean: ! && ||
+ // Operators: * / % + -
+ // Relations: < <= == != >= >
+ // Vector element: []
+ // Condition operator: ?:
// Invert (prefix '-'): I
// Constant value: C
// Create Range: R
@@ -141,7 +156,7 @@ public:
// Lookup Variable: L
// Lookup member per name: N
// Function call: F
- char type;
+ QString type;
Expression();
~Expression();
diff --git a/parser.y b/parser.y
index d9fce18..8006c6a 100644
--- a/parser.y
+++ b/parser.y
@@ -66,9 +66,15 @@ public:
%token TOK_FALSE
%token TOK_UNDEF
+%token LE GE EQ NE AND OR
+
%left '+' '-'
%left '*' '/' '%'
%left '.'
+%left '<' LE GE '>'
+%left EQ NE
+%left AND
+%left OR
%type <expr> expr
%type <value> vector_const
@@ -173,69 +179,69 @@ single_module_instantciation:
expr:
TOK_TRUE {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = new Value(true);
} |
TOK_FALSE {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = new Value(false);
} |
TOK_UNDEF {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = new Value();
} |
TOK_ID {
$$ = new Expression();
- $$->type = 'L';
+ $$->type = "L";
$$->var_name = QString($1);
free($1);
} |
expr '.' TOK_ID {
$$ = new Expression();
- $$->type = 'N';
+ $$->type = "N";
$$->children.append($1);
$$->var_name = QString($3);
free($3);
} |
TOK_STRING {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = new Value(QString($1));
free($1);
} |
TOK_NUMBER {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = new Value($1);
} |
'[' expr ':' expr ']' {
Expression *e_one = new Expression();
- e_one->type = 'C';
+ e_one->type = "C";
e_one->const_value = new Value(1.0);
$$ = new Expression();
- $$->type = 'R';
+ $$->type = "R";
$$->children.append($2);
$$->children.append(e_one);
$$->children.append($4);
} |
'[' expr ':' expr ':' expr ']' {
$$ = new Expression();
- $$->type = 'R';
+ $$->type = "R";
$$->children.append($2);
$$->children.append($4);
$$->children.append($6);
} |
'[' ']' {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = new Value();
$$->const_value->type = Value::VECTOR;
} |
'[' vector_const ']' {
$$ = new Expression();
- $$->type = 'C';
+ $$->type = "C";
$$->const_value = $2;
} |
'[' vector_expr ']' {
@@ -243,31 +249,79 @@ expr:
} |
expr '*' expr {
$$ = new Expression();
- $$->type = '*';
+ $$->type = "*";
$$->children.append($1);
$$->children.append($3);
} |
expr '/' expr {
$$ = new Expression();
- $$->type = '/';
+ $$->type = "/";
$$->children.append($1);
$$->children.append($3);
} |
expr '%' expr {
$$ = new Expression();
- $$->type = '%';
+ $$->type = "%";
$$->children.append($1);
$$->children.append($3);
} |
expr '+' expr {
$$ = new Expression();
- $$->type = '+';
+ $$->type = "+";
$$->children.append($1);
$$->children.append($3);
} |
expr '-' expr {
$$ = new Expression();
- $$->type = '-';
+ $$->type = "-";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr '<' expr {
+ $$ = new Expression();
+ $$->type = "<";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr LE expr {
+ $$ = new Expression();
+ $$->type = "<=";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr EQ expr {
+ $$ = new Expression();
+ $$->type = "==";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr NE expr {
+ $$ = new Expression();
+ $$->type = "!=";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr GE expr {
+ $$ = new Expression();
+ $$->type = ">=";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr '>' expr {
+ $$ = new Expression();
+ $$->type = "<";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr AND expr {
+ $$ = new Expression();
+ $$->type = "&&";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
+ expr OR expr {
+ $$ = new Expression();
+ $$->type = "||";
$$->children.append($1);
$$->children.append($3);
} |
@@ -276,7 +330,12 @@ expr:
} |
'-' expr {
$$ = new Expression();
- $$->type = 'I';
+ $$->type = "I";
+ $$->children.append($2);
+ } |
+ '!' expr {
+ $$ = new Expression();
+ $$->type = "!";
$$->children.append($2);
} |
'(' expr ')' {
@@ -284,14 +343,20 @@ expr:
} |
expr '?' expr ':' expr {
$$ = new Expression();
- $$->type = '?';
+ $$->type = "?:";
$$->children.append($1);
$$->children.append($3);
$$->children.append($5);
} |
+ expr '[' expr ']' {
+ $$ = new Expression();
+ $$->type = "[]";
+ $$->children.append($1);
+ $$->children.append($3);
+ } |
TOK_ID '(' arguments_call ')' {
$$ = new Expression();
- $$->type = 'F';
+ $$->type = "F";
$$->call_funcname = QString($1);
$$->call_argnames = $3->argnames;
$$->children = $3->argexpr;
diff --git a/value.cc b/value.cc
index 0eeec36..7168fc0 100644
--- a/value.cc
+++ b/value.cc
@@ -73,6 +73,30 @@ Value& Value::operator = (const Value &v)
return *this;
}
+Value Value::operator ! () const
+{
+ if (type == BOOL) {
+ return Value(!b);
+ }
+ return Value();
+}
+
+Value Value::operator && (const Value &v) const
+{
+ if (type == BOOL && v.type == BOOL) {
+ return Value(b && v.b);
+ }
+ return Value();
+}
+
+Value Value::operator || (const Value &v) const
+{
+ if (type == BOOL && v.type == BOOL) {
+ return Value(b || v.b);
+ }
+ return Value();
+}
+
Value Value::operator + (const Value &v) const
{
if (type == VECTOR && v.type == VECTOR) {
@@ -155,6 +179,60 @@ Value Value::operator % (const Value &v) const
return Value();
}
+Value Value::operator < (const Value &v) const
+{
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num < v.num);
+ }
+ return Value();
+}
+
+Value Value::operator <= (const Value &v) const
+{
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num <= v.num);
+ }
+ return Value();
+}
+
+Value Value::operator == (const Value &v) const
+{
+ if (type == BOOL && v.type == BOOL) {
+ return Value(b == v.b);
+ }
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num == v.num);
+ }
+ return Value();
+}
+
+Value Value::operator != (const Value &v) const
+{
+ if (type == BOOL && v.type == BOOL) {
+ return Value(b != v.b);
+ }
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num != v.num);
+ }
+ return Value();
+}
+
+Value Value::operator >= (const Value &v) const
+{
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num >= v.num);
+ }
+ return Value();
+}
+
+Value Value::operator > (const Value &v) const
+{
+ if (type == NUMBER && v.type == NUMBER) {
+ return Value(num > v.num);
+ }
+ return Value();
+}
+
Value Value::inv() const
{
if (type == VECTOR) {
contact: Jan Huwald // Impressum