From 92efb5d0d7ba0c2b49cf189d5055bc0d9b09994c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 31 Oct 2009 14:05:02 -0400 Subject: Implement dmnsn_print_astree_sexpr(). --- dimension/parse.c | 104 ++++++++++++++++++++++++++++++++++++++++++------- dimension/parse.h | 5 ++- dimension/tokenize.c | 18 ++++----- dimension/tokenize.h | 2 +- tests/dimension/box.sh | 10 +++++ 5 files changed, 114 insertions(+), 25 deletions(-) diff --git a/dimension/parse.c b/dimension/parse.c index b8085d8..42a48bd 100644 --- a/dimension/parse.c +++ b/dimension/parse.c @@ -35,13 +35,13 @@ dmnsn_parse_expect(dmnsn_token_type type, const dmnsn_array *tokens, if (token.type != type) { dmnsn_diagnostic(token.filename, token.line, token.col, "Expected '%s', found '%s'", - dmnsn_token_name(type), - dmnsn_token_name(token.type)); + dmnsn_token_string(type), + dmnsn_token_string(token.type)); return 1; } } else { fprintf(stderr, "Expected '%s', found end of file\n", - dmnsn_token_name(type)); + dmnsn_token_string(type)); return 1; } @@ -57,8 +57,8 @@ dmnsn_parse_float(const dmnsn_array *tokens, unsigned int *ip, if (i >= dmnsn_array_size(tokens)) { fprintf(stderr, "Expected '%s' or '%s', found end of file\n", - dmnsn_token_name(DMNSN_T_INTEGER), - dmnsn_token_name(DMNSN_T_FLOAT)); + dmnsn_token_string(DMNSN_T_INTEGER), + dmnsn_token_string(DMNSN_T_FLOAT)); return 1; } @@ -72,8 +72,8 @@ dmnsn_parse_float(const dmnsn_array *tokens, unsigned int *ip, ++i; if (i >= dmnsn_array_size(tokens)) { fprintf(stderr, "Expected '%s' or '%s', found end of file\n", - dmnsn_token_name(DMNSN_T_INTEGER), - dmnsn_token_name(DMNSN_T_FLOAT)); + dmnsn_token_string(DMNSN_T_INTEGER), + dmnsn_token_string(DMNSN_T_FLOAT)); return 1; } dmnsn_array_get(tokens, i, &token); @@ -88,9 +88,9 @@ dmnsn_parse_float(const dmnsn_array *tokens, unsigned int *ip, ++i; } else { fprintf(stderr, "Expected '%s' or '%s', found '%s'\n", - dmnsn_token_name(DMNSN_T_INTEGER), - dmnsn_token_name(DMNSN_T_FLOAT), - dmnsn_token_name(token.type)); + dmnsn_token_string(DMNSN_T_INTEGER), + dmnsn_token_string(DMNSN_T_FLOAT), + dmnsn_token_string(token.type)); return 1; } @@ -214,8 +214,8 @@ dmnsn_parse(const dmnsn_array *tokens) if (dmnsn_parse_box(tokens, &i, astree) != 0) { dmnsn_diagnostic(token.filename, token.line, token.col, "Invalid box", - dmnsn_token_name(DMNSN_T_BOX), - dmnsn_token_name(token.type)); + dmnsn_token_string(DMNSN_T_BOX), + dmnsn_token_string(token.type)); goto bailout; } break; @@ -223,7 +223,7 @@ dmnsn_parse(const dmnsn_array *tokens) default: dmnsn_diagnostic(token.filename, token.line, token.col, "Unexpected token '%s'", - dmnsn_token_name(token.type)); + dmnsn_token_string(token.type)); goto bailout; } } @@ -263,7 +263,83 @@ dmnsn_delete_astree(dmnsn_array *astree) } } +static void +dmnsn_print_astnode(FILE *file, dmnsn_astnode astnode) +{ + double dvalue; + + switch (astnode.type) { + case DMNSN_AST_FLOAT: + dvalue = *(double *)astnode.ptr; + fprintf(file, "(%s %g)", dmnsn_astnode_string(astnode.type), dvalue); + break; + + default: + fprintf(file, "%s", dmnsn_astnode_string(astnode.type)); + } +} + +static void +dmnsn_print_astree(FILE *file, dmnsn_astnode astnode) +{ + unsigned int i; + dmnsn_astnode child; + + if (astnode.children) { + fprintf(file, "("); + dmnsn_print_astnode(file, astnode); + for (i = 0; i < dmnsn_array_size(astnode.children); ++i) { + dmnsn_array_get(astnode.children, i, &child); + fprintf(file, " "); + dmnsn_print_astree(file, child); + } + fprintf(file, ")"); + } else { + dmnsn_print_astnode(file, astnode); + } +} + void -dmnsn_print_astree_sexpr(FILE *file, const dmnsn_array *tokens) +dmnsn_print_astree_sexpr(FILE *file, const dmnsn_array *astree) { + dmnsn_astnode astnode; + unsigned int i; + + if (dmnsn_array_size(astree) == 0) { + fprintf(file, "()"); + } else { + fprintf(file, "("); + dmnsn_array_get(astree, 0, &astnode); + dmnsn_print_astree(file, astnode); + + for (i = 1; i < dmnsn_array_size(astree); ++i) { + fprintf(file, " "); + dmnsn_array_get(astree, i, &astnode); + dmnsn_print_astree(file, astnode); + } + + fprintf(file, ")"); + } + + fprintf(file, "\n"); +} + +const char * +dmnsn_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_BOX, "box"); + dmnsn_astnode_map(DMNSN_AST_VECTOR, "vector"); + dmnsn_astnode_map(DMNSN_AST_FLOAT, "float"); + + default: + fprintf(stderr, "Warning: unrecognised astnode type %d.\n", + (int)astnode_type); + return "unrecognized-astnode"; + } } diff --git a/dimension/parse.h b/dimension/parse.h index aa6ee58..0b818bf 100644 --- a/dimension/parse.h +++ b/dimension/parse.h @@ -44,4 +44,7 @@ dmnsn_array *dmnsn_parse(const dmnsn_array *tokens); void dmnsn_delete_astree(dmnsn_array *astree); /* Print an S-expression of the abstract syntax tree to `file' */ -void dmnsn_print_astree_sexpr(FILE *file, const dmnsn_array *tokens); +void dmnsn_print_astree_sexpr(FILE *file, const dmnsn_array *astree); + +/* Returns a readable name for a token type (ex. DMNSN_T_FLOAT -> float) */ +const char *dmnsn_astnode_string(dmnsn_astnode_type astnode_type); diff --git a/dimension/tokenize.c b/dimension/tokenize.c index acd48f5..94543f1 100644 --- a/dimension/tokenize.c +++ b/dimension/tokenize.c @@ -1043,19 +1043,19 @@ dmnsn_delete_tokens(dmnsn_array *tokens) } static void -dmnsn_print_token(FILE *file, const dmnsn_token *token) +dmnsn_print_token(FILE *file, dmnsn_token token) { const char *tname; - if (token->type == DMNSN_T_LPAREN) { + if (token.type == DMNSN_T_LPAREN) { tname = "\\("; - } else if (token->type == DMNSN_T_RPAREN) { + } else if (token.type == DMNSN_T_RPAREN) { tname = "\\)"; } else { - tname = dmnsn_token_name(token->type); + tname = dmnsn_token_string(token.type); } - if (token->value) { - fprintf(file, "(%s \"%s\")", tname, token->value); + if (token.value) { + fprintf(file, "(%s \"%s\")", tname, token.value); } else { fprintf(file, "%s", tname); } @@ -1072,12 +1072,12 @@ dmnsn_print_token_sexpr(FILE *file, const dmnsn_array *tokens) } else { fprintf(file, "("); dmnsn_array_get(tokens, 0, &token); - dmnsn_print_token(file, &token); + dmnsn_print_token(file, token); for (i = 1; i < dmnsn_array_size(tokens); ++i) { fprintf(file, " "); dmnsn_array_get(tokens, i, &token); - dmnsn_print_token(file, &token); + dmnsn_print_token(file, token); } fprintf(file, ")"); @@ -1087,7 +1087,7 @@ dmnsn_print_token_sexpr(FILE *file, const dmnsn_array *tokens) } const char * -dmnsn_token_name(dmnsn_token_type token_type) +dmnsn_token_string(dmnsn_token_type token_type) { switch (token_type) { /* Macro to shorten this huge switch */ diff --git a/dimension/tokenize.h b/dimension/tokenize.h index 894ee13..4eb1109 100644 --- a/dimension/tokenize.h +++ b/dimension/tokenize.h @@ -535,4 +535,4 @@ void dmnsn_delete_tokens(dmnsn_array *tokens); void dmnsn_print_token_sexpr(FILE *file, const dmnsn_array *tokens); /* Returns a readable name for a token type (ex. DMNSN_T_FLOAT -> float) */ -const char *dmnsn_token_name(dmnsn_token_type token_type); +const char *dmnsn_token_string(dmnsn_token_type token_type); diff --git a/tests/dimension/box.sh b/tests/dimension/box.sh index 244b6fa..7a9f754 100755 --- a/tests/dimension/box.sh +++ b/tests/dimension/box.sh @@ -19,4 +19,14 @@ # along with this program. If not, see . # ######################################################################### +box=$(${top_builddir}/dimension/dimension --tokenize --parse ${srcdir}/box.pov) +box_exp='(box { < - (float "0.125") , - (integer "1") , - (integer "1") > , < (float "0.125") , (integer "1") , (integer "1") > } box { < - (integer "1") , - (integer "1") , - (float "0.125") > , < (integer "1") , (integer "1") , (float "0.125") > }) +((box (vector (float -0.125) (float -1) (float -1)) (vector (float 0.125) (float 1) (float 1))) (box (vector (float -1) (float -1) (float -0.125)) (vector (float 1) (float 1) (float 0.125))))' + +if [ "$box" != "$box_exp" ]; then + echo "box.pov parsed as \"$box\"" >&2 + echo " -- expected \"$box_exp\"" >&2 + exit 1 +fi + ${top_builddir}/dimension/dimension -o box.png ${srcdir}/box.pov -- cgit v1.2.3