From 6b4b62ab01309462608ad1c885c07be5648c2cf1 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 23 Nov 2009 18:38:29 -0500 Subject: More parser work. --- dimension/bison.y | 142 +++++++++++++++++++++++++++++++++-------- dimension/parse.h | 2 +- tests/dimension/demo.sh | 2 +- tests/dimension/numeric.sh | 2 +- tests/dimension/punctuation.sh | 2 +- 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 DMNSN_T_INTEGER "integer" +%token 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 DMNSN_T_IDENTIFIER "identifier" /* Strings */ -%token DMNSN_T_STRING "string" +%token DMNSN_T_STRING "string" -%% +/* Top-level items */ +%type SCENE_ITEM -SCENE: /* empty */ - | SCENE SCENE_ITEM - ; +/* Objects */ +%type OBJECT +%type FINITE_SOLID_OBJECT +%type BOX +%type SPHERE -SCENE_ITEM: OBJECT - ; +/* Vectors */ +%type VECTOR +%type VECTOR_LITERAL -OBJECT: FINITE_SOLID_OBJECT - ; +/* Floats */ +%type FLOAT +%type FLOAT_LITERAL -FINITE_SOLID_OBJECT: BOX | SPHERE - ; +%destructor { dmnsn_delete_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 -- cgit v1.2.3