%{ #include #include #include "main/Scene.h" #include "main/Material.h" #include "util/Vector.h" #include "util/refptr.h" #include "shapes/Shape.h" /* includes all shape types */ #include "nodes.h" using namespace std; extern "C" { int yylex(void); } extern FILE * yyin; extern char * yytext; void yyerror(const char * str) { fprintf(stderr, "error: %s\n", str); } int yywrap() { return 1; } #define YYSTYPE refptr static Scene * g_scene; %} %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 SCENE; %token SHININESS; %token SIZE; %token SPECULAR; %token SPHERE; %token SUBTRACT; %token UNION; %token UP; %token VFOV; %token WIDTH; %% scene: SCENE LCURLY scene_items RCURLY { $$ = new SceneNode(); $$->addChildren($3); } ; 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 { $$ = new NumberNode(atoi(yytext)); } | REAL_NUMBER { $$ = new NumberNode(atof(yytext)); } ; 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(atoi(yytext)); } | HEIGHT DEC_NUMBER { $$ = new HeightNode(atoi(yytext)); } | MULTISAMPLE DEC_NUMBER { $$ = new MultisampleNode(atoi(yytext)); } ; 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; } ; 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; } ; 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); } ; 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); } ; %% int Scene::parse(const char * fileName) { g_scene = this; yyin = fopen(fileName, "r"); if (yyin == NULL) { cerr << "Failed to open file '" << fileName << "'" << endl; return -1; } yyparse(); return 0; }