diff --git a/parser/nodes.cc b/parser/nodes.cc index f98008a..7af3eca 100644 --- a/parser/nodes.cc +++ b/parser/nodes.cc @@ -1,6 +1,11 @@ +#include + +#include +#include + #include "nodes.h" -#include + using namespace std; void Node::addChildren(refptr other) @@ -19,3 +24,23 @@ void Node::addChildren(refptr other) Node::~Node() { } + +double BinOpNode::getNumber() +{ + double o = one->getNumber(); + double t = two->getNumber(); + switch (m_op) + { + case '*': + return o * t; + case '/': + return o / t; + case '+': + return o + t; + case '-': + return o - t; + default: + cerr << "Error: BinOpNode created with op '" << m_op << "'" << endl; + exit(-3); + } +} diff --git a/parser/nodes.h b/parser/nodes.h index 275b871..edca3b4 100644 --- a/parser/nodes.h +++ b/parser/nodes.h @@ -15,16 +15,17 @@ class Node void addChildren(refptr other); std::vector< refptr > & getChildren() { return m_children; } - virtual int getInteger() { return 0; } - virtual double getNumber() { return 0.0; } - virtual refptr getVector() + virtual int getInteger() const { return 0; } + virtual double getNumber() const { return 0.0; } + virtual refptr getVector() const { return refptr(NULL); } - virtual bool isShape() { return false; } - virtual bool isMaterial() { return false; } - virtual bool isTransformBlock() { return false; } - virtual std::string getString() { return ""; } + virtual bool isShape() const { return false; } + virtual bool isMaterial() const { return false; } + virtual bool isTransformBlock() const { return false; } + virtual std::string getString() const { return ""; } + virtual bool isExpression() const { return false; } protected: std::vector< refptr > m_children; @@ -375,5 +376,28 @@ class WidthNode : public IntegerNode WidthNode(int i) : IntegerNode(i) {} }; +/******** scripting nodes ********/ + +class ExpressionNode : public Node +{ + public: + bool isExpression() const { return true; } + virtual double getInteger() { return getNumber(); } +}; + +class BinOpNode : public ExpressionNode +{ + public: + BinOpNode(char op, refptr one, refptr two) + : m_op(op), one(one), two(two) + { + } + virtual double getNumber(); + protected: + char m_op; + refptr one; + refptr two; +}; + #endif diff --git a/parser/parser.lex b/parser/parser.lex index 6b1ffc5..79cc0c7 100644 --- a/parser/parser.lex +++ b/parser/parser.lex @@ -14,7 +14,7 @@ \+ return PLUS; - return MINUS; -\* return STAR; +\* return TIMES; \/ return DIVIDE; % return MOD; diff --git a/parser/parser.yy b/parser/parser.yy index ebcb092..9be6450 100644 --- a/parser/parser.yy +++ b/parser/parser.yy @@ -33,7 +33,7 @@ static refptr parsed_scene_node; %token PLUS; %token MINUS; -%token STAR; +%token TIMES; %token DIVIDE; %token MOD; @@ -102,6 +102,10 @@ static refptr parsed_scene_node; %token IDENTIFIER; +%left PLUS MINUS +%left TIMES DIVIDE +%left UMINUS + %% scene: SCENE LCURLY scene_items RCURLY { @@ -168,7 +172,7 @@ camera_item: POSITION vector3 { | UP vector3 { $$ = new UpNode($2->getVector()); } - | VFOV number { + | VFOV expression { $$ = new VFOVNode($2->getNumber()); } ; @@ -219,7 +223,7 @@ intersect: INTERSECT LCURLY bool_items RCURLY { } ; -jitter: JITTER number { +jitter: JITTER expression { $$ = new JitterNode($2->getInteger()); } ; @@ -284,13 +288,13 @@ material_item: COLOR vector3 { | SPECULAR vector3 { $$ = new SpecularNode($2->getVector()); } - | REFLECTANCE number { + | REFLECTANCE expression { $$ = new ReflectanceNode($2->getNumber()); } - | SHININESS number { + | SHININESS expression { $$ = new ShininessNode($2->getNumber()); } - | TRANSPARENCY number { + | TRANSPARENCY expression { $$ = new TransparencyNode($2->getNumber()); } ; @@ -310,16 +314,16 @@ number: DEC_NUMBER { $$ = $1; } | REAL_NUMBER { $$ = $1; } ; -ngon: NGON DEC_NUMBER COMMA number { +ngon: NGON DEC_NUMBER COMMA expression { $$ = new NGonNode($2->getInteger()); $$->addChild(new RadiusNode($4->getNumber())); } ; -offset: OFFSET number { +offset: OFFSET expression { $$ = new OffsetNode($2->getNumber()); } - | OFFSET number LCURLY offset_items RCURLY { + | OFFSET expression LCURLY offset_items RCURLY { $$ = new OffsetNode($2->getNumber()); $$->addChildren($4); } @@ -333,7 +337,7 @@ offset_items: /* empty */ } ; -offset_item: SCALE number { +offset_item: SCALE expression { $$ = new ScaleNode(new Vector($2->getNumber(), $2->getNumber(), $2->getNumber())); } @@ -371,7 +375,7 @@ options_item: WIDTH DEC_NUMBER { | MAXDEPTH DEC_NUMBER { $$ = new MaxDepthNode($2->getInteger()); } - | EXPOSURE number { + | EXPOSURE expression { $$ = new ExposureNode($2->getNumber()); } | AMBIENT vector3 { @@ -396,7 +400,7 @@ plane_items: /* empty */ } ; -plane_item: POSITION vector3 COMMA number { +plane_item: POSITION vector3 COMMA expression { $$ = new PlanePositionNode($2->getVector(), $4->getNumber()); } | shape_item { $$ = $1; } @@ -419,7 +423,7 @@ polygon_items: /* empty */ polygon_item: vector2 { $$ = $1; } ; -radius: RADIUS number { +radius: RADIUS expression { $$ = new RadiusNode($2->getNumber()); } ; @@ -508,13 +512,13 @@ subtract: SUBTRACT LCURLY bool_items RCURLY { transform: TRANSLATE vector3 { $$ = new TranslateNode($2->getVector()); } - | ROTATE number COMMA vector3 { + | ROTATE expression COMMA vector3 { $$ = new RotateNode($2->getNumber(), $4->getVector()); } | SCALE vector3 { $$ = new ScaleNode($2->getVector()); } - | SCALE number { + | SCALE expression { $$ = new ScaleNode(new Vector($2->getNumber(), $2->getNumber(), $2->getNumber())); } @@ -524,7 +528,7 @@ transform_block: TRANSLATE vector3 LCURLY transform_block_items RCURLY { $$ = new TranslateBlockNode($2->getVector()); $$->addChildren($4); } - | ROTATE number COMMA vector3 LCURLY transform_block_items RCURLY { + | ROTATE expression COMMA vector3 LCURLY transform_block_items RCURLY { $$ = new RotateBlockNode($2->getNumber(), $4->getVector()); $$->addChildren($6); } @@ -532,7 +536,7 @@ transform_block: TRANSLATE vector3 LCURLY transform_block_items RCURLY { $$ = new ScaleBlockNode($2->getVector()); $$->addChildren($4); } - | SCALE number LCURLY transform_block_items RCURLY { + | SCALE expression LCURLY transform_block_items RCURLY { $$ = new ScaleBlockNode( new Vector($2->getNumber(), $2->getNumber(), $2->getNumber())); @@ -559,20 +563,37 @@ union: UNION LCURLY bool_items RCURLY { } ; -vector2: LESS number COMMA number GREATER { +vector2: LESS expression COMMA expression GREATER { refptr vec = new Vector($2->getNumber(), $4->getNumber(), 0.0); $$ = new VectorNode(vec); } ; -vector3: LESS number COMMA number COMMA number GREATER { +vector3: LESS expression COMMA expression COMMA expression GREATER { refptr vec = new Vector($2->getNumber(), $4->getNumber(), $6->getNumber()); $$ = new VectorNode(vec); } ; +expression: term { $$ = $1; } + | expression TIMES term { $$ = new BinOpNode('*', $1, $3); } + | expression DIVIDE term { $$ = new BinOpNode('/', $1, $3); } + | MINUS expression %prec UMINUS { + $$ = new BinOpNode('-', new NumberNode(0.0), $2); + } + ; + +term: factor { $$ = $1; } + | term PLUS factor { $$ = new BinOpNode('+', $1, $3); } + | term MINUS factor { $$ = new BinOpNode('-', $1, $3); } + ; + +factor: number { $$ = $1; } + | LPAREN expression RPAREN { $$ = $2; } + ; + %% refptr parse(const char * fileName)