diff options
Diffstat (limited to 'dimension/grammar.y')
-rw-r--r-- | dimension/grammar.y | 1119 |
1 files changed, 1119 insertions, 0 deletions
diff --git a/dimension/grammar.y b/dimension/grammar.y new file mode 100644 index 0000000..426bc29 --- /dev/null +++ b/dimension/grammar.y @@ -0,0 +1,1119 @@ +/************************************************************************* + * Copyright (C) 2009 Tavian Barnes <tavianator@gmail.com> * + * * + * This file is part of Dimension. * + * * + * Dimension is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 3 of the License, or (at * + * your option) any later version. * + * * + * Dimension is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +%{ +#include "parse.h" +#include "tokenize.h" +#include "utility.h" +#include <stdlib.h> +#include <stdio.h> + +typedef struct dmnsn_token_iterator { + const dmnsn_array *tokens; + unsigned int i; +} dmnsn_token_iterator; + +typedef struct dmnsn_location { + const char *first_filename, *last_filename; + int first_line, last_line; + int first_column, last_column; +} dmnsn_location; + +typedef union YYSTYPE { + const char *value; + dmnsn_astnode astnode; +} YYSTYPE; + +#define YYLTYPE dmnsn_location +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do { \ + if (N) { \ + (Current).first_filename = YYRHSLOC(Rhs, 1).first_filename; \ + (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ + (Current).last_filename = YYRHSLOC(Rhs, N).last_filename; \ + (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC(Rhs, N).last_column; \ + } else { \ + (Current).first_filename = (Current).last_filename = \ + YYRHSLOC(Rhs, 0).last_filename; \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC(Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC(Rhs, 0).last_column; \ + } \ + } while (0) + +/* Create a new astnode, populating filename, line, and col */ + +static dmnsn_astnode +dmnsn_copy_astnode(dmnsn_astnode astnode) +{ + dmnsn_astnode copy = { + .type = astnode.type, + .children = dmnsn_new_array(sizeof(dmnsn_astnode)), + .ptr = NULL, + .filename = astnode.filename, + .line = astnode.line, + .col = astnode.col + }; + return copy; +} + +static dmnsn_astnode +dmnsn_new_astnode(dmnsn_astnode_type type, YYLTYPE lloc) +{ + dmnsn_astnode astnode = { + .type = type, + .children = dmnsn_new_array(sizeof(dmnsn_astnode)), + .ptr = NULL, + .filename = lloc.first_filename, + .line = lloc.first_line, + .col = lloc.first_column + }; + return astnode; +} + +static dmnsn_astnode +dmnsn_new_astnode1(dmnsn_astnode_type type, YYLTYPE lloc, dmnsn_astnode n1) +{ + dmnsn_astnode astnode = dmnsn_new_astnode(type, lloc); + dmnsn_array_push(astnode.children, &n1); + return astnode; +} + +static dmnsn_astnode +dmnsn_new_astnode2(dmnsn_astnode_type type, YYLTYPE lloc, + dmnsn_astnode n1, dmnsn_astnode n2) +{ + dmnsn_astnode astnode = dmnsn_new_astnode(type, lloc); + dmnsn_array_push(astnode.children, &n1); + dmnsn_array_push(astnode.children, &n2); + return astnode; +} + +static dmnsn_astnode +dmnsn_new_astnode3(dmnsn_astnode_type type, YYLTYPE lloc, + dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3) +{ + dmnsn_astnode astnode = dmnsn_new_astnode(type, lloc); + dmnsn_array_push(astnode.children, &n1); + dmnsn_array_push(astnode.children, &n2); + dmnsn_array_push(astnode.children, &n3); + return astnode; +} + +/* Delete a single, unused astnode */ +static void +dmnsn_delete_astnode(dmnsn_astnode astnode) +{ + dmnsn_delete_astree(astnode.children); + free(astnode.ptr); +} + +static int +yylex(YYSTYPE *lvalp, YYLTYPE *llocp, dmnsn_token_iterator *iterator) +{ + if (iterator->i >= dmnsn_array_size(iterator->tokens)) { + return 0; + } else { + dmnsn_token token; + dmnsn_array_get(iterator->tokens, iterator->i, &token); + ++iterator->i; + + lvalp->value = token.value; + + llocp->first_filename = llocp->last_filename = token.filename; + llocp->first_line = llocp->last_line = token.line; + llocp->first_column = llocp->last_column = token.col; + + return token.type; + } +} + +void +yyerror(YYLTYPE *locp, dmnsn_array *astree, dmnsn_token_iterator *iterator, + const char *str) +{ + dmnsn_diagnostic(locp->first_filename, locp->first_line, locp->first_column, + "%s", str); +} +%} + +%define api.pure +%locations +%error-verbose +%token-table + +%parse-param {dmnsn_array *astree} +%parse-param {dmnsn_token_iterator *iterator} +%lex-param {dmnsn_token_iterator *iterator} + +%token END 0 "end-of-file" + +/* Punctuation */ +%token DMNSN_T_LBRACE "{" +%token DMNSN_T_RBRACE "}" +%token DMNSN_T_LPAREN "(" +%token DMNSN_T_RPAREN ")" +%token DMNSN_T_LBRACKET "[" +%token DMNSN_T_RBRACKET "]" +%token DMNSN_T_PLUS "+" +%token DMNSN_T_MINUS "-" +%token DMNSN_T_STAR "*" +%token DMNSN_T_SLASH "/" +%token DMNSN_T_COMMA "," +%token DMNSN_T_SEMICOLON ";" +%token DMNSN_T_QUESTION "?" +%token DMNSN_T_COLON ":" +%token DMNSN_T_AND "&" +%token DMNSN_T_DOT "." +%token DMNSN_T_PIPE "|" +%token DMNSN_T_LESS "<" +%token DMNSN_T_GREATER ">" +%token DMNSN_T_BANG "!" +%token DMNSN_T_EQUALS "=" +%token DMNSN_T_LESS_EQUAL "<=" +%token DMNSN_T_GREATER_EQUAL ">=" +%token DMNSN_T_NOT_EQUAL "!=" + +/* Numeric values */ +%token <value> DMNSN_T_INTEGER "integer" +%token <value> DMNSN_T_FLOAT "float" + +/* Keywords */ +%token DMNSN_T_AA_LEVEL +%token DMNSN_T_AA_THRESHOLD +%token DMNSN_T_ABS +%token DMNSN_T_ABSORPTION +%token DMNSN_T_ACCURACY +%token DMNSN_T_ACOS +%token DMNSN_T_ACOSH +%token DMNSN_T_ADAPTIVE +%token DMNSN_T_ADC_BAILOUT +%token DMNSN_T_AGATE +%token DMNSN_T_AGATE_TURB +%token DMNSN_T_ALL +%token DMNSN_T_ALL_INTERSECTIONS +%token DMNSN_T_ALPHA +%token DMNSN_T_ALTITUDE +%token DMNSN_T_ALWAYS_SAMPLE +%token DMNSN_T_AMBIENT +%token DMNSN_T_AMBIENT_LIGHT +%token DMNSN_T_ANGLE +%token DMNSN_T_APERTURE +%token DMNSN_T_APPEND +%token DMNSN_T_ARC_ANGLE +%token DMNSN_T_AREA_LIGHT +%token DMNSN_T_ARRAY +%token DMNSN_T_ASC +%token DMNSN_T_ASCII +%token DMNSN_T_ASIN +%token DMNSN_T_ASINH +%token DMNSN_T_ASSUMED_GAMMA +%token DMNSN_T_ATAN +%token DMNSN_T_ATAN2 +%token DMNSN_T_ATANH +%token DMNSN_T_AUTOSTOP +%token DMNSN_T_AVERAGE +%token DMNSN_T_B_SPLINE +%token DMNSN_T_BACKGROUND +%token DMNSN_T_BEZIER_SPLINE +%token DMNSN_T_BICUBIC_PATCH +%token DMNSN_T_BLACK_HOLE +%token DMNSN_T_BLOB +%token DMNSN_T_BLUE +%token DMNSN_T_BLUR_SAMPLES +%token DMNSN_T_BOUNDED_BY +%token DMNSN_T_BOX "box" +%token DMNSN_T_BOXED +%token DMNSN_T_BOZO +%token DMNSN_T_BRICK +%token DMNSN_T_BRICK_SIZE +%token DMNSN_T_BRIGHTNESS +%token DMNSN_T_BRILLIANCE +%token DMNSN_T_BUMP_MAP +%token DMNSN_T_BUMP_SIZE +%token DMNSN_T_BUMPS +%token DMNSN_T_CAMERA "camera" +%token DMNSN_T_CAUSTICS +%token DMNSN_T_CEIL +%token DMNSN_T_CELLS +%token DMNSN_T_CHARSET +%token DMNSN_T_CHECKER +%token DMNSN_T_CHR +%token DMNSN_T_CIRCULAR +%token DMNSN_T_CLIPPED_BY +%token DMNSN_T_CLOCK +%token DMNSN_T_CLOCK_DELTA +%token DMNSN_T_CLOCK_ON +%token DMNSN_T_COLLECT +%token DMNSN_T_COLOR "color" +%token DMNSN_T_COLOR_MAP +%token DMNSN_T_COMPONENT +%token DMNSN_T_COMPOSITE +%token DMNSN_T_CONCAT +%token DMNSN_T_CONE +%token DMNSN_T_CONFIDENCE +%token DMNSN_T_CONIC_SWEEP +%token DMNSN_T_CONSERVE_ENERGY +%token DMNSN_T_CONTAINED_BY +%token DMNSN_T_CONTROL0 +%token DMNSN_T_CONTROL1 +%token DMNSN_T_COORDS +%token DMNSN_T_COS +%token DMNSN_T_COSH +%token DMNSN_T_COUNT +%token DMNSN_T_CRACKLE +%token DMNSN_T_CRAND +%token DMNSN_T_CUBE +%token DMNSN_T_CUBIC +%token DMNSN_T_CUBIC_SPLINE +%token DMNSN_T_CUBIC_WAVE +%token DMNSN_T_CUTAWAY_TEXTURES +%token DMNSN_T_CYLINDER +%token DMNSN_T_CYLINDRICAL +%token DMNSN_T_DEFINED +%token DMNSN_T_DEGREES +%token DMNSN_T_DENSITY +%token DMNSN_T_DENSITY_FILE +%token DMNSN_T_DENSITY_MAP +%token DMNSN_T_DENTS +%token DMNSN_T_DF3 +%token DMNSN_T_DIFFERENCE +%token DMNSN_T_DIFFUSE +%token DMNSN_T_DIMENSION_SIZE +%token DMNSN_T_DIMENSIONS +%token DMNSN_T_DIRECTION +%token DMNSN_T_DISC +%token DMNSN_T_DISPERSION +%token DMNSN_T_DISPERSION_SAMPLES +%token DMNSN_T_DIST_EXP +%token DMNSN_T_DISTANCE +%token DMNSN_T_DIV +%token DMNSN_T_DOUBLE_ILLUMINATE +%token DMNSN_T_ECCENTRICITY +%token DMNSN_T_EMISSION +%token DMNSN_T_ERROR_BOUND +%token DMNSN_T_EVALUATE +%token DMNSN_T_EXP +%token DMNSN_T_EXPAND_THRESHOLDS +%token DMNSN_T_EXPONENT +%token DMNSN_T_EXTERIOR +%token DMNSN_T_EXTINCTION +%token DMNSN_T_FACE_INDICES +%token DMNSN_T_FACETS +%token DMNSN_T_FADE_COLOR +%token DMNSN_T_FADE_DISTANCE +%token DMNSN_T_FADE_POWER +%token DMNSN_T_FALLOFF +%token DMNSN_T_FALLOFF_ANGLE +%token DMNSN_T_FALSE +%token DMNSN_T_FILE_EXISTS +%token DMNSN_T_FILTER +%token DMNSN_T_FINAL_CLOCK +%token DMNSN_T_FINAL_FRAME +%token DMNSN_T_FINISH +%token DMNSN_T_FISHEYE +%token DMNSN_T_FLATNESS +%token DMNSN_T_FLIP +%token DMNSN_T_FLOOR +%token DMNSN_T_FOCAL_POINT +%token DMNSN_T_FOG +%token DMNSN_T_FOG_ALT +%token DMNSN_T_FOG_OFFSET +%token DMNSN_T_FOG_TYPE +%token DMNSN_T_FORM +%token DMNSN_T_FRAME_NUMBER +%token DMNSN_T_FREQUENCY +%token DMNSN_T_FRESNEL +%token DMNSN_T_FUNCTION +%token DMNSN_T_GATHER +%token DMNSN_T_GIF +%token DMNSN_T_GLOBAL_LIGHTS +%token DMNSN_T_GLOBAL_SETTINGS +%token DMNSN_T_GRADIENT +%token DMNSN_T_GRANITE +%token DMNSN_T_GRAY +%token DMNSN_T_GRAY_THRESHOLD +%token DMNSN_T_GREEN +%token DMNSN_T_HEIGHT_FIELD +%token DMNSN_T_HEXAGON +%token DMNSN_T_HF_GRAY_16 +%token DMNSN_T_HIERARCHY +%token DMNSN_T_HYPERCOMPLEX +%token DMNSN_T_HOLLOW +%token DMNSN_T_IFF +%token DMNSN_T_IMAGE_HEIGHT +%token DMNSN_T_IMAGE_MAP +%token DMNSN_T_IMAGE_PATTERN +%token DMNSN_T_IMAGE_WIDTH +%token DMNSN_T_INITIAL_CLOCK +%token DMNSN_T_INITIAL_FRAME +%token DMNSN_T_INSIDE +%token DMNSN_T_INSIDE_VECTOR +%token DMNSN_T_INT +%token DMNSN_T_INTERIOR +%token DMNSN_T_INTERIOR_TEXTURE +%token DMNSN_T_INTERNAL +%token DMNSN_T_INTERPOLATE +%token DMNSN_T_INTERSECTION +%token DMNSN_T_INTERVALS +%token DMNSN_T_INVERSE +%token DMNSN_T_IOR +%token DMNSN_T_IRID +%token DMNSN_T_IRID_WAVELENGTH +%token DMNSN_T_ISOSURFACE +%token DMNSN_T_JITTER +%token DMNSN_T_JPEG +%token DMNSN_T_JULIA +%token DMNSN_T_JULIA_FRACTAL +%token DMNSN_T_LAMBDA +%token DMNSN_T_LATHE +%token DMNSN_T_LEOPARD +%token DMNSN_T_LIGHT_GROUP +%token DMNSN_T_LIGHT_SOURCE +%token DMNSN_T_LINEAR_SPLINE +%token DMNSN_T_LINEAR_SWEEP +%token DMNSN_T_LN +%token DMNSN_T_LOAD_FILE +%token DMNSN_T_LOCATION +%token DMNSN_T_LOG +%token DMNSN_T_LOOK_AT +%token DMNSN_T_LOOKS_LIKE +%token DMNSN_T_LOW_ERROR_FACTOR +%token DMNSN_T_MAGNET +%token DMNSN_T_MAJOR_RADIUS +%token DMNSN_T_MANDEL +%token DMNSN_T_MAP_TYPE +%token DMNSN_T_MARBLE +%token DMNSN_T_MATERIAL +%token DMNSN_T_MATERIAL_MAP +%token DMNSN_T_MATRIX +%token DMNSN_T_MAX +%token DMNSN_T_MAX_EXTENT +%token DMNSN_T_MAX_GRADIENT +%token DMNSN_T_MAX_INTERSECTIONS +%token DMNSN_T_MAX_ITERATION +%token DMNSN_T_MAX_SAMPLE +%token DMNSN_T_MAX_TRACE +%token DMNSN_T_MAX_TRACE_LEVEL +%token DMNSN_T_MEDIA +%token DMNSN_T_MEDIA_ATTENUATION +%token DMNSN_T_MEDIA_INTERACTION +%token DMNSN_T_MERGE +%token DMNSN_T_MESH +%token DMNSN_T_MESH2 +%token DMNSN_T_METALLIC +%token DMNSN_T_METHOD +%token DMNSN_T_METRIC +%token DMNSN_T_MIN +%token DMNSN_T_MIN_EXTENT +%token DMNSN_T_MINIMUM_REUSE +%token DMNSN_T_MOD +%token DMNSN_T_MORTAR +%token DMNSN_T_NATURAL_SPLINE +%token DMNSN_T_NEAREST_COUNT +%token DMNSN_T_NO +%token DMNSN_T_NO_BUMP_SCALE +%token DMNSN_T_NO_IMAGE +%token DMNSN_T_NO_REFLECTION +%token DMNSN_T_NO_SHADOW +%token DMNSN_T_NOISE_GENERATOR +%token DMNSN_T_NORMAL +%token DMNSN_T_NORMAL_INDICES +%token DMNSN_T_NORMAL_MAP +%token DMNSN_T_NORMAL_VECTORS +%token DMNSN_T_NUMBER_OF_WAVES +%token DMNSN_T_OBJECT +%token DMNSN_T_OCTAVES +%token DMNSN_T_OFF +%token DMNSN_T_OFFSET +%token DMNSN_T_OMEGA +%token DMNSN_T_OMNIMAX +%token DMNSN_T_ON +%token DMNSN_T_ONCE +%token DMNSN_T_ONION +%token DMNSN_T_OPEN +%token DMNSN_T_ORIENT +%token DMNSN_T_ORIENTATION +%token DMNSN_T_ORTHOGRAPHIC +%token DMNSN_T_PANORAMIC +%token DMNSN_T_PARALLEL +%token DMNSN_T_PARAMETRIC +%token DMNSN_T_PASS_THROUGH +%token DMNSN_T_PATTERN +%token DMNSN_T_PERSPECTIVE +%token DMNSN_T_PGM +%token DMNSN_T_PHASE +%token DMNSN_T_PHONG +%token DMNSN_T_PHONG_SIZE +%token DMNSN_T_PHOTONS +%token DMNSN_T_PI +%token DMNSN_T_PIGMENT +%token DMNSN_T_PIGMENT_MAP +%token DMNSN_T_PIGMENT_PATTERN +%token DMNSN_T_PLANAR +%token DMNSN_T_PLANE +%token DMNSN_T_PNG +%token DMNSN_T_POINT_AT +%token DMNSN_T_POLY +%token DMNSN_T_POLY_WAVE +%token DMNSN_T_POLYGON +%token DMNSN_T_POT +%token DMNSN_T_POW +%token DMNSN_T_PPM +%token DMNSN_T_PRECISION +%token DMNSN_T_PRECOMPUTE +%token DMNSN_T_PRETRACE_END +%token DMNSN_T_PRETRACE_START +%token DMNSN_T_PRISM +%token DMNSN_T_PROD +%token DMNSN_T_PROJECTED_THROUGH +%token DMNSN_T_PWR +%token DMNSN_T_QUADRATIC_SPLINE +%token DMNSN_T_QUADRIC +%token DMNSN_T_QUARTIC +%token DMNSN_T_QUATERNION +%token DMNSN_T_QUICK_COLOR +%token DMNSN_T_QUILTED +%token DMNSN_T_RADIAL +%token DMNSN_T_RADIANS +%token DMNSN_T_RADIOSITY +%token DMNSN_T_RADIUS +%token DMNSN_T_RAINBOW +%token DMNSN_T_RAMP_WAVE +%token DMNSN_T_RAND +%token DMNSN_T_RATIO +%token DMNSN_T_RECIPROCAL +%token DMNSN_T_RECURSION_LIMIT +%token DMNSN_T_RED +%token DMNSN_T_REFLECTION +%token DMNSN_T_REFLECTION_EXPONENT +%token DMNSN_T_REFRACTION +%token DMNSN_T_REPEAT +%token DMNSN_T_RGB +%token DMNSN_T_RGBF +%token DMNSN_T_RGBFT +%token DMNSN_T_RGBT +%token DMNSN_T_RIGHT +%token DMNSN_T_RIPPLES +%token DMNSN_T_ROTATE +%token DMNSN_T_ROUGHNESS +%token DMNSN_T_SAMPLES +%token DMNSN_T_SAVE_FILE +%token DMNSN_T_SCALE +%token DMNSN_T_SCALLOP_WAVE +%token DMNSN_T_SCATTERING +%token DMNSN_T_SEED +%token DMNSN_T_SELECT +%token DMNSN_T_SHADOWLESS +%token DMNSN_T_SIN +%token DMNSN_T_SINE_WAVE +%token DMNSN_T_SINH +%token DMNSN_T_SIZE +%token DMNSN_T_SKY +%token DMNSN_T_SKY_SPHERE +%token DMNSN_T_SLICE +%token DMNSN_T_SLOPE +%token DMNSN_T_SLOPE_MAP +%token DMNSN_T_SMOOTH +%token DMNSN_T_SMOOTH_TRIANGLE +%token DMNSN_T_SOLID +%token DMNSN_T_SOR +%token DMNSN_T_SPACING +%token DMNSN_T_SPECULAR +%token DMNSN_T_SPHERE "sphere" +%token DMNSN_T_SPHERE_SWEEP +%token DMNSN_T_SPHERICAL +%token DMNSN_T_SPIRAL1 +%token DMNSN_T_SPIRAL2 +%token DMNSN_T_SPLINE +%token DMNSN_T_SPLIT_UNION +%token DMNSN_T_SPOTLIGHT +%token DMNSN_T_SPOTTED +%token DMNSN_T_SQR +%token DMNSN_T_SQRT +%token DMNSN_T_STR +%token DMNSN_T_STRCMP +%token DMNSN_T_STRENGTH +%token DMNSN_T_STRLEN +%token DMNSN_T_STRLWR +%token DMNSN_T_STRUPR +%token DMNSN_T_STURM +%token DMNSN_T_SUBSTR +%token DMNSN_T_SUM +%token DMNSN_T_SUPERELLIPSOID +%token DMNSN_T_SYS +%token DMNSN_T_T +%token DMNSN_T_TAN +%token DMNSN_T_TANH +%token DMNSN_T_TARGET +%token DMNSN_T_TEXT +%token DMNSN_T_TEXTURE +%token DMNSN_T_TEXTURE_LIST +%token DMNSN_T_TEXTURE_MAP +%token DMNSN_T_TGA +%token DMNSN_T_THICKNESS +%token DMNSN_T_THRESHOLD +%token DMNSN_T_TIFF +%token DMNSN_T_TIGHTNESS +%token DMNSN_T_TILE2 +%token DMNSN_T_TILES +%token DMNSN_T_TOLERANCE +%token DMNSN_T_TOROIDAL +%token DMNSN_T_TORUS +%token DMNSN_T_TRACE +%token DMNSN_T_TRANSFORM +%token DMNSN_T_TRANSLATE +%token DMNSN_T_TRANSMIT +%token DMNSN_T_TRIANGLE +%token DMNSN_T_TRIANGLE_WAVE +%token DMNSN_T_TRUE +%token DMNSN_T_TTF +%token DMNSN_T_TURB_DEPTH +%token DMNSN_T_TURBULENCE +%token DMNSN_T_TYPE +%token DMNSN_T_U +%token DMNSN_T_U_STEPS +%token DMNSN_T_ULTRA_WIDE_ANGLE +%token DMNSN_T_UNION +%token DMNSN_T_UP +%token DMNSN_T_USE_ALPHA +%token DMNSN_T_USE_COLOR +%token DMNSN_T_USE_INDEX +%token DMNSN_T_UTF8 +%token DMNSN_T_UV_INDICES +%token DMNSN_T_UV_MAPPING +%token DMNSN_T_UV_VECTORS +%token DMNSN_T_V +%token DMNSN_T_V_STEPS +%token DMNSN_T_VAL +%token DMNSN_T_VARIANCE +%token DMNSN_T_VAXIS_ROTATE +%token DMNSN_T_VCROSS +%token DMNSN_T_VDOT +%token DMNSN_T_VERTEX_VECTORS +%token DMNSN_T_VLENGTH +%token DMNSN_T_VNORMALIZE +%token DMNSN_T_VROTATE +%token DMNSN_T_VSTR +%token DMNSN_T_VTURBULENCE +%token DMNSN_T_WARP +%token DMNSN_T_WATER_LEVEL +%token DMNSN_T_WAVES +%token DMNSN_T_WIDTH +%token DMNSN_T_WOOD +%token DMNSN_T_WRINKLES +%token DMNSN_T_X +%token DMNSN_T_Y +%token DMNSN_T_YES +%token DMNSN_T_Z + +/* Directives (#declare etc.) */ +%token DMNSN_T_BREAK +%token DMNSN_T_CASE +%token DMNSN_T_DEBUG +%token DMNSN_T_DECLARE "#declare" +%token DMNSN_T_DEFAULT +%token DMNSN_T_ELSE +%token DMNSN_T_END +%token DMNSN_T_ERROR +%token DMNSN_T_FCLOSE +%token DMNSN_T_FOPEN +%token DMNSN_T_IF +%token DMNSN_T_IFDEF +%token DMNSN_T_IFNDEF +%token DMNSN_T_INCLUDE "#include" +%token DMNSN_T_LOCAL +%token DMNSN_T_MACRO +%token DMNSN_T_RANGE +%token DMNSN_T_READ +%token DMNSN_T_RENDER +%token DMNSN_T_STATISTICS +%token DMNSN_T_SWITCH +%token DMNSN_T_UNDEF +%token DMNSN_T_VERSION +%token DMNSN_T_WARNING +%token DMNSN_T_WHILE +%token DMNSN_T_WRITE + +/* Identifiers */ +%token <value> DMNSN_T_IDENTIFIER "identifier" + +/* Strings */ +%token <value> DMNSN_T_STRING "string" + +/* Top-level items */ +%type <astnode> SCENE_ITEM + +/* Objects */ +%type <astnode> OBJECT +%type <astnode> FINITE_SOLID_OBJECT +%type <astnode> BOX +%type <astnode> SPHERE + +/* Floats */ +%type <astnode> FLOAT +%type <astnode> FLOAT_TERM +%type <astnode> FLOAT_FACTOR +%type <astnode> FLOAT_LITERAL + +/* Vectors */ +%type <astnode> VECTOR +%type <astnode> VECTOR_LITERAL + +%destructor { dmnsn_delete_astnode($$); } <astnode> + +%% + +SCENE: /* empty */ { } + | SCENE SCENE_ITEM { + dmnsn_array_push(astree, &$2); + } +; + +SCENE_ITEM: OBJECT +; + +OBJECT: FINITE_SOLID_OBJECT +; + +FINITE_SOLID_OBJECT: BOX + | SPHERE +; + +BOX: "box" "{" + VECTOR "," VECTOR + "}" + { + $$ = dmnsn_new_astnode2(DMNSN_AST_BOX, @$, $3, $5); + } +; + +SPHERE: "sphere" "{" + VECTOR "," FLOAT + "}" + { + $$ = dmnsn_new_astnode2(DMNSN_AST_SPHERE, @$, $3, $5); + } +; + +FLOAT: FLOAT_TERM + { + $$ = dmnsn_eval_scalar($1); + dmnsn_delete_astnode($1); + } + | FLOAT "+" FLOAT_TERM + { + dmnsn_astnode sum = dmnsn_new_astnode2(DMNSN_AST_ADD, @$, $1, $3); + $$ = dmnsn_eval_scalar(sum); + dmnsn_delete_astnode(sum); + } + | FLOAT "-" FLOAT_TERM + { + dmnsn_astnode diff = dmnsn_new_astnode2(DMNSN_AST_SUB, @$, $1, $3); + $$ = dmnsn_eval_scalar(diff); + dmnsn_delete_astnode(diff); + } +; + +FLOAT_TERM: FLOAT_FACTOR + | FLOAT_TERM "*" FLOAT_FACTOR + { + $$ = dmnsn_new_astnode2(DMNSN_AST_MUL, @$, $1, $3); + } + | FLOAT_TERM "/" FLOAT_FACTOR + { + $$ = dmnsn_new_astnode2(DMNSN_AST_DIV, @$, $1, $3); + } + +FLOAT_FACTOR: FLOAT_LITERAL + | "+" FLOAT_FACTOR { $$ = $2; } + | "-" FLOAT_FACTOR + { + $$ = dmnsn_new_astnode1(DMNSN_AST_NEGATE, @$, $2); + } + | "(" FLOAT ")" { $$ = $2; } + +FLOAT_LITERAL: "integer" + { + $$ = dmnsn_new_astnode(DMNSN_AST_INTEGER, @$); + $$.ptr = malloc(sizeof(long)); + if (!$$.ptr) + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Failed to allocate room for integer."); + + *(long *)$$.ptr = strtol($1, NULL, 0); + } + | "float" + { + $$ = dmnsn_new_astnode(DMNSN_AST_FLOAT, @$); + $$.ptr = malloc(sizeof(double)); + if (!$$.ptr) + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Failed to allocate room for float."); + + *(double *)$$.ptr = strtod($1, NULL); + } +; + +VECTOR: VECTOR_LITERAL +; + +VECTOR_LITERAL: "<" FLOAT "," FLOAT "," FLOAT ">" + { + $$ = dmnsn_new_astnode3(DMNSN_AST_VECTOR, @$, $2, $4, $6); + } +; + +%% + +dmnsn_array * +dmnsn_parse(const dmnsn_array *tokens) +{ + dmnsn_array *astree = dmnsn_new_array(sizeof(dmnsn_astnode)); + dmnsn_token_iterator iterator = { .tokens = tokens, .i = 0 }; + + if (yyparse(astree, &iterator) != 0) { + dmnsn_delete_astree(astree); + return NULL; + } + + return astree; +} + +void +dmnsn_delete_astree(dmnsn_array *astree) +{ + unsigned int i; + dmnsn_astnode node; + + if (astree) { + for (i = 0; i < dmnsn_array_size(astree); ++i) { + dmnsn_array_get(astree, i, &node); + dmnsn_delete_astree(node.children); + free(node.ptr); + } + dmnsn_delete_array(astree); + } +} + +static dmnsn_astnode +dmnsn_eval_scalar_unary(dmnsn_astnode astnode) +{ + dmnsn_astnode ret = dmnsn_copy_astnode(astnode), rhs; + dmnsn_array_get(astnode.children, 0, &rhs); + rhs = dmnsn_eval_scalar(rhs); + + if (rhs.type == DMNSN_AST_INTEGER) { + long n = *(long *)rhs.ptr; + long *res = malloc(sizeof(long)); + if (!res) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for integer."); + + switch(astnode.type) { + case DMNSN_AST_NEGATE: + *res = -n; + break; + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Attempt to evaluate wrong unary operator."); + } + + ret.type = DMNSN_AST_INTEGER; + ret.ptr = res; + } else if (rhs.type == DMNSN_AST_FLOAT) { + double n = *(double *)rhs.ptr; + double *res = malloc(sizeof(double)); + if (!res) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for float."); + + switch(astnode.type) { + case DMNSN_AST_NEGATE: + *res = -n; + break; + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Attempt to evaluate wrong unary operator."); + } + + ret.type = DMNSN_AST_FLOAT; + ret.ptr = res; + } else { + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Invalid right hand side to unary operator."); + } + + dmnsn_delete_astnode(rhs); + return ret; +} + +static dmnsn_astnode +dmnsn_eval_scalar_binary(dmnsn_astnode astnode) +{ + dmnsn_astnode ret = dmnsn_copy_astnode(astnode), lhs, rhs; + dmnsn_array_get(astnode.children, 0, &lhs); + dmnsn_array_get(astnode.children, 1, &rhs); + lhs = dmnsn_eval_scalar(lhs); + rhs = dmnsn_eval_scalar(rhs); + + if (lhs.type == DMNSN_AST_INTEGER && rhs.type == DMNSN_AST_INTEGER + && astnode.type != DMNSN_AST_DIV) { + long l, r; + l = *(long *)lhs.ptr; + r = *(long *)rhs.ptr; + + long *res = malloc(sizeof(long)); + if (!res) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for integer."); + + switch (astnode.type) { + case DMNSN_AST_ADD: + *res = l + r; + break; + case DMNSN_AST_SUB: + *res = l - r; + break; + case DMNSN_AST_MUL: + *res = l*r; + break; + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Attempt to evaluate wrong binary operator."); + } + + ret.type = DMNSN_AST_INTEGER; + ret.ptr = res; + } else { + double l = 0.0, r = 0.0; + + if (lhs.type == DMNSN_AST_INTEGER) + l = *(long *)lhs.ptr; + else if (lhs.type == DMNSN_AST_FLOAT) + l = *(double *)lhs.ptr; + else + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Invalid left hand side to binary operator."); + + if (rhs.type == DMNSN_AST_INTEGER) + r = *(long *)rhs.ptr; + else if (rhs.type == DMNSN_AST_FLOAT) + r = *(double *)rhs.ptr; + else + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Invalid right hand side to binary operator."); + + double *res = malloc(sizeof(double)); + if (!res) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for float."); + + switch (astnode.type) { + case DMNSN_AST_ADD: + *res = l + r; + break; + case DMNSN_AST_SUB: + *res = l - r; + break; + case DMNSN_AST_MUL: + *res = l*r; + break; + case DMNSN_AST_DIV: + *res = l/r; + break; + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Attempt to evaluate wrong binary operator."); + } + + ret.type = DMNSN_AST_FLOAT; + ret.ptr = res; + } + + dmnsn_delete_astnode(lhs); + dmnsn_delete_astnode(rhs); + return ret; +} + +dmnsn_astnode +dmnsn_eval_scalar(dmnsn_astnode astnode) +{ + dmnsn_astnode ret; + + switch (astnode.type) { + case DMNSN_AST_INTEGER: + ret = dmnsn_copy_astnode(astnode); + ret.ptr = malloc(sizeof(long)); + if (!ret.ptr) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for integer."); + + memcpy(ret.ptr, astnode.ptr, sizeof(long)); + return ret; + + case DMNSN_AST_FLOAT: + ret = dmnsn_copy_astnode(astnode); + ret.ptr = malloc(sizeof(double)); + if (!ret.ptr) + dmnsn_error(DMNSN_SEVERITY_HIGH, "Failed to allocate room for float."); + + memcpy(ret.ptr, astnode.ptr, sizeof(double)); + return ret; + + case DMNSN_AST_NEGATE: + return dmnsn_eval_scalar_unary(astnode); + + case DMNSN_AST_ADD: + case DMNSN_AST_SUB: + case DMNSN_AST_MUL: + case DMNSN_AST_DIV: + return dmnsn_eval_scalar_binary(astnode); + + default: + dmnsn_error(DMNSN_SEVERITY_HIGH, + "Given non-arithmetic-expression to evaluate."); + return astnode; /* Silence warning */ + } +} + +/* TODO */ +dmnsn_astnode dmnsn_eval_vector(dmnsn_astnode astnode); + +static void +dmnsn_print_astnode(FILE *file, dmnsn_astnode astnode) +{ + long ivalue; + double dvalue; + + switch (astnode.type) { + case DMNSN_AST_INTEGER: + ivalue = *(long *)astnode.ptr; + fprintf(file, "(%s %ld)", dmnsn_astnode_string(astnode.type), ivalue); + break; + + case DMNSN_AST_FLOAT: + dvalue = *(double *)astnode.ptr; + fprintf(file, "(%s %g)", dmnsn_astnode_string(astnode.type), dvalue); + break; + + default: + fprintf(file, "%s", dmnsn_astnode_string(astnode.type)); + } +} + +static void +dmnsn_print_astree(FILE *file, dmnsn_astnode astnode) +{ + unsigned int i; + dmnsn_astnode child; + + if (astnode.children && dmnsn_array_size(astnode.children) > 0) { + fprintf(file, "("); + dmnsn_print_astnode(file, astnode); + for (i = 0; i < dmnsn_array_size(astnode.children); ++i) { + dmnsn_array_get(astnode.children, i, &child); + fprintf(file, " "); + dmnsn_print_astree(file, child); + } + fprintf(file, ")"); + } else { + dmnsn_print_astnode(file, astnode); + } +} + +void +dmnsn_print_astree_sexpr(FILE *file, const dmnsn_array *astree) +{ + dmnsn_astnode astnode; + unsigned int i; + + if (dmnsn_array_size(astree) == 0) { + fprintf(file, "()"); + } else { + fprintf(file, "("); + dmnsn_array_get(astree, 0, &astnode); + dmnsn_print_astree(file, astnode); + + for (i = 1; i < dmnsn_array_size(astree); ++i) { + fprintf(file, " "); + dmnsn_array_get(astree, i, &astnode); + dmnsn_print_astree(file, astnode); + } + + fprintf(file, ")"); + } + + fprintf(file, "\n"); +} + +const char * +dmnsn_token_string(dmnsn_token_type token_type) +{ +#define TOKEN_SIZE 255 + static char token[TOKEN_SIZE + 1]; + + unsigned int i = YYTRANSLATE(token_type); + if (i > YYNTOKENS) { + fprintf(stderr, "Warning: unrecognised token %d.\n", (int)token_type); + return "unrecognized-token"; + } + + /* Trim the quotation marks */ + + if (strlen(yytname[i]) - 1 >= TOKEN_SIZE) { + fprintf(stderr, "Warning: name of token %d too long.\n", (int)token_type); + return "unrepresentable-token"; + } + + strcpy(token, yytname[i] + 1); + token[strlen(token) - 1] = '\0'; + + return token; +#undef TOKEN_SIZE +} + +const char * +dmnsn_astnode_string(dmnsn_astnode_type astnode_type) +{ + switch (astnode_type) { + /* Macro to shorten this switch */ +#define dmnsn_astnode_map(type, str) \ + case type: \ + return str; + + dmnsn_astnode_map(DMNSN_AST_FLOAT, "float"); + dmnsn_astnode_map(DMNSN_AST_INTEGER, "integer"); + dmnsn_astnode_map(DMNSN_AST_NEGATE, "-"); + dmnsn_astnode_map(DMNSN_AST_ADD, "+"); + dmnsn_astnode_map(DMNSN_AST_SUB, "-"); + dmnsn_astnode_map(DMNSN_AST_MUL, "*"); + dmnsn_astnode_map(DMNSN_AST_DIV, "/"); + dmnsn_astnode_map(DMNSN_AST_BOX, "box"); + dmnsn_astnode_map(DMNSN_AST_VECTOR, "vector"); + dmnsn_astnode_map(DMNSN_AST_SPHERE, "sphere"); + + default: + fprintf(stderr, "Warning: unrecognised astnode type %d.\n", + (int)astnode_type); + return "unrecognized-astnode"; + } +} |