summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-12-21 17:21:00 -0500
committerTavian Barnes <tavianator@gmail.com>2009-12-21 17:21:00 -0500
commitff44d1b89812c1c7ef86c848937f17a59c64a66e (patch)
tree4c3c1ee113430ed1a3d1b4ec9acd186859ef0a40
parent8424804b1feaff5121060ed5ae4a321c47a76c34 (diff)
downloaddimension-ff44d1b89812c1c7ef86c848937f17a59c64a66e.tar.xz
Clean up parser, and make it GLR.
-rw-r--r--dimension/Makefile.am3
-rw-r--r--dimension/grammar.y116
-rw-r--r--dimension/y.tab.h21
-rw-r--r--tests/dimension/directives.pov2
-rwxr-xr-xtests/dimension/directives.sh4
5 files changed, 64 insertions, 82 deletions
diff --git a/dimension/Makefile.am b/dimension/Makefile.am
index 0e3c862..343aa27 100644
--- a/dimension/Makefile.am
+++ b/dimension/Makefile.am
@@ -35,5 +35,6 @@ dimension_SOURCES = grammar.y \
realize.h \
tokenize.h \
utility.c \
- utility.h
+ utility.h \
+ y.tab.h
dimension_LDADD = $(top_builddir)/libdimension/libdimension.la
diff --git a/dimension/grammar.y b/dimension/grammar.y
index 7369300..b7e2b19 100644
--- a/dimension/grammar.y
+++ b/dimension/grammar.y
@@ -76,52 +76,23 @@ dmnsn_new_astnode(dmnsn_astnode_type type, YYLTYPE lloc)
}
/* Semi-shallow copy */
-static dmnsn_astnode
-dmnsn_copy_astnode(dmnsn_astnode astnode)
+static void
+dmnsn_copy_children(dmnsn_astnode dest, dmnsn_astnode src)
{
- dmnsn_astnode copy = {
- .type = astnode.type,
- .children = dmnsn_new_array(sizeof(dmnsn_astnode)),
- .ptr = NULL,
- .refcount = malloc(sizeof(unsigned int)),
- .filename = astnode.filename,
- .line = astnode.line,
- .col = astnode.col
- };
-
- if (!copy.refcount) {
- dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't allocate reference count.");
- }
- *copy.refcount = 1;
-
unsigned int i;
- for (i = 0; i < dmnsn_array_size(astnode.children); ++i) {
- dmnsn_astnode n;
- dmnsn_array_get(astnode.children, i, &n);
- ++*n.refcount;
- dmnsn_array_push(copy.children, &n);
+ 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);
}
-
- switch (astnode.type) {
- case DMNSN_AST_INTEGER:
- copy.ptr = malloc(sizeof(long));
- memcpy(copy.ptr, astnode.ptr, sizeof(long));
- break;
-
- case DMNSN_AST_FLOAT:
- copy.ptr = malloc(sizeof(double));
- memcpy(copy.ptr, astnode.ptr, sizeof(double));
- break;
-
- case DMNSN_AST_STRING:
- copy.ptr = strdup(astnode.ptr);
- break;
-
- default:
- break;
- }
-
- return copy;
}
static dmnsn_astnode
@@ -196,7 +167,8 @@ yyerror(YYLTYPE *locp, const char *filename, void *yyscanner,
%name-prefix "dmnsn_yy"
-%expect 18
+%expect 7
+%glr-parser
%parse-param {const char *filename}
%parse-param {void *yyscanner}
@@ -800,7 +772,7 @@ DECLARATION: "#declare" "identifier" "=" RVALUE {
}
;
-RVALUE: ARITH_EXPR ";" {
+RVALUE: ARITH_EXPR ";" %dprec 2 {
$$ = dmnsn_eval($1, symtable);
dmnsn_delete_astnode($1);
@@ -809,7 +781,7 @@ RVALUE: ARITH_EXPR ";" {
YYERROR;
}
}
- | COLOR ";"
+ | COLOR ";" %dprec 1
;
IDENTIFIER: "identifier" {
@@ -1123,8 +1095,8 @@ COLOR: COLOR_BODY {
}
;
-COLOR_BODY: COLOR_VECTOR
- | COLOR_KEYWORD_GROUP
+COLOR_BODY: COLOR_VECTOR %dprec 1
+ | COLOR_KEYWORD_GROUP %dprec 2
;
COLOR_VECTOR: "rgb" VECTOR { $$ = $2; }
@@ -1138,6 +1110,7 @@ COLOR_VECTOR: "rgb" VECTOR { $$ = $2; }
dmnsn_array_set($$.children, 3, &temp);
}
| "rgbft" VECTOR { $$ = $2; }
+ | VECTOR
;
COLOR_KEYWORD_GROUP: COLOR_KEYWORD_GROUP_INIT COLOR_KEYWORD_ITEM
@@ -1158,41 +1131,28 @@ COLOR_KEYWORD_GROUP_INIT: /* empty */ {
}
;
-COLOR_KEYWORD_ITEM: ARITH_EXPR {
- if ($1.type == DMNSN_AST_IDENTIFIER) {
- dmnsn_astnode *symbol = dmnsn_find_symbol(symtable,
- $1.ptr);
- if (!symbol) {
- dmnsn_diagnostic(@1.first_filename, @1.first_line,
- @1.first_column,
- "unbound identifier '%s'", $1);
- dmnsn_delete_astnode($1);
+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;
- } else if (symbol->type != DMNSN_AST_VECTOR
- && symbol->type != DMNSN_AST_COLOR) {
- dmnsn_astnode eval = dmnsn_eval_vector(*symbol,
- symtable);
- if (eval.type == DMNSN_AST_NONE) {
- dmnsn_diagnostic(@1.first_filename, @1.first_line,
- @1.first_column,
- "expected color; found '%s'",
- dmnsn_astnode_string(symbol->type));
- dmnsn_delete_astnode($1);
- YYERROR;
- }
-
- $<astnode>0 = dmnsn_copy_astnode(eval);
- dmnsn_delete_astnode(eval);
- } else {
- $<astnode>0 = dmnsn_copy_astnode(*symbol);
}
- } else {
- dmnsn_astnode eval = dmnsn_eval_vector($1, symtable);
- $<astnode>0 = dmnsn_copy_astnode(eval);
+
+ dmnsn_copy_children($<astnode>0, eval);
dmnsn_delete_astnode(eval);
+ } else {
+ dmnsn_copy_children($<astnode>0, *symbol);
}
- dmnsn_delete_astnode($1);
+ free($1);
}
| "red" FLOAT {
dmnsn_astnode old;
diff --git a/dimension/y.tab.h b/dimension/y.tab.h
new file mode 100644
index 0000000..d6b0b52
--- /dev/null
+++ b/dimension/y.tab.h
@@ -0,0 +1,21 @@
+/*************************************************************************
+ * 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/>. *
+ *************************************************************************/
+
+/* Hack around automake sucking */
+#include "grammar.h"
diff --git a/tests/dimension/directives.pov b/tests/dimension/directives.pov
index 6b0e72c..0b2b2b3 100644
--- a/tests/dimension/directives.pov
+++ b/tests/dimension/directives.pov
@@ -29,6 +29,6 @@
sphere {
Center, R
pigment {
- color Color
+ color Color green 1
}
}
diff --git a/tests/dimension/directives.sh b/tests/dimension/directives.sh
index 49095a9..c953cd6 100755
--- a/tests/dimension/directives.sh
+++ b/tests/dimension/directives.sh
@@ -29,7 +29,7 @@ directives_exp="$(echo -n \
sphere {
(identifier "Center") , (identifier "R")
pigment {
- color (identifier "Color")
+ color (identifier "Color") green (integer "1")
}
})' \
| tr '\n' ' ' | sed -r 's/[[:space:]]+/ /g')
@@ -39,7 +39,7 @@ $(echo -n \
(integer 1)
(object-modifiers
(texture
- (pigment (color (integer 1) (integer 0) (integer 1)
+ (pigment (color (integer 1) (integer 1) (integer 1)
(integer 0) (integer 0)))))))' \
| tr '\n' ' ' | sed -r 's/[[:space:]]+/ /g')"