summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2010-03-20 15:55:52 -0400
committerTavian Barnes <tavianator@gmail.com>2010-03-20 15:55:52 -0400
commitac3e97014885af00b5a2eb01df232221482db023 (patch)
tree39163e9eed2427580260d0097b1c7887bcc536a5
parent5da32d0dce6b8ade0b636b83f67b6244e6a56494 (diff)
downloaddimension-ac3e97014885af00b5a2eb01df232221482db023.tar.xz
Support max() and min().
-rw-r--r--dimension/common.nonterminals2
-rw-r--r--dimension/common.rules22
-rw-r--r--dimension/common.terminals4
-rw-r--r--dimension/grammar.epilogue2
-rw-r--r--dimension/lexer.l2
-rw-r--r--dimension/parse.c38
-rw-r--r--dimension/parse.h2
-rw-r--r--tests/dimension/arithexp.pov8
8 files changed, 78 insertions, 2 deletions
diff --git a/dimension/common.nonterminals b/dimension/common.nonterminals
index c3b2b3f..2008290 100644
--- a/dimension/common.nonterminals
+++ b/dimension/common.nonterminals
@@ -73,6 +73,8 @@
/* Generalized arithmetic expressions */
%type <astnode> ARITH_EXPR
+%type <astnode> MAX_LIST
+%type <astnode> MIN_LIST
/* Colors */
%type <astnode> COLOR
diff --git a/dimension/common.rules b/dimension/common.rules
index e5b9e67..c8e0767 100644
--- a/dimension/common.rules
+++ b/dimension/common.rules
@@ -453,6 +453,12 @@ ARITH_EXPR: FLOAT_LITERAL
| "log" "(" ARITH_EXPR ")" {
$$ = dmnsn_new_astnode1(DMNSN_AST_LOG, @$, $3);
}
+ | "max" "(" MAX_LIST ")" {
+ $$ = $3;
+ }
+ | "min" "(" MIN_LIST ")" {
+ $$ = $3;
+ }
| "mod" "(" ARITH_EXPR "," ARITH_EXPR ")" {
$$ = dmnsn_new_astnode2(DMNSN_AST_MOD, @$, $3, $5);
}
@@ -501,6 +507,22 @@ ARITH_EXPR: FLOAT_LITERAL
| "t" { $$ = dmnsn_new_ast_ivector(0, 0, 0, 1, 0); }
;
+MAX_LIST: ARITH_EXPR "," ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_MAX, @$, $1, $3);
+ }
+ | MAX_LIST "," ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_MAX, @$, $1, $3);
+ }
+;
+
+MIN_LIST: ARITH_EXPR "," ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_MIN, @$, $1, $3);
+ }
+ | MIN_LIST "," ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_MIN, @$, $1, $3);
+ }
+;
+
/* Colors */
COLOR: COLOR_BODY {
diff --git a/dimension/common.terminals b/dimension/common.terminals
index a877ac1..b5308e4 100644
--- a/dimension/common.terminals
+++ b/dimension/common.terminals
@@ -270,7 +270,7 @@
%token DMNSN_T_MATERIAL
%token DMNSN_T_MATERIAL_MAP
%token DMNSN_T_MATRIX
-%token DMNSN_T_MAX
+%token DMNSN_T_MAX "max"
%token DMNSN_T_MAX_EXTENT
%token DMNSN_T_MAX_GRADIENT
%token DMNSN_T_MAX_INTERSECTIONS
@@ -287,7 +287,7 @@
%token DMNSN_T_METALLIC
%token DMNSN_T_METHOD
%token DMNSN_T_METRIC
-%token DMNSN_T_MIN
+%token DMNSN_T_MIN "min"
%token DMNSN_T_MIN_EXTENT
%token DMNSN_T_MINIMUM_REUSE
%token DMNSN_T_MOD "mod"
diff --git a/dimension/grammar.epilogue b/dimension/grammar.epilogue
index 05e9741..6a4a85f 100644
--- a/dimension/grammar.epilogue
+++ b/dimension/grammar.epilogue
@@ -197,6 +197,8 @@ dmnsn_astnode_string(dmnsn_astnode_type astnode_type)
dmnsn_astnode_map(DMNSN_AST_INT, "int" );
dmnsn_astnode_map(DMNSN_AST_LN, "ln" );
dmnsn_astnode_map(DMNSN_AST_LOG, "log" );
+ dmnsn_astnode_map(DMNSN_AST_MAX, "max" );
+ dmnsn_astnode_map(DMNSN_AST_MIN, "min" );
dmnsn_astnode_map(DMNSN_AST_MOD, "mod" );
dmnsn_astnode_map(DMNSN_AST_POW, "pow" );
dmnsn_astnode_map(DMNSN_AST_RADIANS, "radians");
diff --git a/dimension/lexer.l b/dimension/lexer.l
index 79d0a51..a2cf342 100644
--- a/dimension/lexer.l
+++ b/dimension/lexer.l
@@ -214,7 +214,9 @@ unsigned long wchar;
"log" RETURN_TOKEN(DMNSN_T_LOG);
"look_at" RETURN_TOKEN(DMNSN_T_LOOK_AT);
"light_source" RETURN_TOKEN(DMNSN_T_LIGHT_SOURCE);
+"max" RETURN_TOKEN(DMNSN_T_MAX);
"max_trace_level" RETURN_TOKEN(DMNSN_T_MAX_TRACE_LEVEL);
+"min" RETURN_TOKEN(DMNSN_T_MIN);
"mod" RETURN_TOKEN(DMNSN_T_MOD);
"perspective" RETURN_TOKEN(DMNSN_T_PERSPECTIVE);
"phong" RETURN_TOKEN(DMNSN_T_PHONG);
diff --git a/dimension/parse.c b/dimension/parse.c
index fb9de1c..177a96c 100644
--- a/dimension/parse.c
+++ b/dimension/parse.c
@@ -1184,6 +1184,12 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
case DMNSN_AST_INT_DIV:
dmnsn_make_ast_integer(&ret, l/r);
break;
+ case DMNSN_AST_MAX:
+ dmnsn_make_ast_integer(&ret, l > r ? l : r);
+ break;
+ case DMNSN_AST_MIN:
+ dmnsn_make_ast_integer(&ret, l < r ? l : r);
+ break;
case DMNSN_AST_MOD:
dmnsn_make_ast_float(&ret, fmod(l, r));
break;
@@ -1287,6 +1293,36 @@ dmnsn_eval_binary(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
case DMNSN_AST_INT_DIV:
dmnsn_make_ast_float(&ret, trunc(l/r));
break;
+ case DMNSN_AST_MAX:
+ if (l > r) {
+ if (lhs.type == DMNSN_AST_INTEGER) {
+ dmnsn_make_ast_maybe_integer(&ret, l);
+ } else {
+ dmnsn_make_ast_float(&ret, l);
+ }
+ } else {
+ if (rhs.type == DMNSN_AST_INTEGER) {
+ dmnsn_make_ast_maybe_integer(&ret, r);
+ } else {
+ dmnsn_make_ast_float(&ret, r);
+ }
+ }
+ break;
+ case DMNSN_AST_MIN:
+ if (l < r) {
+ if (lhs.type == DMNSN_AST_INTEGER) {
+ dmnsn_make_ast_maybe_integer(&ret, l);
+ } else {
+ dmnsn_make_ast_float(&ret, l);
+ }
+ } else {
+ if (rhs.type == DMNSN_AST_INTEGER) {
+ dmnsn_make_ast_maybe_integer(&ret, r);
+ } else {
+ dmnsn_make_ast_float(&ret, r);
+ }
+ }
+ break;
case DMNSN_AST_MOD:
dmnsn_make_ast_float(&ret, fmod(l, r));
break;
@@ -1395,6 +1431,8 @@ dmnsn_eval(dmnsn_astnode astnode, dmnsn_symbol_table *symtable)
case DMNSN_AST_OR:
case DMNSN_AST_ATAN2:
case DMNSN_AST_INT_DIV:
+ case DMNSN_AST_MAX:
+ case DMNSN_AST_MIN:
case DMNSN_AST_MOD:
case DMNSN_AST_POW:
case DMNSN_AST_STRCMP:
diff --git a/dimension/parse.h b/dimension/parse.h
index 4648c87..ddd5e7a 100644
--- a/dimension/parse.h
+++ b/dimension/parse.h
@@ -109,6 +109,8 @@ typedef enum {
DMNSN_AST_INT,
DMNSN_AST_LN,
DMNSN_AST_LOG,
+ DMNSN_AST_MAX,
+ DMNSN_AST_MIN,
DMNSN_AST_MOD,
DMNSN_AST_POW,
DMNSN_AST_RADIANS,
diff --git a/tests/dimension/arithexp.pov b/tests/dimension/arithexp.pov
index c891b1c..d25be7d 100644
--- a/tests/dimension/arithexp.pov
+++ b/tests/dimension/arithexp.pov
@@ -100,6 +100,14 @@ sphere {
#error "log"
#end
+#if (max(-1.5, 0, 1) != 1)
+ #error "max"
+#end
+
+#if (min(-1.5, 0, 1) != -1.5)
+ #error "min"
+#end
+
#if (mod(3.5, 2) != 1.5)
#error "mod"
#end