%{ #include #include #include "util/Vector.h" #include "util/refptr.h" #include "nodes.h" #include "parser.h" using namespace std; int yylex(void); extern FILE * yyin; void yyerror(const char * str) { fprintf(stderr, "error: %s\n", str); } int yywrap() { return 1; } static refptr parsed_scene_node; %} %token PLUS; %token MINUS; %token STAR; %token DIVIDE; %token MOD; %token SEMICOLON; %token COLON; %token QUESTION; %token DOLLAR; %token DOT; %token DQUOTE; %token SQUOTE; %token COMMA; %token LCURLY; %token RCURLY; %token LBRACKET; %token RBRACKET; %token LPAREN; %token RPAREN; %token LESS; %token GREATER; %token DEC_NUMBER; %token REAL_NUMBER; %token AMBIENT; %token BOX; %token CAMERA; %token DIFFUSE; %token HEIGHT; %token INTERSECT; %token LIGHT; %token LOOKAT; %token MATERIAL; %token MULTISAMPLE; %token OPTIONS; %token PLANE; %token POSITION; %token RADIUS; %token REFLECTANCE; %token ROTATE; %token SCALE; %token SCENE; %token SHININESS; %token SIZE; %token SPECULAR; %token SPHERE; %token SUBTRACT; %token TRANSLATE; %token UNION; %token UP; %token VFOV; %token WIDTH; %% scene: SCENE LCURLY scene_items RCURLY { $$ = new SceneNode(); $$->addChildren($3); parsed_scene_node = $$; } ; box: BOX LCURLY box_items RCURLY { $$ = new BoxNode(); $$->addChildren($3); } ; box_items: /* empty */ | box_item box_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; box_item: SIZE vector { $$ = new SizeNode($2->getVector()); } | shape_item { $$ = $1; } ; camera: CAMERA LCURLY camera_items RCURLY { Vector default_position(0, -1, 0); Vector default_look_at(0, 0, 0); Vector default_up(0, 0, 1); } ; camera_items: /* empty */ | camera_item camera_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; camera_item: POSITION vector { $$ = new PositionNode(); $$->addChild($2); } | LOOKAT vector { $$ = new LookAtNode(); $$->addChild($2); } | UP vector { $$ = new UpNode(); $$->addChild($2); } | VFOV vector { $$ = new VFOVNode(); $$->addChild($2); } ; intersect: INTERSECT LCURLY shape shape shape_items RCURLY { $$ = new IntersectNode(); $$->addChild($3); $$->addChild($4); $$->addChildren($5); } ; light: LIGHT LCURLY light_items RCURLY { $$ = new LightNode(); $$->addChildren($3); } ; light_items: /* empty */ | light_item light_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; light_item: POSITION vector { $$ = new PositionNode(); $$->addChild($2); } | DIFFUSE vector { $$ = new DiffuseNode(); $$->addChild($2); } | SPECULAR vector { $$ = new SpecularNode(); $$->addChild($2); } ; material: MATERIAL LCURLY material_items RCURLY { $$ = new MaterialNode(); $$->addChildren($3); } ; material_items: /* empty */ | material_item material_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; material_item: AMBIENT vector { $$ = new AmbientNode(); $$->addChild($2); } | DIFFUSE vector { $$ = new DiffuseNode(); $$->addChild($2); } | SPECULAR vector { $$ = new SpecularNode(); $$->addChild($2); } | REFLECTANCE number { $$ = new ReflectanceNode($2->getNumber()); } | SHININESS number { $$ = new ShininessNode($2->getNumber()); } ; number: DEC_NUMBER { $$ = $1; } | REAL_NUMBER { $$ = $1; } ; options: OPTIONS LCURLY options_items RCURLY { $$ = new OptionsNode(); $$->addChildren($3); } ; options_items: /* empty */ | options_item options_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; options_item: WIDTH DEC_NUMBER { $$ = new WidthNode($2->getInteger()); } | HEIGHT DEC_NUMBER { $$ = new HeightNode($2->getInteger()); } | MULTISAMPLE DEC_NUMBER { $$ = new MultisampleNode($2->getInteger()); } ; plane: PLANE LCURLY plane_items RCURLY { $$ = new PlaneNode(); $$->addChildren($3); } ; plane_items: /* empty */ | plane_item plane_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; plane_item: POSITION vector COMMA number { $$ = new PlanePositionNode($2->getVector(), $4->getNumber()); } | shape_item { $$ = $1; } ; radius: RADIUS number { $$ = new RadiusNode($2->getNumber()); } ; scene_items: /* empty */ | scene_item scene_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; scene_item: camera { $$ = $1; } | shape { $$ = $1; } | options { $$ = $1; } | light { $$ = $1; } | transform_block { $$ = $1; } ; shape: plane { $$ = $1; } | sphere { $$ = $1; } | box { $$ = $1; } | union { $$ = $1; } | intersect { $$ = $1; } | subtract { $$ = $1; } ; shape_items: /* empty */ | shape_item shape_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; shape_item: material { $$ = $1; } | transform { $$ = $1; } ; sphere: SPHERE LCURLY sphere_items RCURLY { $$ = new SphereNode(); $$->addChild($3); } ; sphere_items: /* empty */ | sphere_item sphere_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; sphere_item: radius { $$ = $1; } | shape_item { $$ = $1; } ; subtract: SUBTRACT LCURLY shape shape shape_items RCURLY { $$ = new SubtractNode(); $$->addChild($3); $$->addChild($4); $$->addChildren($5); } ; transform: TRANSLATE vector { $$ = new TranslateNode($2->getVector()); } | ROTATE number COMMA vector { $$ = new RotateNode($2->getNumber(), $4->getVector()); } | SCALE vector { $$ = new ScaleNode($2->getVector()); } ; transform_block: TRANSLATE vector LCURLY transform_block_items RCURLY { $$ = new TranslateBlockNode($2->getVector()); $$->addChildren($4); } | ROTATE number COMMA vector LCURLY transform_block_items RCURLY { $$ = new RotateBlockNode($2->getNumber(), $4->getVector()); $$->addChildren($6); } | SCALE vector LCURLY transform_block_items RCURLY { $$ = new ScaleBlockNode($2->getVector()); $$->addChildren($4); } ; transform_block_items: /* empty */ | transform_block_item transform_block_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; transform_block_item: transform_block { $$ = $1; } | light { $$ = $1; } | shape { $$ = $1; } ; union: UNION LCURLY shape shape shape_items RCURLY { $$ = new UnionNode(); $$->addChild($3); $$->addChild($4); $$->addChildren($5); } ; vector: LESS number COMMA number COMMA number GREATER { refptr vec = new Vector(); (*vec)[0] = $2->getNumber(); (*vec)[1] = $4->getNumber(); (*vec)[2] = $6->getNumber(); $$ = new VectorNode(vec); } ; %% refptr parse(const char * fileName) { yyin = fopen(fileName, "r"); if (yyin == NULL) { cerr << "Failed to open file '" << fileName << "'" << endl; return refptr(NULL); } yyparse(); return parsed_scene_node; }