summaryrefslogtreecommitdiffstats
path: root/dimension
diff options
context:
space:
mode:
Diffstat (limited to 'dimension')
-rw-r--r--dimension/Makefile.am16
-rw-r--r--dimension/grammar.declarations38
-rw-r--r--dimension/grammar.epilogue148
-rw-r--r--dimension/grammar.nonterminals83
-rw-r--r--dimension/grammar.prologue153
-rw-r--r--dimension/grammar.rules562
-rw-r--r--dimension/grammar.terminals519
-rw-r--r--dimension/grammar.y1419
8 files changed, 1519 insertions, 1419 deletions
diff --git a/dimension/Makefile.am b/dimension/Makefile.am
index 1d18374..1ee125c 100644
--- a/dimension/Makefile.am
+++ b/dimension/Makefile.am
@@ -23,6 +23,22 @@ bin_PROGRAMS = dimension
AM_YFLAGS = -d
BUILT_SOURCES = grammar.h
+EXTRA_DIST = grammar.prologue \
+ grammar.declarations \
+ grammar.terminals \
+ grammar.nonterminals \
+ grammar.rules \
+ grammar.epilogue
+
+grammar.y: grammar.prologue grammar.declarations grammar.terminals grammar.nonterminals grammar.rules grammar.epilogue
+ echo "%{" >$@
+ cat grammar.prologue >>$@
+ echo "%}" >>$@
+ cat grammar.{declarations,terminals,nonterminals} >>$@
+ echo "%%" >>$@
+ cat grammar.rules >>$@
+ echo "%%" >>$@
+ cat grammar.epilogue >>$@
dimension_SOURCES = grammar.y \
lexer.l \
diff --git a/dimension/grammar.declarations b/dimension/grammar.declarations
new file mode 100644
index 0000000..c951758
--- /dev/null
+++ b/dimension/grammar.declarations
@@ -0,0 +1,38 @@
+/*************************************************************************
+ * Copyright (C) 2010 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/>. *
+ *************************************************************************/
+
+%define api.pure
+%locations
+%error-verbose
+%token-table
+
+%name-prefix "dmnsn_yy"
+
+%expect 10
+%glr-parser
+
+%parse-param {const char *filename}
+%parse-param {void *yyscanner}
+%parse-param {dmnsn_astree *astree}
+%parse-param {dmnsn_symbol_table *symtable}
+%lex-param {const char *filename}
+%lex-param {void *yyscanner}
+
+%destructor { free($$); } <value>
+%destructor { dmnsn_delete_astnode($$); } <astnode>
diff --git a/dimension/grammar.epilogue b/dimension/grammar.epilogue
new file mode 100644
index 0000000..345fa0f
--- /dev/null
+++ b/dimension/grammar.epilogue
@@ -0,0 +1,148 @@
+/*************************************************************************
+ * Copyright (C) 2010 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/>. *
+ *************************************************************************/
+
+dmnsn_astree *
+dmnsn_parse(FILE *file, dmnsn_symbol_table *symtable)
+{
+ const char *filename;
+ dmnsn_astnode *fnode = dmnsn_find_symbol(symtable, "__file__");
+ if (fnode && fnode->type == DMNSN_AST_STRING) {
+ filename = fnode->ptr;
+ } else {
+ filename = "<>";
+ dmnsn_declare_symbol(symtable, "__file__", dmnsn_new_ast_string(filename));
+ }
+
+ void *scanner;
+ dmnsn_astree *astree = dmnsn_new_array(sizeof(dmnsn_astnode));
+
+ dmnsn_yylex_init(&scanner);
+ dmnsn_yyset_in(file, scanner);
+
+ if (yyparse(filename, scanner, astree, symtable) != 0) {
+ dmnsn_delete_astree(astree);
+ astree = NULL;
+ }
+
+ dmnsn_yylex_destroy(scanner);
+ return astree;
+}
+
+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_NONE, "none");
+
+ dmnsn_astnode_map(DMNSN_AST_ROTATION, "rotate");
+ dmnsn_astnode_map(DMNSN_AST_SCALE, "scale");
+ dmnsn_astnode_map(DMNSN_AST_TRANSLATION, "translate");
+
+ dmnsn_astnode_map(DMNSN_AST_CAMERA, "camera");
+ dmnsn_astnode_map(DMNSN_AST_PERSPECTIVE, "perspective");
+ dmnsn_astnode_map(DMNSN_AST_LOCATION, "location");
+ dmnsn_astnode_map(DMNSN_AST_RIGHT, "right");
+ dmnsn_astnode_map(DMNSN_AST_UP, "up");
+ dmnsn_astnode_map(DMNSN_AST_SKY, "sky");
+ dmnsn_astnode_map(DMNSN_AST_ANGLE, "angle");
+ dmnsn_astnode_map(DMNSN_AST_LOOK_AT, "look_at");
+ dmnsn_astnode_map(DMNSN_AST_DIRECTION, "direction");
+
+ dmnsn_astnode_map(DMNSN_AST_BACKGROUND, "background");
+
+ dmnsn_astnode_map(DMNSN_AST_BOX, "box");
+ dmnsn_astnode_map(DMNSN_AST_SPHERE, "sphere");
+ dmnsn_astnode_map(DMNSN_AST_LIGHT_SOURCE, "light_source");
+
+ dmnsn_astnode_map(DMNSN_AST_OBJECT_MODIFIERS, "object-modifiers");
+
+ dmnsn_astnode_map(DMNSN_AST_TEXTURE, "texture");
+
+ dmnsn_astnode_map(DMNSN_AST_PIGMENT, "pigment");
+
+ dmnsn_astnode_map(DMNSN_AST_FINISH, "finish");
+ dmnsn_astnode_map(DMNSN_AST_AMBIENT, "ambient");
+ dmnsn_astnode_map(DMNSN_AST_DIFFUSE, "diffuse");
+ dmnsn_astnode_map(DMNSN_AST_PHONG, "phong");
+ dmnsn_astnode_map(DMNSN_AST_PHONG_SIZE, "phong_size");
+
+ dmnsn_astnode_map(DMNSN_AST_REFLECTION, "reflection");
+ dmnsn_astnode_map(DMNSN_AST_REFLECTION_ITEMS, "reflection-items");
+ dmnsn_astnode_map(DMNSN_AST_FALLOFF, "falloff");
+
+ dmnsn_astnode_map(DMNSN_AST_FLOAT, "float");
+ dmnsn_astnode_map(DMNSN_AST_INTEGER, "integer");
+
+ dmnsn_astnode_map(DMNSN_AST_VECTOR, "vector");
+
+ 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_NEGATE, "-");
+ dmnsn_astnode_map(DMNSN_AST_DOT_X, ".x");
+ dmnsn_astnode_map(DMNSN_AST_DOT_Y, ".y");
+ dmnsn_astnode_map(DMNSN_AST_DOT_Z, ".z");
+ dmnsn_astnode_map(DMNSN_AST_DOT_T, ".t");
+ dmnsn_astnode_map(DMNSN_AST_DOT_TRANSMIT, ".transmit");
+
+ dmnsn_astnode_map(DMNSN_AST_COLOR, "color");
+
+ dmnsn_astnode_map(DMNSN_AST_IDENTIFIER, "identifier");
+
+ dmnsn_astnode_map(DMNSN_AST_STRING, "string");
+
+ default:
+ fprintf(stderr, "Warning: unrecognised astnode type %d.\n",
+ (int)astnode_type);
+ return "unrecognized-astnode";
+ }
+}
diff --git a/dimension/grammar.nonterminals b/dimension/grammar.nonterminals
new file mode 100644
index 0000000..ae752c3
--- /dev/null
+++ b/dimension/grammar.nonterminals
@@ -0,0 +1,83 @@
+/*************************************************************************
+ * Copyright (C) 2010 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/>. *
+ *************************************************************************/
+
+/* Top-level items */
+%type <astnode> SCENE_ITEM
+
+/* Language directives */
+%type <astnode> RVALUE
+%type <astnode> IDENTIFIER
+
+/* Transformations */
+%type <astnode> TRANSFORMATION
+
+/* The camera */
+%type <astnode> CAMERA
+%type <astnode> CAMERA_ITEMS
+%type <astnode> CAMERA_ITEM
+%type <astnode> CAMERA_TYPE
+%type <astnode> CAMERA_VECTOR
+%type <astnode> CAMERA_MODIFIER
+
+/* Atmospheric effects */
+%type <astnode> ATMOSPHERIC_EFFECT
+%type <astnode> BACKGROUND
+
+/* Objects */
+%type <astnode> OBJECT
+%type <astnode> FINITE_SOLID_OBJECT
+%type <astnode> BOX
+%type <astnode> LIGHT_SOURCE
+%type <astnode> SPHERE
+
+/* Object modifiers */
+%type <astnode> OBJECT_MODIFIERS
+%type <astnode> OBJECT_MODIFIER
+
+/* Textures */
+%type <astnode> TEXTURE
+%type <astnode> TEXTURE_ITEMS
+
+/* Pigments */
+%type <astnode> PIGMENT
+%type <astnode> PIGMENT_TYPE
+
+/* Finishes */
+%type <astnode> FINISH
+%type <astnode> FINISH_ITEMS
+%type <astnode> REFLECTION
+%type <astnode> REFLECTION_ITEMS
+
+/* Floats */
+%type <astnode> FLOAT
+%type <astnode> FLOAT_LITERAL
+
+/* Vectors */
+%type <astnode> VECTOR
+%type <astnode> VECTOR_LITERAL
+
+/* Generalized arithmetic expressions */
+%type <astnode> ARITH_EXPR
+
+/* Colors */
+%type <astnode> COLOR
+%type <astnode> COLOR_BODY
+%type <astnode> COLOR_VECTOR
+%type <astnode> COLOR_KEYWORD_GROUP
+%type <astnode> COLOR_KEYWORD_GROUP_INIT
diff --git a/dimension/grammar.prologue b/dimension/grammar.prologue
new file mode 100644
index 0000000..7b0db1f
--- /dev/null
+++ b/dimension/grammar.prologue
@@ -0,0 +1,153 @@
+/*************************************************************************
+ * Copyright (C) 2010 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>
+
+#define YYSTYPE dmnsn_parse_item
+#define YYLTYPE dmnsn_parse_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_new_astnode(dmnsn_astnode_type type, YYLTYPE lloc)
+{
+ dmnsn_astnode astnode = {
+ .type = type,
+ .children = dmnsn_new_array(sizeof(dmnsn_astnode)),
+ .ptr = NULL,
+ .refcount = malloc(sizeof(unsigned int)),
+ .filename = lloc.first_filename,
+ .line = lloc.first_line,
+ .col = lloc.first_column
+ };
+
+ if (!astnode.refcount) {
+ dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate reference count.");
+ }
+ *astnode.refcount = 1;
+
+ return astnode;
+}
+
+/* Semi-shallow copy */
+static void
+dmnsn_copy_children(dmnsn_astnode dest, dmnsn_astnode src)
+{
+ unsigned int i;
+ for (i = 0; i < dmnsn_array_size(src.children); ++i) {
+ dmnsn_astnode node;
+ dmnsn_array_get(src.children, i, &node);
+ ++*node.refcount;
+
+ if (i < dmnsn_array_size(dest.children)) {
+ dmnsn_astnode clobbered;
+ dmnsn_array_get(dest.children, i, &clobbered);
+ dmnsn_delete_astnode(clobbered);
+ }
+
+ dmnsn_array_set(dest.children, i, &node);
+ }
+}
+
+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;
+}
+
+static dmnsn_astnode
+dmnsn_new_astnode4(dmnsn_astnode_type type, YYLTYPE lloc,
+ dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3,
+ dmnsn_astnode n4)
+{
+ 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);
+ dmnsn_array_push(astnode.children, &n4);
+ return astnode;
+}
+
+static dmnsn_astnode
+dmnsn_new_astnode5(dmnsn_astnode_type type, YYLTYPE lloc,
+ dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3,
+ dmnsn_astnode n4, dmnsn_astnode n5)
+{
+ 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);
+ dmnsn_array_push(astnode.children, &n4);
+ dmnsn_array_push(astnode.children, &n5);
+ return astnode;
+}
+
+void
+yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
+ dmnsn_astree *astree, dmnsn_symbol_table *symtable, const char *str)
+{
+ dmnsn_diagnostic(locp->first_filename, locp->first_line, locp->first_column,
+ "%s", str);
+}
diff --git a/dimension/grammar.rules b/dimension/grammar.rules
new file mode 100644
index 0000000..2558485
--- /dev/null
+++ b/dimension/grammar.rules
@@ -0,0 +1,562 @@
+/*************************************************************************
+ * Copyright (C) 2010 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/>. *
+ *************************************************************************/
+
+/* Start symbol */
+
+SCENE: /* empty */
+ | SCENE LANGUAGE_DIRECTIVE
+ | SCENE SCENE_ITEM {
+ dmnsn_array_push(astree, &$2);
+ }
+;
+
+/* Language directives */
+
+LANGUAGE_DIRECTIVE: DECLARATION
+;
+
+DECLARATION: "#declare" "identifier" "=" RVALUE {
+ dmnsn_declare_symbol(symtable, $2, $4);
+ free($2);
+ dmnsn_delete_astnode($4);
+ }
+ | "#local" "identifier" "=" RVALUE {
+ dmnsn_local_symbol(symtable, $2, $4);
+ free($2);
+ dmnsn_delete_astnode($4);
+ }
+ | "#undef" "identifier" {
+ dmnsn_undef_symbol(symtable, $2);
+ free($2);
+ }
+;
+
+RVALUE: ARITH_EXPR ";" %dprec 2 {
+ $$ = dmnsn_eval($1, symtable);
+ dmnsn_delete_astnode($1);
+
+ if ($$.type == DMNSN_AST_NONE) {
+ dmnsn_delete_astnode($$);
+ YYERROR;
+ }
+ }
+ | COLOR ";" %dprec 1
+;
+
+IDENTIFIER: "identifier" {
+ $$ = dmnsn_new_astnode(DMNSN_AST_IDENTIFIER, @$);
+ $$.ptr = $1;
+ }
+;
+
+/* Top-level scene item */
+SCENE_ITEM: ATMOSPHERIC_EFFECT
+ | CAMERA
+ | OBJECT
+;
+
+/* Transformations */
+
+TRANSFORMATION: "rotate" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_ROTATION, @$, $2);
+ }
+ | "scale" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_SCALE, @$, $2);
+ }
+ | "translate" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSLATION, @$, $2);
+ }
+;
+
+/* Cameras */
+
+CAMERA: "camera" "{"
+ CAMERA_ITEMS
+ "}"
+ {
+ $$ = $3;
+ }
+;
+
+CAMERA_ITEMS: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_CAMERA, @$);
+ }
+ | CAMERA_ITEMS CAMERA_ITEM {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+;
+
+CAMERA_ITEM: CAMERA_TYPE
+ | CAMERA_VECTOR
+ | CAMERA_MODIFIER
+;
+
+CAMERA_TYPE: "perspective" {
+ $$ = dmnsn_new_astnode(DMNSN_AST_PERSPECTIVE, @$);
+ }
+;
+
+CAMERA_VECTOR: "location" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_LOCATION, @$, $2);
+ }
+ | "right" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_RIGHT, @$, $2);
+ }
+ | "up" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_UP, @$, $2);
+ }
+ | "sky" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_SKY, @$, $2);
+ }
+ | "direction" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DIRECTION, @$, $2);
+ }
+;
+
+CAMERA_MODIFIER: "angle" FLOAT {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_ANGLE, @$, $2);
+ }
+ | "look_at" VECTOR {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_LOOK_AT, @$, $2);
+ }
+ | TRANSFORMATION
+;
+
+/* Atmospheric effects */
+
+ATMOSPHERIC_EFFECT: BACKGROUND
+;
+
+BACKGROUND: "background" "{" COLOR "}" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_BACKGROUND, @$, $3);
+ }
+;
+
+/* Objects */
+
+OBJECT: FINITE_SOLID_OBJECT
+ | LIGHT_SOURCE
+;
+
+FINITE_SOLID_OBJECT: BOX
+ | SPHERE
+;
+
+BOX: "box" "{"
+ VECTOR "," VECTOR
+ OBJECT_MODIFIERS
+ "}"
+ {
+ $$ = dmnsn_new_astnode3(DMNSN_AST_BOX, @$, $3, $5, $6);
+ }
+;
+
+LIGHT_SOURCE: "light_source" "{"
+ VECTOR "," COLOR
+ "}"
+ {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_LIGHT_SOURCE, @$, $3, $5);
+ }
+;
+
+SPHERE: "sphere" "{"
+ VECTOR "," FLOAT
+ OBJECT_MODIFIERS
+ "}"
+ {
+ $$ = dmnsn_new_astnode3(DMNSN_AST_SPHERE, @$, $3, $5, $6);
+ }
+;
+
+/* Object modifiers */
+
+OBJECT_MODIFIERS: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_OBJECT_MODIFIERS, @$);
+ }
+ | OBJECT_MODIFIERS OBJECT_MODIFIER {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+;
+
+OBJECT_MODIFIER: TRANSFORMATION
+ | TEXTURE
+ | PIGMENT {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_TEXTURE, @$, $1);
+ }
+;
+
+/* Textures */
+
+TEXTURE: "texture" "{"
+ TEXTURE_ITEMS
+ "}"
+ { $$ = $3; }
+;
+
+TEXTURE_ITEMS: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_TEXTURE, @$);
+ }
+ | TEXTURE_ITEMS PIGMENT {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+ | TEXTURE_ITEMS FINISH {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+;
+
+/* Pigments */
+
+PIGMENT: "pigment" "{"
+ PIGMENT_TYPE
+ "}"
+ {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_PIGMENT, @$, $3);
+ }
+;
+
+PIGMENT_TYPE: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_NONE, @$);
+ }
+ | COLOR
+;
+
+/* Finishes */
+FINISH: "finish" "{"
+ FINISH_ITEMS
+ "}"
+ { $$ = $3; }
+;
+
+FINISH_ITEMS: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_FINISH, @$);
+ }
+ | FINISH_ITEMS "ambient" COLOR {
+ dmnsn_astnode ambient = dmnsn_new_astnode1(DMNSN_AST_AMBIENT,
+ @2, $3);
+ $$ = $1;
+ dmnsn_array_push($$.children, &ambient);
+ }
+ | FINISH_ITEMS "diffuse" FLOAT {
+ dmnsn_astnode diffuse = dmnsn_new_astnode1(DMNSN_AST_DIFFUSE,
+ @2, $3);
+ $$ = $1;
+ dmnsn_array_push($$.children, &diffuse);
+ }
+ | FINISH_ITEMS "phong" FLOAT {
+ dmnsn_astnode phong = dmnsn_new_astnode1(DMNSN_AST_PHONG, @2, $3);
+ $$ = $1;
+ dmnsn_array_push($$.children, &phong);
+ }
+ | FINISH_ITEMS "phong_size" FLOAT {
+ dmnsn_astnode phong_size
+ = dmnsn_new_astnode1(DMNSN_AST_PHONG_SIZE, @2, $3);
+ $$ = $1;
+ dmnsn_array_push($$.children, &phong_size);
+ }
+ | FINISH_ITEMS REFLECTION {
+ $$ = $1;
+ dmnsn_array_push($$.children, &$2);
+ }
+;
+
+REFLECTION: "reflection" "{"
+ COLOR
+ REFLECTION_ITEMS
+ "}"
+ {
+ ++*$3.refcount;
+ $$ = dmnsn_new_astnode3(DMNSN_AST_REFLECTION, @$, $3, $3, $4);
+ }
+ | "reflection" "{"
+ COLOR "," COLOR
+ REFLECTION_ITEMS
+ "}"
+ {
+ $$ = dmnsn_new_astnode3(DMNSN_AST_REFLECTION, @$, $3, $5, $6);
+ }
+;
+
+REFLECTION_ITEMS: /* empty */ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_REFLECTION_ITEMS, @$);
+ }
+ | REFLECTION_ITEMS "falloff" FLOAT {
+ dmnsn_astnode falloff
+ = dmnsn_new_astnode1(DMNSN_AST_FALLOFF, @2, $3);
+ $$ = $1;
+ dmnsn_array_push($$.children, &falloff);
+ }
+;
+
+/* Floats */
+
+FLOAT: ARITH_EXPR {
+ $$ = dmnsn_eval_scalar($1, symtable);
+ dmnsn_delete_astnode($1);
+
+ if ($$.type == DMNSN_AST_NONE) {
+ dmnsn_delete_astnode($$);
+ YYERROR;
+ }
+ }
+;
+
+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);
+ free($1);
+ }
+ | "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);
+ free($1);
+ }
+;
+
+/* Vectors */
+
+VECTOR: ARITH_EXPR {
+ $$ = dmnsn_eval_vector($1, symtable);
+ dmnsn_delete_astnode($1);
+
+ if ($$.type == DMNSN_AST_NONE) {
+ dmnsn_delete_astnode($$);
+ YYERROR;
+ }
+ }
+;
+
+VECTOR_LITERAL: "<" ARITH_EXPR "," ARITH_EXPR ">" {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_VECTOR, @$, $2, $4);
+ }
+ | "<" ARITH_EXPR "," ARITH_EXPR "," ARITH_EXPR ">" {
+ $$ = dmnsn_new_astnode3(DMNSN_AST_VECTOR, @$, $2, $4, $6);
+ }
+ | "<" ARITH_EXPR "," ARITH_EXPR "," ARITH_EXPR ","
+ ARITH_EXPR ">" {
+ $$ = dmnsn_new_astnode4(DMNSN_AST_VECTOR, @$, $2, $4, $6, $8);
+ }
+ | "<" ARITH_EXPR "," ARITH_EXPR "," ARITH_EXPR ","
+ ARITH_EXPR "," ARITH_EXPR ">" {
+ $$ = dmnsn_new_astnode5(DMNSN_AST_VECTOR, @$,
+ $2, $4, $6, $8, $10);
+ }
+;
+
+/* Generalized arithmetic expressions */
+
+ARITH_EXPR: FLOAT_LITERAL
+ | VECTOR_LITERAL
+ | ARITH_EXPR "+" ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_ADD, @$, $1, $3);
+ }
+ | ARITH_EXPR "-" ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_SUB, @$, $1, $3);
+ }
+ | ARITH_EXPR "*" ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_MUL, @$, $1, $3);
+ }
+ | ARITH_EXPR "/" ARITH_EXPR {
+ $$ = dmnsn_new_astnode2(DMNSN_AST_DIV, @$, $1, $3);
+ }
+ | "+" ARITH_EXPR %prec DMNSN_T_NEGATE { $$ = $2; }
+ | "-" ARITH_EXPR %prec DMNSN_T_NEGATE {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_NEGATE, @$, $2);
+ }
+ | ARITH_EXPR "." "x" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_X, @$, $1);
+ }
+ | ARITH_EXPR "." "u" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_X, @$, $1);
+ }
+ | ARITH_EXPR "." "red" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_X, @$, $1);
+ }
+ | ARITH_EXPR "." "y" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Y, @$, $1);
+ }
+ | ARITH_EXPR "." "v" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Y, @$, $1);
+ }
+ | ARITH_EXPR "." "green" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Y, @$, $1);
+ }
+ | ARITH_EXPR "." "z" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Z, @$, $1);
+ }
+ | ARITH_EXPR "." "blue" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Z, @$, $1);
+ }
+ | ARITH_EXPR "." "t" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_T, @$, $1);
+ }
+ | ARITH_EXPR "." "filter" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_T, @$, $1);
+ }
+ | ARITH_EXPR "." "transmit" {
+ $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_TRANSMIT, @$, $1);
+ }
+ | "(" ARITH_EXPR ")" { $$ = $2; }
+ | IDENTIFIER
+;
+
+/* Colors */
+
+COLOR: COLOR_BODY {
+ $$ = $1;
+ $$.type = DMNSN_AST_COLOR;
+ }
+ | "color" COLOR_BODY {
+ $$ = $2;
+ $$.type = DMNSN_AST_COLOR;
+ }
+;
+
+COLOR_BODY: COLOR_VECTOR %dprec 1
+ | COLOR_KEYWORD_GROUP %dprec 2
+;
+
+COLOR_VECTOR: "rgb" VECTOR {
+ dmnsn_astnode f, t;
+ dmnsn_array_get($2.children, 3, &f);
+ dmnsn_array_get($2.children, 4, &t);
+ dmnsn_delete_astnode(f);
+ dmnsn_delete_astnode(t);
+
+ dmnsn_array_resize($2.children, 3);
+
+ $$ = dmnsn_eval_vector($2, symtable);
+ dmnsn_delete_astnode($2);
+ }
+ | "rgbf" VECTOR {
+ dmnsn_astnode t;
+ dmnsn_array_get($2.children, 4, &t);
+ dmnsn_delete_astnode(t);
+
+ dmnsn_array_resize($2.children, 4);
+
+ $$ = dmnsn_eval_vector($2, symtable);
+ dmnsn_delete_astnode($2);
+ }
+ | "rgbt" VECTOR {
+ /* Chop off the fifth component */
+ dmnsn_astnode t;
+ dmnsn_array_get($2.children, 4, &t);
+ dmnsn_delete_astnode(t);
+
+ dmnsn_array_resize($2.children, 4);
+
+ $$ = dmnsn_eval_vector($2, symtable);
+ dmnsn_delete_astnode($2);
+
+ /* Swap the transmit and filter components */
+ dmnsn_astnode temp;
+ dmnsn_array_get($$.children, 4, &temp);
+ dmnsn_array_set($$.children, 4, dmnsn_array_at($$.children, 3));
+ dmnsn_array_set($$.children, 3, &temp);
+ }
+ | "rgbft" VECTOR { $$ = $2; }
+ | VECTOR
+;
+
+COLOR_KEYWORD_GROUP: COLOR_KEYWORD_GROUP_INIT COLOR_KEYWORD_ITEM
+ | COLOR_KEYWORD_GROUP COLOR_KEYWORD_ITEM
+;
+
+COLOR_KEYWORD_GROUP_INIT: /* empty */ {
+ dmnsn_astnode zero =
+ dmnsn_new_astnode(DMNSN_AST_INTEGER, @$);
+ zero.ptr = malloc(sizeof(long));
+ if (!zero.ptr)
+ dmnsn_error(DMNSN_SEVERITY_HIGH,
+ "Failed to allocate room for integer.");
+ *(long *)zero.ptr = 0;
+
+ $$ = dmnsn_eval_vector(zero, symtable);
+ dmnsn_delete_astnode(zero);
+ }
+;
+
+COLOR_KEYWORD_ITEM: "identifier" {
+ dmnsn_astnode *symbol = dmnsn_find_symbol(symtable, $1);
+ if (!symbol) {
+ dmnsn_diagnostic(@1.first_filename, @1.first_line,
+ @1.first_column,
+ "unbound identifier '%s'", $1);
+ free($1);
+ YYERROR;
+ } else if (symbol->type != DMNSN_AST_COLOR) {
+ dmnsn_astnode eval = dmnsn_eval_vector(*symbol, symtable);
+ if (eval.type == DMNSN_AST_NONE) {
+ free($1);
+ YYERROR;
+ }
+
+ dmnsn_copy_children($<astnode>0, eval);
+ dmnsn_delete_astnode(eval);
+ } else {
+ dmnsn_copy_children($<astnode>0, *symbol);
+ }
+
+ free($1);
+ }
+ | "red" FLOAT {
+ dmnsn_astnode old;
+ dmnsn_array_get($<astnode>0.children, 0, &old);
+ dmnsn_array_set($<astnode>0.children, 0, &$2);
+ dmnsn_delete_astnode(old);
+ }
+ | "green" FLOAT {
+ dmnsn_astnode old;
+ dmnsn_array_get($<astnode>0.children, 1, &old);
+ dmnsn_array_set($<astnode>0.children, 1, &$2);
+ dmnsn_delete_astnode(old);
+ }
+ | "blue" FLOAT {
+ dmnsn_astnode old;
+ dmnsn_array_get($<astnode>0.children, 2, &old);
+ dmnsn_array_set($<astnode>0.children, 2, &$2);
+ dmnsn_delete_astnode(old);
+ }
+ | "filter" FLOAT {
+ dmnsn_astnode old;
+ dmnsn_array_get($<astnode>0.children, 3, &old);
+ dmnsn_array_set($<astnode>0.children, 3, &$2);
+ dmnsn_delete_astnode(old);
+ }
+ | "transmit" FLOAT {
+ dmnsn_astnode old;
+ dmnsn_array_get($<astnode>0.children, 4, &old);
+ dmnsn_array_set($<astnode>0.children, 4, &$2);
+ dmnsn_delete_astnode(old);
+ }
+;
diff --git a/dimension/grammar.terminals b/dimension/grammar.terminals
new file mode 100644
index 0000000..586715b
--- /dev/null
+++ b/dimension/grammar.terminals
@@ -0,0 +1,519 @@
+/*************************************************************************
+ * Copyright (C) 2010 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/>. *
+ *************************************************************************/
+
+%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 "!="
+
+/* Operators */
+%left "+" "-"
+%left "*" "/"
+%left "."
+%left DMNSN_T_NEGATE
+
+/* 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 "ambient"
+%token DMNSN_T_AMBIENT_LIGHT
+%token DMNSN_T_ANGLE "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 "background"
+%token DMNSN_T_BEZIER_SPLINE
+%token DMNSN_T_BICUBIC_PATCH
+%token DMNSN_T_BLACK_HOLE
+%token DMNSN_T_BLOB
+%token DMNSN_T_BLUE "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 "diffuse"
+%token DMNSN_T_DIMENSION_SIZE
+%token DMNSN_T_DIMENSIONS
+%token DMNSN_T_DIRECTION "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 "falloff"
+%token DMNSN_T_FALLOFF_ANGLE
+%token DMNSN_T_FALSE
+%token DMNSN_T_FILE_EXISTS
+%token DMNSN_T_FILTER "filter"
+%token DMNSN_T_FINAL_CLOCK
+%token DMNSN_T_FINAL_FRAME
+%token DMNSN_T_FINISH "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 "gray"
+%token DMNSN_T_GRAY_THRESHOLD
+%token DMNSN_T_GREEN "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 "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 "location"
+%token DMNSN_T_LOG
+%token DMNSN_T_LOOK_AT "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 "perspective"
+%token DMNSN_T_PGM
+%token DMNSN_T_PHASE
+%token DMNSN_T_PHONG "phong"
+%token DMNSN_T_PHONG_SIZE "phong_size"
+%token DMNSN_T_PHOTONS
+%token DMNSN_T_PI
+%token DMNSN_T_PIGMENT "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 "red"
+%token DMNSN_T_REFLECTION "reflection"
+%token DMNSN_T_REFLECTION_EXPONENT
+%token DMNSN_T_REFRACTION
+%token DMNSN_T_REPEAT
+%token DMNSN_T_RGB "rgb"
+%token DMNSN_T_RGBF "rgbf"
+%token DMNSN_T_RGBFT "rgbft"
+%token DMNSN_T_RGBT "rgbt"
+%token DMNSN_T_RIGHT "right"
+%token DMNSN_T_RIPPLES
+%token DMNSN_T_ROTATE "rotate"
+%token DMNSN_T_ROUGHNESS
+%token DMNSN_T_SAMPLES
+%token DMNSN_T_SAVE_FILE
+%token DMNSN_T_SCALE "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 "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 "t"
+%token DMNSN_T_TAN
+%token DMNSN_T_TANH
+%token DMNSN_T_TARGET
+%token DMNSN_T_TEXT
+%token DMNSN_T_TEXTURE "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 "translate"
+%token DMNSN_T_TRANSMIT "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 "u"
+%token DMNSN_T_U_STEPS
+%token DMNSN_T_ULTRA_WIDE_ANGLE
+%token DMNSN_T_UNION
+%token DMNSN_T_UP "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 "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 "x"
+%token DMNSN_T_Y "y"
+%token DMNSN_T_YES
+%token DMNSN_T_Z "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 "#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 "#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"
diff --git a/dimension/grammar.y b/dimension/grammar.y
deleted file mode 100644
index b41100f..0000000
--- a/dimension/grammar.y
+++ /dev/null
@@ -1,1419 +0,0 @@
-/*************************************************************************
- * Copyright (C) 2010 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>
-
-#define YYSTYPE dmnsn_parse_item
-#define YYLTYPE dmnsn_parse_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_new_astnode(dmnsn_astnode_type type, YYLTYPE lloc)
-{
- dmnsn_astnode astnode = {
- .type = type,
- .children = dmnsn_new_array(sizeof(dmnsn_astnode)),
- .ptr = NULL,
- .refcount = malloc(sizeof(unsigned int)),
- .filename = lloc.first_filename,
- .line = lloc.first_line,
- .col = lloc.first_column
- };
-
- if (!astnode.refcount) {
- dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate reference count.");
- }
- *astnode.refcount = 1;
-
- return astnode;
-}
-
-/* Semi-shallow copy */
-static void
-dmnsn_copy_children(dmnsn_astnode dest, dmnsn_astnode src)
-{
- unsigned int i;
- for (i = 0; i < dmnsn_array_size(src.children); ++i) {
- dmnsn_astnode node;
- dmnsn_array_get(src.children, i, &node);
- ++*node.refcount;
-
- if (i < dmnsn_array_size(dest.children)) {
- dmnsn_astnode clobbered;
- dmnsn_array_get(dest.children, i, &clobbered);
- dmnsn_delete_astnode(clobbered);
- }
-
- dmnsn_array_set(dest.children, i, &node);
- }
-}
-
-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;
-}
-
-static dmnsn_astnode
-dmnsn_new_astnode4(dmnsn_astnode_type type, YYLTYPE lloc,
- dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3,
- dmnsn_astnode n4)
-{
- 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);
- dmnsn_array_push(astnode.children, &n4);
- return astnode;
-}
-
-static dmnsn_astnode
-dmnsn_new_astnode5(dmnsn_astnode_type type, YYLTYPE lloc,
- dmnsn_astnode n1, dmnsn_astnode n2, dmnsn_astnode n3,
- dmnsn_astnode n4, dmnsn_astnode n5)
-{
- 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);
- dmnsn_array_push(astnode.children, &n4);
- dmnsn_array_push(astnode.children, &n5);
- return astnode;
-}
-
-void
-yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
- dmnsn_astree *astree, dmnsn_symbol_table *symtable, const char *str)
-{
- dmnsn_diagnostic(locp->first_filename, locp->first_line, locp->first_column,
- "%s", str);
-}
-%}
-
-%define api.pure
-%locations
-%error-verbose
-%token-table
-
-%name-prefix "dmnsn_yy"
-
-%expect 10
-%glr-parser
-
-%parse-param {const char *filename}
-%parse-param {void *yyscanner}
-%parse-param {dmnsn_astree *astree}
-%parse-param {dmnsn_symbol_table *symtable}
-%lex-param {const char *filename}
-%lex-param {void *yyscanner}
-
-%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 "!="
-
-/* Operators */
-%left "+" "-"
-%left "*" "/"
-%left "."
-%left DMNSN_T_NEGATE
-
-/* 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 "ambient"
-%token DMNSN_T_AMBIENT_LIGHT
-%token DMNSN_T_ANGLE "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 "background"
-%token DMNSN_T_BEZIER_SPLINE
-%token DMNSN_T_BICUBIC_PATCH
-%token DMNSN_T_BLACK_HOLE
-%token DMNSN_T_BLOB
-%token DMNSN_T_BLUE "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 "diffuse"
-%token DMNSN_T_DIMENSION_SIZE
-%token DMNSN_T_DIMENSIONS
-%token DMNSN_T_DIRECTION "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 "falloff"
-%token DMNSN_T_FALLOFF_ANGLE
-%token DMNSN_T_FALSE
-%token DMNSN_T_FILE_EXISTS
-%token DMNSN_T_FILTER "filter"
-%token DMNSN_T_FINAL_CLOCK
-%token DMNSN_T_FINAL_FRAME
-%token DMNSN_T_FINISH "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 "gray"
-%token DMNSN_T_GRAY_THRESHOLD
-%token DMNSN_T_GREEN "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 "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 "location"
-%token DMNSN_T_LOG
-%token DMNSN_T_LOOK_AT "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 "perspective"
-%token DMNSN_T_PGM
-%token DMNSN_T_PHASE
-%token DMNSN_T_PHONG "phong"
-%token DMNSN_T_PHONG_SIZE "phong_size"
-%token DMNSN_T_PHOTONS
-%token DMNSN_T_PI
-%token DMNSN_T_PIGMENT "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 "red"
-%token DMNSN_T_REFLECTION "reflection"
-%token DMNSN_T_REFLECTION_EXPONENT
-%token DMNSN_T_REFRACTION
-%token DMNSN_T_REPEAT
-%token DMNSN_T_RGB "rgb"
-%token DMNSN_T_RGBF "rgbf"
-%token DMNSN_T_RGBFT "rgbft"
-%token DMNSN_T_RGBT "rgbt"
-%token DMNSN_T_RIGHT "right"
-%token DMNSN_T_RIPPLES
-%token DMNSN_T_ROTATE "rotate"
-%token DMNSN_T_ROUGHNESS
-%token DMNSN_T_SAMPLES
-%token DMNSN_T_SAVE_FILE
-%token DMNSN_T_SCALE "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 "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 "t"
-%token DMNSN_T_TAN
-%token DMNSN_T_TANH
-%token DMNSN_T_TARGET
-%token DMNSN_T_TEXT
-%token DMNSN_T_TEXTURE "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 "translate"
-%token DMNSN_T_TRANSMIT "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 "u"
-%token DMNSN_T_U_STEPS
-%token DMNSN_T_ULTRA_WIDE_ANGLE
-%token DMNSN_T_UNION
-%token DMNSN_T_UP "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 "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 "x"
-%token DMNSN_T_Y "y"
-%token DMNSN_T_YES
-%token DMNSN_T_Z "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 "#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 "#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
-
-/* Language directives */
-%type <astnode> RVALUE
-%type <astnode> IDENTIFIER
-
-/* Transformations */
-%type <astnode> TRANSFORMATION
-
-/* The camera */
-%type <astnode> CAMERA
-%type <astnode> CAMERA_ITEMS
-%type <astnode> CAMERA_ITEM
-%type <astnode> CAMERA_TYPE
-%type <astnode> CAMERA_VECTOR
-%type <astnode> CAMERA_MODIFIER
-
-/* Atmospheric effects */
-%type <astnode> ATMOSPHERIC_EFFECT
-%type <astnode> BACKGROUND
-
-/* Objects */
-%type <astnode> OBJECT
-%type <astnode> FINITE_SOLID_OBJECT
-%type <astnode> BOX
-%type <astnode> LIGHT_SOURCE
-%type <astnode> SPHERE
-
-/* Object modifiers */
-%type <astnode> OBJECT_MODIFIERS
-%type <astnode> OBJECT_MODIFIER
-
-/* Textures */
-%type <astnode> TEXTURE
-%type <astnode> TEXTURE_ITEMS
-
-/* Pigments */
-%type <astnode> PIGMENT
-%type <astnode> PIGMENT_TYPE
-
-/* Finishes */
-%type <astnode> FINISH
-%type <astnode> FINISH_ITEMS
-%type <astnode> REFLECTION
-%type <astnode> REFLECTION_ITEMS
-
-/* Floats */
-%type <astnode> FLOAT
-%type <astnode> FLOAT_LITERAL
-
-/* Vectors */
-%type <astnode> VECTOR
-%type <astnode> VECTOR_LITERAL
-
-/* Generalized arithmetic expressions */
-%type <astnode> ARITH_EXPR
-
-/* Colors */
-%type <astnode> COLOR
-%type <astnode> COLOR_BODY
-%type <astnode> COLOR_VECTOR
-%type <astnode> COLOR_KEYWORD_GROUP
-%type <astnode> COLOR_KEYWORD_GROUP_INIT
-
-%destructor { free($$); } <value>
-%destructor { dmnsn_delete_astnode($$); } <astnode>
-
-%%
-
-/* Start symbol */
-
-SCENE: /* empty */
- | SCENE LANGUAGE_DIRECTIVE
- | SCENE SCENE_ITEM {
- dmnsn_array_push(astree, &$2);
- }
-;
-
-/* Language directives */
-
-LANGUAGE_DIRECTIVE: DECLARATION
-;
-
-DECLARATION: "#declare" "identifier" "=" RVALUE {
- dmnsn_declare_symbol(symtable, $2, $4);
- free($2);
- dmnsn_delete_astnode($4);
- }
- | "#local" "identifier" "=" RVALUE {
- dmnsn_local_symbol(symtable, $2, $4);
- free($2);
- dmnsn_delete_astnode($4);
- }
- | "#undef" "identifier" {
- dmnsn_undef_symbol(symtable, $2);
- free($2);
- }
-;
-
-RVALUE: ARITH_EXPR ";" %dprec 2 {
- $$ = dmnsn_eval($1, symtable);
- dmnsn_delete_astnode($1);
-
- if ($$.type == DMNSN_AST_NONE) {
- dmnsn_delete_astnode($$);
- YYERROR;
- }
- }
- | COLOR ";" %dprec 1
-;
-
-IDENTIFIER: "identifier" {
- $$ = dmnsn_new_astnode(DMNSN_AST_IDENTIFIER, @$);
- $$.ptr = $1;
- }
-;
-
-/* Top-level scene item */
-SCENE_ITEM: ATMOSPHERIC_EFFECT
- | CAMERA
- | OBJECT
-;
-
-/* Transformations */
-
-TRANSFORMATION: "rotate" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_ROTATION, @$, $2);
- }
- | "scale" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_SCALE, @$, $2);
- }
- | "translate" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_TRANSLATION, @$, $2);
- }
-;
-
-/* Cameras */
-
-CAMERA: "camera" "{"
- CAMERA_ITEMS
- "}"
- {
- $$ = $3;
- }
-;
-
-CAMERA_ITEMS: /* empty */ {
- $$ = dmnsn_new_astnode(DMNSN_AST_CAMERA, @$);
- }
- | CAMERA_ITEMS CAMERA_ITEM {
- $$ = $1;
- dmnsn_array_push($$.children, &$2);
- }
-;
-
-CAMERA_ITEM: CAMERA_TYPE
- | CAMERA_VECTOR
- | CAMERA_MODIFIER
-;
-
-CAMERA_TYPE: "perspective" {
- $$ = dmnsn_new_astnode(DMNSN_AST_PERSPECTIVE, @$);
- }
-;
-
-CAMERA_VECTOR: "location" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_LOCATION, @$, $2);
- }
- | "right" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_RIGHT, @$, $2);
- }
- | "up" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_UP, @$, $2);
- }
- | "sky" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_SKY, @$, $2);
- }
- | "direction" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DIRECTION, @$, $2);
- }
-;
-
-CAMERA_MODIFIER: "angle" FLOAT {
- $$ = dmnsn_new_astnode1(DMNSN_AST_ANGLE, @$, $2);
- }
- | "look_at" VECTOR {
- $$ = dmnsn_new_astnode1(DMNSN_AST_LOOK_AT, @$, $2);
- }
- | TRANSFORMATION
-;
-
-/* Atmospheric effects */
-
-ATMOSPHERIC_EFFECT: BACKGROUND
-;
-
-BACKGROUND: "background" "{" COLOR "}" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_BACKGROUND, @$, $3);
- }
-;
-
-/* Objects */
-
-OBJECT: FINITE_SOLID_OBJECT
- | LIGHT_SOURCE
-;
-
-FINITE_SOLID_OBJECT: BOX
- | SPHERE
-;
-
-BOX: "box" "{"
- VECTOR "," VECTOR
- OBJECT_MODIFIERS
- "}"
- {
- $$ = dmnsn_new_astnode3(DMNSN_AST_BOX, @$, $3, $5, $6);
- }
-;
-
-LIGHT_SOURCE: "light_source" "{"
- VECTOR "," COLOR
- "}"
- {
- $$ = dmnsn_new_astnode2(DMNSN_AST_LIGHT_SOURCE, @$, $3, $5);
- }
-;
-
-SPHERE: "sphere" "{"
- VECTOR "," FLOAT
- OBJECT_MODIFIERS
- "}"
- {
- $$ = dmnsn_new_astnode3(DMNSN_AST_SPHERE, @$, $3, $5, $6);
- }
-;
-
-/* Object modifiers */
-
-OBJECT_MODIFIERS: /* empty */ {
- $$ = dmnsn_new_astnode(DMNSN_AST_OBJECT_MODIFIERS, @$);
- }
- | OBJECT_MODIFIERS OBJECT_MODIFIER {
- $$ = $1;
- dmnsn_array_push($$.children, &$2);
- }
-;
-
-OBJECT_MODIFIER: TRANSFORMATION
- | TEXTURE
- | PIGMENT {
- $$ = dmnsn_new_astnode1(DMNSN_AST_TEXTURE, @$, $1);
- }
-;
-
-/* Textures */
-
-TEXTURE: "texture" "{"
- TEXTURE_ITEMS
- "}"
- { $$ = $3; }
-;
-
-TEXTURE_ITEMS: /* empty */ {
- $$ = dmnsn_new_astnode(DMNSN_AST_TEXTURE, @$);
- }
- | TEXTURE_ITEMS PIGMENT {
- $$ = $1;
- dmnsn_array_push($$.children, &$2);
- }
- | TEXTURE_ITEMS FINISH {
- $$ = $1;
- dmnsn_array_push($$.children, &$2);
- }
-;
-
-/* Pigments */
-
-PIGMENT: "pigment" "{"
- PIGMENT_TYPE
- "}"
- {
- $$ = dmnsn_new_astnode1(DMNSN_AST_PIGMENT, @$, $3);
- }
-;
-
-PIGMENT_TYPE: /* empty */ {
- $$ = dmnsn_new_astnode(DMNSN_AST_NONE, @$);
- }
- | COLOR
-;
-
-/* Finishes */
-FINISH: "finish" "{"
- FINISH_ITEMS
- "}"
- { $$ = $3; }
-;
-
-FINISH_ITEMS: /* empty */ {
- $$ = dmnsn_new_astnode(DMNSN_AST_FINISH, @$);
- }
- | FINISH_ITEMS "ambient" COLOR {
- dmnsn_astnode ambient = dmnsn_new_astnode1(DMNSN_AST_AMBIENT,
- @2, $3);
- $$ = $1;
- dmnsn_array_push($$.children, &ambient);
- }
- | FINISH_ITEMS "diffuse" FLOAT {
- dmnsn_astnode diffuse = dmnsn_new_astnode1(DMNSN_AST_DIFFUSE,
- @2, $3);
- $$ = $1;
- dmnsn_array_push($$.children, &diffuse);
- }
- | FINISH_ITEMS "phong" FLOAT {
- dmnsn_astnode phong = dmnsn_new_astnode1(DMNSN_AST_PHONG, @2, $3);
- $$ = $1;
- dmnsn_array_push($$.children, &phong);
- }
- | FINISH_ITEMS "phong_size" FLOAT {
- dmnsn_astnode phong_size
- = dmnsn_new_astnode1(DMNSN_AST_PHONG_SIZE, @2, $3);
- $$ = $1;
- dmnsn_array_push($$.children, &phong_size);
- }
- | FINISH_ITEMS REFLECTION {
- $$ = $1;
- dmnsn_array_push($$.children, &$2);
- }
-;
-
-REFLECTION: "reflection" "{"
- COLOR
- REFLECTION_ITEMS
- "}"
- {
- ++*$3.refcount;
- $$ = dmnsn_new_astnode3(DMNSN_AST_REFLECTION, @$, $3, $3, $4);
- }
- | "reflection" "{"
- COLOR "," COLOR
- REFLECTION_ITEMS
- "}"
- {
- $$ = dmnsn_new_astnode3(DMNSN_AST_REFLECTION, @$, $3, $5, $6);
- }
-;
-
-REFLECTION_ITEMS: /* empty */ {
- $$ = dmnsn_new_astnode(DMNSN_AST_REFLECTION_ITEMS, @$);
- }
- | REFLECTION_ITEMS "falloff" FLOAT {
- dmnsn_astnode falloff
- = dmnsn_new_astnode1(DMNSN_AST_FALLOFF, @2, $3);
- $$ = $1;
- dmnsn_array_push($$.children, &falloff);
- }
-;
-
-/* Floats */
-
-FLOAT: ARITH_EXPR {
- $$ = dmnsn_eval_scalar($1, symtable);
- dmnsn_delete_astnode($1);
-
- if ($$.type == DMNSN_AST_NONE) {
- dmnsn_delete_astnode($$);
- YYERROR;
- }
- }
-;
-
-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);
- free($1);
- }
- | "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);
- free($1);
- }
-;
-
-/* Vectors */
-
-VECTOR: ARITH_EXPR {
- $$ = dmnsn_eval_vector($1, symtable);
- dmnsn_delete_astnode($1);
-
- if ($$.type == DMNSN_AST_NONE) {
- dmnsn_delete_astnode($$);
- YYERROR;
- }
- }
-;
-
-VECTOR_LITERAL: "<" ARITH_EXPR "," ARITH_EXPR ">" {
- $$ = dmnsn_new_astnode2(DMNSN_AST_VECTOR, @$, $2, $4);
- }
- | "<" ARITH_EXPR "," ARITH_EXPR "," ARITH_EXPR ">" {
- $$ = dmnsn_new_astnode3(DMNSN_AST_VECTOR, @$, $2, $4, $6);
- }
- | "<" ARITH_EXPR "," ARITH_EXPR "," ARITH_EXPR ","
- ARITH_EXPR ">" {
- $$ = dmnsn_new_astnode4(DMNSN_AST_VECTOR, @$, $2, $4, $6, $8);
- }
- | "<" ARITH_EXPR "," ARITH_EXPR "," ARITH_EXPR ","
- ARITH_EXPR "," ARITH_EXPR ">" {
- $$ = dmnsn_new_astnode5(DMNSN_AST_VECTOR, @$,
- $2, $4, $6, $8, $10);
- }
-;
-
-/* Generalized arithmetic expressions */
-
-ARITH_EXPR: FLOAT_LITERAL
- | VECTOR_LITERAL
- | ARITH_EXPR "+" ARITH_EXPR {
- $$ = dmnsn_new_astnode2(DMNSN_AST_ADD, @$, $1, $3);
- }
- | ARITH_EXPR "-" ARITH_EXPR {
- $$ = dmnsn_new_astnode2(DMNSN_AST_SUB, @$, $1, $3);
- }
- | ARITH_EXPR "*" ARITH_EXPR {
- $$ = dmnsn_new_astnode2(DMNSN_AST_MUL, @$, $1, $3);
- }
- | ARITH_EXPR "/" ARITH_EXPR {
- $$ = dmnsn_new_astnode2(DMNSN_AST_DIV, @$, $1, $3);
- }
- | "+" ARITH_EXPR %prec DMNSN_T_NEGATE { $$ = $2; }
- | "-" ARITH_EXPR %prec DMNSN_T_NEGATE {
- $$ = dmnsn_new_astnode1(DMNSN_AST_NEGATE, @$, $2);
- }
- | ARITH_EXPR "." "x" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_X, @$, $1);
- }
- | ARITH_EXPR "." "u" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_X, @$, $1);
- }
- | ARITH_EXPR "." "red" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_X, @$, $1);
- }
- | ARITH_EXPR "." "y" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Y, @$, $1);
- }
- | ARITH_EXPR "." "v" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Y, @$, $1);
- }
- | ARITH_EXPR "." "green" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Y, @$, $1);
- }
- | ARITH_EXPR "." "z" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Z, @$, $1);
- }
- | ARITH_EXPR "." "blue" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_Z, @$, $1);
- }
- | ARITH_EXPR "." "t" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_T, @$, $1);
- }
- | ARITH_EXPR "." "filter" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_T, @$, $1);
- }
- | ARITH_EXPR "." "transmit" {
- $$ = dmnsn_new_astnode1(DMNSN_AST_DOT_TRANSMIT, @$, $1);
- }
- | "(" ARITH_EXPR ")" { $$ = $2; }
- | IDENTIFIER
-;
-
-/* Colors */
-
-COLOR: COLOR_BODY {
- $$ = $1;
- $$.type = DMNSN_AST_COLOR;
- }
- | "color" COLOR_BODY {
- $$ = $2;
- $$.type = DMNSN_AST_COLOR;
- }
-;
-
-COLOR_BODY: COLOR_VECTOR %dprec 1
- | COLOR_KEYWORD_GROUP %dprec 2
-;
-
-COLOR_VECTOR: "rgb" VECTOR {
- dmnsn_astnode f, t;
- dmnsn_array_get($2.children, 3, &f);
- dmnsn_array_get($2.children, 4, &t);
- dmnsn_delete_astnode(f);
- dmnsn_delete_astnode(t);
-
- dmnsn_array_resize($2.children, 3);
-
- $$ = dmnsn_eval_vector($2, symtable);
- dmnsn_delete_astnode($2);
- }
- | "rgbf" VECTOR {
- dmnsn_astnode t;
- dmnsn_array_get($2.children, 4, &t);
- dmnsn_delete_astnode(t);
-
- dmnsn_array_resize($2.children, 4);
-
- $$ = dmnsn_eval_vector($2, symtable);
- dmnsn_delete_astnode($2);
- }
- | "rgbt" VECTOR {
- /* Chop off the fifth component */
- dmnsn_astnode t;
- dmnsn_array_get($2.children, 4, &t);
- dmnsn_delete_astnode(t);
-
- dmnsn_array_resize($2.children, 4);
-
- $$ = dmnsn_eval_vector($2, symtable);
- dmnsn_delete_astnode($2);
-
- /* Swap the transmit and filter components */
- dmnsn_astnode temp;
- dmnsn_array_get($$.children, 4, &temp);
- dmnsn_array_set($$.children, 4, dmnsn_array_at($$.children, 3));
- dmnsn_array_set($$.children, 3, &temp);
- }
- | "rgbft" VECTOR { $$ = $2; }
- | VECTOR
-;
-
-COLOR_KEYWORD_GROUP: COLOR_KEYWORD_GROUP_INIT COLOR_KEYWORD_ITEM
- | COLOR_KEYWORD_GROUP COLOR_KEYWORD_ITEM
-;
-
-COLOR_KEYWORD_GROUP_INIT: /* empty */ {
- dmnsn_astnode zero =
- dmnsn_new_astnode(DMNSN_AST_INTEGER, @$);
- zero.ptr = malloc(sizeof(long));
- if (!zero.ptr)
- dmnsn_error(DMNSN_SEVERITY_HIGH,
- "Failed to allocate room for integer.");
- *(long *)zero.ptr = 0;
-
- $$ = dmnsn_eval_vector(zero, symtable);
- dmnsn_delete_astnode(zero);
- }
-;
-
-COLOR_KEYWORD_ITEM: "identifier" {
- dmnsn_astnode *symbol = dmnsn_find_symbol(symtable, $1);
- if (!symbol) {
- dmnsn_diagnostic(@1.first_filename, @1.first_line,
- @1.first_column,
- "unbound identifier '%s'", $1);
- free($1);
- YYERROR;
- } else if (symbol->type != DMNSN_AST_COLOR) {
- dmnsn_astnode eval = dmnsn_eval_vector(*symbol, symtable);
- if (eval.type == DMNSN_AST_NONE) {
- free($1);
- YYERROR;
- }
-
- dmnsn_copy_children($<astnode>0, eval);
- dmnsn_delete_astnode(eval);
- } else {
- dmnsn_copy_children($<astnode>0, *symbol);
- }
-
- free($1);
- }
- | "red" FLOAT {
- dmnsn_astnode old;
- dmnsn_array_get($<astnode>0.children, 0, &old);
- dmnsn_array_set($<astnode>0.children, 0, &$2);
- dmnsn_delete_astnode(old);
- }
- | "green" FLOAT {
- dmnsn_astnode old;
- dmnsn_array_get($<astnode>0.children, 1, &old);
- dmnsn_array_set($<astnode>0.children, 1, &$2);
- dmnsn_delete_astnode(old);
- }
- | "blue" FLOAT {
- dmnsn_astnode old;
- dmnsn_array_get($<astnode>0.children, 2, &old);
- dmnsn_array_set($<astnode>0.children, 2, &$2);
- dmnsn_delete_astnode(old);
- }
- | "filter" FLOAT {
- dmnsn_astnode old;
- dmnsn_array_get($<astnode>0.children, 3, &old);
- dmnsn_array_set($<astnode>0.children, 3, &$2);
- dmnsn_delete_astnode(old);
- }
- | "transmit" FLOAT {
- dmnsn_astnode old;
- dmnsn_array_get($<astnode>0.children, 4, &old);
- dmnsn_array_set($<astnode>0.children, 4, &$2);
- dmnsn_delete_astnode(old);
- }
-;
-
-%%
-
-dmnsn_astree *
-dmnsn_parse(FILE *file, dmnsn_symbol_table *symtable)
-{
- const char *filename;
- dmnsn_astnode *fnode = dmnsn_find_symbol(symtable, "__file__");
- if (fnode && fnode->type == DMNSN_AST_STRING) {
- filename = fnode->ptr;
- } else {
- filename = "<>";
- dmnsn_declare_symbol(symtable, "__file__", dmnsn_new_ast_string(filename));
- }
-
- void *scanner;
- dmnsn_astree *astree = dmnsn_new_array(sizeof(dmnsn_astnode));
-
- dmnsn_yylex_init(&scanner);
- dmnsn_yyset_in(file, scanner);
-
- if (yyparse(filename, scanner, astree, symtable) != 0) {
- dmnsn_delete_astree(astree);
- astree = NULL;
- }
-
- dmnsn_yylex_destroy(scanner);
- return astree;
-}
-
-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_NONE, "none");
-
- dmnsn_astnode_map(DMNSN_AST_ROTATION, "rotate");
- dmnsn_astnode_map(DMNSN_AST_SCALE, "scale");
- dmnsn_astnode_map(DMNSN_AST_TRANSLATION, "translate");
-
- dmnsn_astnode_map(DMNSN_AST_CAMERA, "camera");
- dmnsn_astnode_map(DMNSN_AST_PERSPECTIVE, "perspective");
- dmnsn_astnode_map(DMNSN_AST_LOCATION, "location");
- dmnsn_astnode_map(DMNSN_AST_RIGHT, "right");
- dmnsn_astnode_map(DMNSN_AST_UP, "up");
- dmnsn_astnode_map(DMNSN_AST_SKY, "sky");
- dmnsn_astnode_map(DMNSN_AST_ANGLE, "angle");
- dmnsn_astnode_map(DMNSN_AST_LOOK_AT, "look_at");
- dmnsn_astnode_map(DMNSN_AST_DIRECTION, "direction");
-
- dmnsn_astnode_map(DMNSN_AST_BACKGROUND, "background");
-
- dmnsn_astnode_map(DMNSN_AST_BOX, "box");
- dmnsn_astnode_map(DMNSN_AST_SPHERE, "sphere");
- dmnsn_astnode_map(DMNSN_AST_LIGHT_SOURCE, "light_source");
-
- dmnsn_astnode_map(DMNSN_AST_OBJECT_MODIFIERS, "object-modifiers");
-
- dmnsn_astnode_map(DMNSN_AST_TEXTURE, "texture");
-
- dmnsn_astnode_map(DMNSN_AST_PIGMENT, "pigment");
-
- dmnsn_astnode_map(DMNSN_AST_FINISH, "finish");
- dmnsn_astnode_map(DMNSN_AST_AMBIENT, "ambient");
- dmnsn_astnode_map(DMNSN_AST_DIFFUSE, "diffuse");
- dmnsn_astnode_map(DMNSN_AST_PHONG, "phong");
- dmnsn_astnode_map(DMNSN_AST_PHONG_SIZE, "phong_size");
-
- dmnsn_astnode_map(DMNSN_AST_REFLECTION, "reflection");
- dmnsn_astnode_map(DMNSN_AST_REFLECTION_ITEMS, "reflection-items");
- dmnsn_astnode_map(DMNSN_AST_FALLOFF, "falloff");
-
- dmnsn_astnode_map(DMNSN_AST_FLOAT, "float");
- dmnsn_astnode_map(DMNSN_AST_INTEGER, "integer");
-
- dmnsn_astnode_map(DMNSN_AST_VECTOR, "vector");
-
- 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_NEGATE, "-");
- dmnsn_astnode_map(DMNSN_AST_DOT_X, ".x");
- dmnsn_astnode_map(DMNSN_AST_DOT_Y, ".y");
- dmnsn_astnode_map(DMNSN_AST_DOT_Z, ".z");
- dmnsn_astnode_map(DMNSN_AST_DOT_T, ".t");
- dmnsn_astnode_map(DMNSN_AST_DOT_TRANSMIT, ".transmit");
-
- dmnsn_astnode_map(DMNSN_AST_COLOR, "color");
-
- dmnsn_astnode_map(DMNSN_AST_IDENTIFIER, "identifier");
-
- dmnsn_astnode_map(DMNSN_AST_STRING, "string");
-
- default:
- fprintf(stderr, "Warning: unrecognised astnode type %d.\n",
- (int)astnode_type);
- return "unrecognized-astnode";
- }
-}