summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-11-23 18:38:29 -0500
committerTavian Barnes <tavianator@gmail.com>2009-11-23 18:38:29 -0500
commit6b4b62ab01309462608ad1c885c07be5648c2cf1 (patch)
tree5d400fc4d26701d17d30a53fe8db86a9950a06d6
parent0d35bf194a386cc6f7ad238bb356e65ed45a6062 (diff)
downloaddimension-6b4b62ab01309462608ad1c885c07be5648c2cf1.tar.xz
More parser work.
-rw-r--r--dimension/bison.y142
-rw-r--r--dimension/parse.h2
-rwxr-xr-xtests/dimension/demo.sh2
-rwxr-xr-xtests/dimension/numeric.sh2
-rwxr-xr-xtests/dimension/punctuation.sh2
5 files changed, 121 insertions, 29 deletions
diff --git a/dimension/bison.y b/dimension/bison.y
index ff50a8c..8b67669 100644
--- a/dimension/bison.y
+++ b/dimension/bison.y
@@ -29,14 +29,17 @@ typedef struct dmnsn_token_iterator {
unsigned int i;
} dmnsn_token_iterator;
-#define YYSTYPE const char *
-
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 { \
@@ -57,6 +60,29 @@ typedef struct dmnsn_location {
} \
} 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,
+ .filename = lloc.first_filename,
+ .line = lloc.first_line,
+ .col = lloc.first_column
+ };
+ 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)
{
@@ -67,7 +93,7 @@ yylex(YYSTYPE *lvalp, YYLTYPE *llocp, dmnsn_token_iterator *iterator)
dmnsn_array_get(iterator->tokens, iterator->i, &token);
++iterator->i;
- *lvalp = token.value;
+ lvalp->value = token.value;
llocp->first_filename = llocp->last_filename = token.filename;
llocp->first_line = llocp->last_line = token.line;
@@ -124,8 +150,8 @@ yyerror(YYLTYPE *locp, dmnsn_array *astree, dmnsn_token_iterator *iterator,
%token DMNSN_T_NOT_EQUAL "!="
/* Numeric values */
-%token DMNSN_T_INTEGER "integer"
-%token DMNSN_T_FLOAT "float"
+%token <value> DMNSN_T_INTEGER "integer"
+%token <value> DMNSN_T_FLOAT "float"
/* Keywords */
%token DMNSN_T_AA_LEVEL
@@ -585,31 +611,93 @@ yyerror(YYLTYPE *locp, dmnsn_array *astree, dmnsn_token_iterator *iterator,
%token DMNSN_T_WRITE
/* Identifiers */
-%token DMNSN_T_IDENTIFIER "identifier"
+%token <value> DMNSN_T_IDENTIFIER "identifier"
/* Strings */
-%token DMNSN_T_STRING "string"
+%token <value> DMNSN_T_STRING "string"
-%%
+/* Top-level items */
+%type <astnode> SCENE_ITEM
-SCENE: /* empty */
- | SCENE SCENE_ITEM
- ;
+/* Objects */
+%type <astnode> OBJECT
+%type <astnode> FINITE_SOLID_OBJECT
+%type <astnode> BOX
+%type <astnode> SPHERE
-SCENE_ITEM: OBJECT
- ;
+/* Vectors */
+%type <astnode> VECTOR
+%type <astnode> VECTOR_LITERAL
-OBJECT: FINITE_SOLID_OBJECT
- ;
+/* Floats */
+%type <astnode> FLOAT
+%type <astnode> FLOAT_LITERAL
-FINITE_SOLID_OBJECT: BOX | SPHERE
- ;
+%destructor { dmnsn_delete_astnode($$); } <astnode>
+
+%%
-BOX: "box" "{" "}"
- ;
+SCENE: /* empty */ { }
+ | SCENE SCENE_ITEM {
+ dmnsn_array_push(astree, &$2);
+ }
+;
-SPHERE: "sphere" "{" "}"
- ;
+SCENE_ITEM: OBJECT
+;
+
+OBJECT: FINITE_SOLID_OBJECT
+;
+
+FINITE_SOLID_OBJECT: BOX
+ | SPHERE
+;
+
+BOX: "box" "{"
+ VECTOR "," VECTOR
+ "}"
+ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_BOX, @$);
+ dmnsn_array_push($$.children, &$3);
+ dmnsn_array_push($$.children, &$5);
+ }
+;
+
+SPHERE: "sphere" "{"
+ "}"
+ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_SPHERE, @$);
+ }
+;
+
+VECTOR: VECTOR_LITERAL
+;
+
+VECTOR_LITERAL: "<" FLOAT "," FLOAT "," FLOAT ">"
+ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_VECTOR, @$);
+ dmnsn_array_push($$.children, &$2);
+ dmnsn_array_push($$.children, &$4);
+ dmnsn_array_push($$.children, &$6);
+ }
+;
+
+FLOAT: FLOAT_LITERAL
+;
+
+FLOAT_LITERAL: "integer"
+ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_INTEGER, @$);
+ $$.ptr = malloc(sizeof(long));
+ *(long *)$$.ptr = strtol($1, NULL, 0);
+ }
+ | "float"
+ {
+ $$ = dmnsn_new_astnode(DMNSN_AST_FLOAT, @$);
+ $$.ptr = malloc(sizeof(double));
+ *(double *)$$.ptr = strtod($1, NULL);
+ }
+;
%%
@@ -713,8 +801,8 @@ dmnsn_print_astree_sexpr(FILE *file, const dmnsn_array *astree)
const char *
dmnsn_token_string(dmnsn_token_type token_type)
{
-#define TOKEN_SIZE 256
- static char token[TOKEN_SIZE];
+#define TOKEN_SIZE 255
+ static char token[TOKEN_SIZE + 1];
unsigned int i = YYTRANSLATE(token_type);
if (i > YYNTOKENS) {
@@ -722,12 +810,16 @@ dmnsn_token_string(dmnsn_token_type token_type)
return "unrecognized-token";
}
- if (yytnamerr(NULL, yytname[i]) >= TOKEN_SIZE) {
+ /* 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";
}
- yytnamerr(token, yytname[i]);
+ strcpy(token, yytname[i] + 1);
+ token[strlen(token) - 1] = '\0';
+
return token;
#undef TOKEN_SIZE
}
diff --git a/dimension/parse.h b/dimension/parse.h
index b55588b..956c946 100644
--- a/dimension/parse.h
+++ b/dimension/parse.h
@@ -47,7 +47,7 @@ struct dmnsn_astnode {
void *ptr;
/* File name, and line and column numbers from source code */
- char *filename;
+ const char *filename;
unsigned int line, col;
};
diff --git a/tests/dimension/demo.sh b/tests/dimension/demo.sh
index 452b9bb..816a317 100755
--- a/tests/dimension/demo.sh
+++ b/tests/dimension/demo.sh
@@ -20,7 +20,7 @@
#########################################################################
demo=$(${top_builddir}/dimension/dimension --tokenize --parse ${srcdir}/demo.pov)
-demo_exp='(box { < - (float "2.0") + (integer "1") "," - (integer "2") / (float "2.0") "," - (float "1.0") > "," < (float "1.0") "," \( (float "1.0") + (integer "2") \) * (integer "2") - (integer "5") "," (float "1.0") + (integer "2") * (integer "2") - (integer "4") > } sphere { < (integer "1") / (integer "5") + - (integer "1") / (integer "5") "," (integer "1") / (float "5.0") - (float "1.0") / (integer "5") "," - (integer "1") - - (integer "1") > "," (float "1.25") })
+demo_exp='(box { < - (float "2.0") + (integer "1") , - (integer "2") / (float "2.0") , - (float "1.0") > , < (float "1.0") , \( (float "1.0") + (integer "2") \) * (integer "2") - (integer "5") , (float "1.0") + (integer "2") * (integer "2") - (integer "4") > } sphere { < (integer "1") / (integer "5") + - (integer "1") / (integer "5") , (integer "1") / (float "5.0") - (float "1.0") / (integer "5") , - (integer "1") - - (integer "1") > , (float "1.25") })
((box (vector (float -1) (float -1) (float -1)) (vector (float 1) (float 1) (float 1))) (sphere (vector (float 0) (float 0) (integer 0)) (float 1.25)))'
if [ "$demo" != "$demo_exp" ]; then
diff --git a/tests/dimension/numeric.sh b/tests/dimension/numeric.sh
index 372176f..d4b4d89 100755
--- a/tests/dimension/numeric.sh
+++ b/tests/dimension/numeric.sh
@@ -20,7 +20,7 @@
#########################################################################
numeric=$(${top_builddir}/dimension/dimension --tokenize ${srcdir}/numeric.pov)
-numeric_exp='((integer "1") (integer "123456789") (integer "01234567") (integer "0x123456789") - (integer "0x01") (float ".1") (float "0.1") (float "1.0") (float "0.123456789") - (float "0.123456789") < (integer "1") "," (float "2.2") "," - (float "3.03") >)'
+numeric_exp='((integer "1") (integer "123456789") (integer "01234567") (integer "0x123456789") - (integer "0x01") (float ".1") (float "0.1") (float "1.0") (float "0.123456789") - (float "0.123456789") < (integer "1") , (float "2.2") , - (float "3.03") >)'
if [ "$numeric" != "$numeric_exp" ]; then
echo "numeric.pov tokenized as \"$numeric\"" >&2
diff --git a/tests/dimension/punctuation.sh b/tests/dimension/punctuation.sh
index 4a91cd7..3765ffa 100755
--- a/tests/dimension/punctuation.sh
+++ b/tests/dimension/punctuation.sh
@@ -20,7 +20,7 @@
#########################################################################
punctuation=$(${top_builddir}/dimension/dimension --tokenize ${srcdir}/punctuation.pov)
-punctuation_exp='({ } \( \) [ ] + - * / "," ; ? : & . | = < > ! <= >= !=)'
+punctuation_exp='({ } \( \) [ ] + - * / , ; ? : & . | = < > ! <= >= !=)'
if [ "$punctuation" != "$punctuation_exp" ]; then
echo "punctuation.pov tokenized as \"$punctuation\"" >&2