fart/parser/parser.yy

511 lines
14 KiB
Plaintext

%{
#include <stdio.h>
#include <iostream>
#include "util/Vector.h"
#include "util/refptr.h"
#include "util/Scope.h"
#include "nodes.h"
#include "parser.h"
#include "parser.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<Node> parsed_scene_node;
refptr<Scope> parser_scope;
%}
%pure-parser
%locations
%error-verbose
%token PLUS;
%token MINUS;
%token TIMES;
%token DIVIDE;
%token MOD;
%token POW;
%token ASSIGN;
%token EQUALS;
%token NOTEQUALS;
%token LESS;
%token LESSEQ;
%token GREATER;
%token GREATEREQ;
%token AND
%token OR
%token NOT;
%token SEMICOLON;
%token COLON;
%token QUESTION;
%token DOLLAR;
%token DOT;
%token COMMA;
%token LCURLY;
%token RCURLY;
%token LBRACKET;
%token RBRACKET;
%token LPAREN;
%token RPAREN;
%token REAL_NUMBER;
%token STRING;
%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 REFRACTION;
%token ROTATE;
%token SCALE;
%token SCENE;
%token SHAPE;
%token SHININESS;
%token SIZE;
%token SPECULAR;
%token SPHERE;
%token SUBTRACT;
%token TEXTURE;
%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 AND OR NOT
%left PLUS MINUS
%left TIMES DIVIDE MOD
%right POW
%left UMINUS
%%
scene: SCENE LCURLY general_items RCURLY {
$$ = new SceneNode();
$$->addChildren($3);
parsed_scene_node = $$;
}
;
box: BOX LCURLY general_items RCURLY {
$$ = new BoxNode();
$$->addChildren($3);
}
;
camera: CAMERA LCURLY general_items RCURLY {
$$ = new CameraNode();
$$->addChildren($3);
}
;
cyl: CYL LCURLY general_items RCURLY {
$$ = new CylNode();
$$->addChildren($3);
}
;
extrude: EXTRUDE LCURLY general_items RCURLY {
$$ = new ExtrudeNode();
$$->addChildren($3);
}
;
general_items: /* empty */ { $$ = NULL; }
| general_item general_items {
$$ = new ItemsNode();
$$->addChild($1);
$$->addChildren($2);
}
;
general_item: AMBIENT vector3 { $$ = new AmbientNode($2); }
| AMBIENT_OCCLUSION expression {
$$ = new AmbientOcclusionNode($2);
}
| camera { $$ = $1; }
| COLOR vector3 { $$ = new ColorNode($2); }
| DIFFUSE vector3 { $$ = new DiffuseNode($2); }
| EXPOSURE expression { $$ = new ExposureNode($2); }
| for { $$ = $1; }
| HEIGHT expression { $$ = new HeightNode($2); }
| if { $$ = $1; }
| JITTER expression { $$ = new JitterNode($2); }
| light { $$ = $1; }
| LOOKAT vector3 { $$ = new LookAtNode($2); }
| material { $$ = $1; }
| material_definition { $$ = $1; }
| material_ref { $$ = $1; }
| MAXDEPTH expression { $$ = new MaxDepthNode($2); }
| MULTISAMPLE expression { $$ = new MultisampleNode($2); }
| ngon { $$ = $1; }
| offset { $$ = $1; }
| options { $$ = $1; }
| polygon { $$ = $1; }
| POSITION vector3 { $$ = new PositionNode($2); }
| POSITION vector3 COMMA expression {
$$ = new PlanePositionNode($2, $4);
}
| RADIUS expression { $$ = new RadiusNode($2); }
| REFLECTANCE expression { $$ = new ReflectanceNode($2); }
| REFRACTION expression { $$ = new RefractionNode($2); }
| ROTATE expression COMMA vector3 { $$ = new RotateNode($2, $4); }
| SCALE expression { $$ = new ScaleNode(new ScaleScalarNode($2)); }
| SCALE vector2 { $$ = new ScaleNode($2); }
| SCALE vector3 { $$ = new ScaleNode($2); }
| shape { $$ = $1; }
| shape_definition { $$ = $1; }
| SHININESS expression { $$ = new ShininessNode($2); }
| SIZE vector3 { $$ = new SizeNode($2); }
| SPECULAR vector3 { $$ = new SpecularNode($2); }
| stmt_expression { $$ = $1; }
| TEXTURE STRING { $$ = new TextureNode($2->getString()); }
| transform_block { $$ = $1; }
| TRANSLATE vector3 { $$ = new TranslateNode($2); }
| TRANSPARENCY expression { $$ = new TransparencyNode($2); }
| UP vector3 { $$ = new UpNode($2); }
| vector2 { $$ = $1; }
| VFOV expression { $$ = new VFOVNode($2); }
| while { $$ = $1; }
| WIDTH expression { $$ = new WidthNode($2); }
;
intersect: INTERSECT LCURLY general_items RCURLY {
$$ = new IntersectNode();
$$->addChildren($3);
}
;
light: LIGHT LCURLY general_items RCURLY {
$$ = new LightNode();
$$->addChildren($3);
}
;
material: MATERIAL LCURLY general_items RCURLY {
$$ = new MaterialNode();
$$->addChildren($3);
}
;
material_definition: DEFINE MATERIAL IDENTIFIER LCURLY general_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 general_items RCURLY {
$$ = new OffsetNode($2);
$$->addChildren($4);
}
;
options: OPTIONS LCURLY general_items RCURLY {
$$ = new OptionsNode();
$$->addChildren($3);
}
;
plane: PLANE LCURLY general_items RCURLY {
$$ = new PlaneNode();
$$->addChildren($3);
}
;
polygon: POLYGON LCURLY general_items RCURLY {
$$ = new PolygonNode();
$$->addChildren($3);
}
;
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 */ { $$ = NULL; }
| LCURLY general_items RCURLY { $$ = $2; }
;
sphere: SPHERE LCURLY general_items RCURLY {
$$ = new SphereNode();
$$->addChildren($3);
}
;
subtract: SUBTRACT LCURLY general_items RCURLY {
$$ = new SubtractNode();
$$->addChildren($3);
}
;
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 general_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: expression TIMES expression { $$ = new BinOpNode('*', $1, $3); }
| expression DIVIDE expression { $$ = new BinOpNode('/', $1, $3); }
| expression PLUS expression { $$ = new BinOpNode('+', $1, $3); }
| expression MINUS expression { $$ = new BinOpNode('-', $1, $3); }
| expression MOD expression { $$ = new BinOpNode('%', $1, $3); }
| expression POW expression { $$ = new BinOpNode('^', $1, $3); }
| MINUS expression %prec UMINUS {
$$ = new BinOpNode('-', new NumberNode(0.0), $2);
}
| stmt_expression { $$ = $1; }
| function_call { $$ = $1; }
| number { $$ = $1; }
| VARREF { $$ = $1; }
| LPAREN expression RPAREN { $$ = $2; }
;
maybe_expression: /* empty */ { $$ = NULL; }
| 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);
}
| bool_expression AND bool_expression {
$$ = new BoolExpressionNode('&', $1, $3);
}
| bool_expression OR bool_expression {
$$ = new BoolExpressionNode('|', $1, $3);
}
| NOT bool_expression {
$$ = new BoolExpressionNode('!', $2, NULL);
}
| LPAREN bool_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);
}
;
while: WHILE LPAREN bool_expression RPAREN LCURLY general_items RCURLY {
$$ = new ForNode(NULL, $3, NULL);
$$->addChildren($6);
}
;
if: IF LPAREN bool_expression RPAREN LCURLY general_items RCURLY if_more {
$$ = new IfNode($3, $8);
$$->addChildren($6);
}
;
if_more: /* empty */ { $$ = NULL; }
| ELSIF LPAREN bool_expression RPAREN LCURLY general_items RCURLY if_more {
$$ = new IfNode($3, $8);
$$->addChildren($6);
}
| ELSE LCURLY general_items RCURLY {
$$ = new ElseNode();
$$->addChildren($3);
}
;
function_call: IDENTIFIER LPAREN function_call_parameters RPAREN {
$$ = new FunctionCallNode($1, $3);
}
;
function_call_parameters: /* empty */ { $$ = NULL; }
| expression function_call_more_parameters {
$$ = new ItemsNode();
$$->addChild($1);
$$->addChildren($2);
}
;
function_call_more_parameters: /* empty */ { $$ = NULL; }
| COMMA expression function_call_more_parameters {
$$ = new ItemsNode();
$$->addChild($2);
$$->addChildren($3);
}
;
%%
refptr<Node> parse(const char * fileName, refptr<Scope> scope)
{
parser_scope = scope;
yyin = fopen(fileName, "r");
if (yyin == NULL)
{
cerr << "Failed to open file '" << fileName << "'" << endl;
return refptr<Node>(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);
}