%{ #include #include #include "util/Vector.h" #include "util/refptr.h" #include "util/Scope.h" #include "nodes.h" #include "parser.h" #include "parser.tab.hh" /* bison-generated header with YY[SL]TYPE */ using namespace std; #define yyerror(msg) errFunc(msg, &yylloc) int yylex(YYSTYPE *, YYLTYPE *); extern FILE * yyin; void errFunc(const char * str, YYLTYPE * yyllocp); int yywrap() { return 1; } static refptr parsed_scene_node; refptr parser_scope; %} %pure-parser %locations %error-verbose %token PLUS; %token MINUS; %token TIMES; %token DIVIDE; %token MOD; %token ASSIGN; %token EQUALS; %token NOTEQUALS; %token NOT; %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 LESSEQ; %token GREATER; %token GREATEREQ; %token REAL_NUMBER; %token AMBIENT; %token AMBIENT_OCCLUSION; %token BOX; %token CAMERA; %token COLOR; %token CYL; %token DEFINE; %token DIFFUSE; %token EXPOSURE; %token EXTRUDE; %token HEIGHT; %token INTERSECT; %token JITTER; %token LIGHT; %token LOOKAT; %token MATERIAL; %token MAXDEPTH; %token MULTISAMPLE; %token NGON; %token OFFSET; %token OPTIONS; %token PLANE; %token POLYGON; %token POSITION; %token RADIUS; %token REFLECTANCE; %token ROTATE; %token SCALE; %token SCENE; %token SHAPE; %token SHININESS; %token SIZE; %token SPECULAR; %token SPHERE; %token SUBTRACT; %token TRANSLATE; %token TRANSPARENCY; %token UNION; %token UP; %token VFOV; %token WIDTH; %token IDENTIFIER; %token VARREF; %token ELSE; %token ELSIF; %token FOR; %token IF; %token WHILE; %token LOCAL; %right ASSIGN %left PLUS MINUS %left TIMES DIVIDE MOD %left UMINUS %% scene: SCENE LCURLY scene_items RCURLY { $$ = new SceneNode(); $$->addChildren($3); parsed_scene_node = $$; } ; bool_items: /* empty */ | bool_item bool_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; bool_item: shape | shape_item | shape_definition | transform_block ; 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 vector3 { $$ = new SizeNode($2); } | shape_item { $$ = $1; } ; camera: CAMERA LCURLY camera_items RCURLY { $$ = new CameraNode(); $$->addChildren($3); } ; camera_items: /* empty */ | camera_item camera_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; camera_item: POSITION vector3 { $$ = new PositionNode($2); } | LOOKAT vector3 { $$ = new LookAtNode($2); } | UP vector3 { $$ = new UpNode($2); } | VFOV expression { $$ = new VFOVNode($2); } ; cyl: CYL LCURLY cyl_items RCURLY { $$ = new CylNode(); $$->addChildren($3); } ; cyl_items: /* empty */ | cyl_item cyl_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; cyl_item: SIZE vector3 { $$ = new SizeNode($2); } | shape_item { $$ = $1; } ; extrude: EXTRUDE LCURLY extrude_items RCURLY { $$ = new ExtrudeNode(); $$->addChildren($3); } ; extrude_items: /* empty */ | extrude_item extrude_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; extrude_item: polygon { $$ = $1; } | ngon { $$ = $1; } | offset { $$ = $1; } | shape_item { $$ = $1; } ; general_items: /* empty */ | general_item general_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; general_item: transform_block { $$ = $1; } | material_definition { $$ = $1; } | shape_definition { $$ = $1; } | shape { $$ = $1; } | for { $$ = $1; } | if { $$ = $1; } | stmt_expression { $$ = $1; } ; intersect: INTERSECT LCURLY bool_items RCURLY { $$ = new IntersectNode(); $$->addChildren($3); } ; jitter: JITTER expression { $$ = new JitterNode($2); } ; 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 vector3 { $$ = new PositionNode($2); } | DIFFUSE vector3 { $$ = new DiffuseNode($2); } | SPECULAR vector3 { $$ = new SpecularNode($2); } | COLOR vector3 { $$ = new ColorNode($2); } | radius { $$ = $1; } | jitter { $$ = $1; } ; 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: COLOR vector3 { $$ = new ColorNode($2); } | AMBIENT vector3 { $$ = new AmbientNode($2); } | DIFFUSE vector3 { $$ = new DiffuseNode($2); } | SPECULAR vector3 { $$ = new SpecularNode($2); } | REFLECTANCE expression { $$ = new ReflectanceNode($2); } | SHININESS expression { $$ = new ShininessNode($2); } | TRANSPARENCY expression { $$ = new TransparencyNode($2); } ; material_definition: DEFINE MATERIAL IDENTIFIER LCURLY material_items RCURLY { $$ = new MaterialDefinitionNode($3->getString()); $$->addChildren($5); } ; material_ref: MATERIAL IDENTIFIER { $$ = new MaterialRefNode($2->getString()); } ; number: REAL_NUMBER { $$ = $1; } ; ngon: NGON expression COMMA expression { $$ = new NGonNode($2); $$->addChild(new RadiusNode($4)); } ; offset: OFFSET expression { $$ = new OffsetNode($2); } | OFFSET expression LCURLY offset_items RCURLY { $$ = new OffsetNode($2); $$->addChildren($4); } ; offset_items: /* empty */ | offset_item offset_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; offset_item: SCALE expression { $$ = new ScaleNode(new ScaleScalarNode($2)); } | SCALE vector2 { $$ = new ScaleNode($2); } | POSITION vector2 { $$ = new PositionNode($2); } ; 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 expression { $$ = new WidthNode($2); } | HEIGHT expression { $$ = new HeightNode($2); } | MULTISAMPLE expression { $$ = new MultisampleNode($2); } | MAXDEPTH expression { $$ = new MaxDepthNode($2); } | EXPOSURE expression { $$ = new ExposureNode($2); } | AMBIENT vector3 { $$ = new AmbientNode($2); } | AMBIENT_OCCLUSION expression { $$ = new AmbientOcclusionNode($2); } ; 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 vector3 COMMA expression { $$ = new PlanePositionNode($2, $4); } | shape_item { $$ = $1; } ; polygon: POLYGON LCURLY polygon_items RCURLY { $$ = new PolygonNode(); $$->addChildren($3); } ; polygon_items: /* empty */ | polygon_item polygon_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; polygon_item: vector2 { $$ = $1; } ; radius: RADIUS expression { $$ = new RadiusNode($2); } ; scene_items: /* empty */ | scene_item scene_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; scene_item: camera { $$ = $1; } | light { $$ = $1; } | options { $$ = $1; } | general_item { $$ = $1; } ; shape: plane { $$ = $1; } | sphere { $$ = $1; } | box { $$ = $1; } | cyl { $$ = $1; } | union { $$ = $1; } | intersect { $$ = $1; } | subtract { $$ = $1; } | extrude { $$ = $1; } | shape_ref { $$ = $1; } ; shape_definition: DEFINE SHAPE IDENTIFIER shape { $$ = new ShapeDefinitionNode($3->getString()); $$->addChild($4); } ; shape_ref: SHAPE IDENTIFIER shape_ref_more { $$ = new ShapeRefNode($2->getString()); $$->addChildren($3); } ; shape_ref_more: /* empty */ | LCURLY shape_ref_items RCURLY { $$ = $2; } ; shape_ref_items: /* empty */ | shape_item shape_ref_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; shape_item: material { $$ = $1; } | material_ref { $$ = $1; } | transform { $$ = $1; } ; sphere: SPHERE LCURLY sphere_items RCURLY { $$ = new SphereNode(); $$->addChildren($3); } ; sphere_items: /* empty */ | sphere_item sphere_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; sphere_item: radius { $$ = $1; } | shape_item { $$ = $1; } ; subtract: SUBTRACT LCURLY bool_items RCURLY { $$ = new SubtractNode(); $$->addChildren($3); } ; transform: TRANSLATE vector3 { $$ = new TranslateNode($2); } | ROTATE expression COMMA vector3 { $$ = new RotateNode($2, $4); } | SCALE vector3 { $$ = new ScaleNode($2); } | SCALE expression { $$ = new ScaleNode(new ScaleScalarNode($2)); } ; transform_block: TRANSLATE vector3 LCURLY general_items RCURLY { $$ = new TranslateBlockNode($2); $$->addChildren($4); } | ROTATE expression COMMA vector3 LCURLY general_items RCURLY { $$ = new RotateBlockNode($2, $4); $$->addChildren($6); } | SCALE vector3 LCURLY general_items RCURLY { $$ = new ScaleBlockNode($2); $$->addChildren($4); } | SCALE expression LCURLY general_items RCURLY { $$ = new ScaleBlockNode(new ScaleScalarNode($2)); $$->addChildren($4); } ; union: UNION LCURLY bool_items RCURLY { $$ = new UnionNode(); $$->addChildren($3); } ; vector2: LESS expression COMMA expression GREATER { $$ = new VectorNode($2, $4, new NumberNode(0.0)); } ; vector3: LESS expression COMMA expression COMMA expression GREATER { $$ = new VectorNode($2, $4, $6); } ; expression: term { $$ = $1; } | expression TIMES term { $$ = new BinOpNode('*', $1, $3); } | expression DIVIDE term { $$ = new BinOpNode('/', $1, $3); } | expression MOD term { $$ = new BinOpNode('%', $1, $3); } | MINUS expression %prec UMINUS { $$ = new BinOpNode('-', new NumberNode(0.0), $2); } | stmt_expression { $$ = $1; } ; maybe_expression: /* empty */ | expression { $$ = $1; } ; stmt_expression: assignment { $$ = $1; } | local_assignment { $$ = $1; } | local_decl { $$ = $1; } ; bool_expression: expression LESS expression { $$ = new BoolExpressionNode('<', $1, $3); } | expression LESSEQ expression { $$ = new BoolExpressionNode('l', $1, $3); } | expression GREATER expression { $$ = new BoolExpressionNode('>', $1, $3); } | expression GREATEREQ expression { $$ = new BoolExpressionNode('g', $1, $3); } | expression EQUALS expression { $$ = new BoolExpressionNode('=', $1, $3); } | expression NOTEQUALS expression { $$ = new BoolExpressionNode('n', $1, $3); } | NOT bool_expression { $$ = new BoolExpressionNode('!', $2, NULL); } ; term: factor { $$ = $1; } | term PLUS factor { $$ = new BinOpNode('+', $1, $3); } | term MINUS factor { $$ = new BinOpNode('-', $1, $3); } ; factor: number { $$ = $1; } | VARREF { $$ = $1; } | LPAREN expression RPAREN { $$ = $2; } ; assignment: VARREF ASSIGN expression { $$ = new AssignmentNode($1, $3); } ; local_assignment: LOCAL VARREF ASSIGN expression { $$ = new LocalAssignmentNode($2, $4); } ; local_decl: LOCAL VARREF { $$ = new LocalDeclNode($2); } ; for: FOR LPAREN maybe_expression SEMICOLON bool_expression SEMICOLON maybe_expression RPAREN LCURLY general_items RCURLY { $$ = new ForNode($3, $5, $7); $$->addChildren($10); } ; if: IF LPAREN bool_expression RPAREN LCURLY general_items RCURLY if_more { $$ = new IfNode($3, $8); $$->addChildren($6); } ; if_more: /* empty */ | ELSIF LPAREN bool_expression RPAREN LCURLY general_items RCURLY if_more { } | ELSE LCURLY general_items RCURLY { } ; %% refptr parse(const char * fileName, refptr scope) { parser_scope = scope; yyin = fopen(fileName, "r"); if (yyin == NULL) { cerr << "Failed to open file '" << fileName << "'" << endl; return refptr(NULL); } if (yyparse()) { cerr << "Aborting." << endl; exit(1); } return parsed_scene_node; } void errFunc(const char * str, YYLTYPE * yyllocp) { fprintf(stderr, "error: %s: line %d, column %d\n", str, yyllocp->first_line, yyllocp->first_column); }