diff options
-rw-r--r-- | dimension/directives.rules | 17 | ||||
-rw-r--r-- | dimension/tokenize.c | 236 | ||||
-rw-r--r-- | tests/dimension/directives.pov | 9 | ||||
-rwxr-xr-x | tests/dimension/directives.sh | 8 |
4 files changed, 181 insertions, 89 deletions
diff --git a/dimension/directives.rules b/dimension/directives.rules index 48cdd77..6f8a812 100644 --- a/dimension/directives.rules +++ b/dimension/directives.rules @@ -53,6 +53,23 @@ LANGUAGE_DIRECTIVE: "#include" STRING { " backwards-compatibility not supported"); dmnsn_delete_astnode($2); } + | "#debug" STRING { + fprintf(stderr, "%s\n", (const char *)$2.ptr); + dmnsn_delete_astnode($2); + } + | "#warning" STRING { + dmnsn_diagnostic(@$.first_filename, @$.first_line, + @$.first_column, + "WARNING: %s", (const char *)$2.ptr); + dmnsn_delete_astnode($2); + } + | "#error" STRING { + dmnsn_diagnostic(@$.first_filename, @$.first_line, + @$.first_column, + "%s", (const char *)$2.ptr); + dmnsn_delete_astnode($2); + YYERROR; + } RVALUE: ARITH_EXPR ";" %dprec 2 { $$ = dmnsn_eval($1, symtable); diff --git a/dimension/tokenize.c b/dimension/tokenize.c index 4e499d5..e872e0c 100644 --- a/dimension/tokenize.c +++ b/dimension/tokenize.c @@ -84,42 +84,79 @@ dmnsn_yylex_wrapper(dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, int dmnsn_ld_yyparse(const char *filename, void *yyscanner, dmnsn_symbol_table *symtable); -static dmnsn_token_buffer * -dmnsn_include_buffer(int token, dmnsn_token_buffer *prev, - dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, - const char *filename, dmnsn_symbol_table *symtable, - void *yyscanner) +static int +dmnsn_buffer_balanced(dmnsn_token_buffer *tbuffer, bool recursive, + dmnsn_token_type left, dmnsn_token_type right, + const char *filename, dmnsn_symbol_table *symtable, + void *yyscanner) { - dmnsn_token_buffer *include_buffer - = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + dmnsn_buffered_token buffered; - /* Buffer the current token */ - dmnsn_buffered_token buffered = { - .type = token, - .lval = *lvalp, - .lloc = *llocp - }; - dmnsn_array_push(include_buffer->buffered, &buffered); + int nesting = -1; + while (1) { + if (recursive) { + buffered.type = dmnsn_yylex(&buffered.lval, &buffered.lloc, + filename, symtable, yyscanner); + } else { + buffered.type = dmnsn_yylex_wrapper(&buffered.lval, &buffered.lloc, + filename, symtable, yyscanner); + } - /* Recursive call */ - buffered.type = dmnsn_yylex(&buffered.lval, &buffered.lloc, - filename, symtable, yyscanner); + if (buffered.type == DMNSN_T_EOF) { + dmnsn_diagnostic(buffered.lloc.first_filename, buffered.lloc.first_line, + buffered.lloc.first_column, + "syntax error, unexpected end-of-file"); + return 1; + } else if (buffered.type == DMNSN_T_LEX_ERROR) { + return 1; + } + + dmnsn_array_push(tbuffer->buffered, &buffered); + + if (buffered.type == left) { + if (nesting < 0) + nesting = 1; + else + ++nesting; + } else if (buffered.type == right) { + --nesting; + if (nesting == 0) { + break; + } + } + } + + return 0; +} + +static int +dmnsn_buffer_strexp(dmnsn_token_buffer *tbuffer, bool recursive, + const char *filename, dmnsn_symbol_table *symtable, + void *yyscanner) +{ + dmnsn_buffered_token buffered; + + if (recursive) { + buffered.type = dmnsn_yylex(&buffered.lval, &buffered.lloc, + filename, symtable, yyscanner); + } else { + buffered.type = dmnsn_yylex_wrapper(&buffered.lval, &buffered.lloc, + filename, symtable, yyscanner); + } if (buffered.type == DMNSN_T_EOF) { dmnsn_diagnostic(buffered.lloc.first_filename, buffered.lloc.first_line, buffered.lloc.first_column, "syntax error, unexpected end-of-file"); - dmnsn_delete_token_buffer(include_buffer); - return NULL; + return 1; } else if (buffered.type == DMNSN_T_LEX_ERROR) { - dmnsn_delete_token_buffer(include_buffer); - return NULL; + return 1; } - /* Buffer the next token */ - dmnsn_array_push(include_buffer->buffered, &buffered); + /* Buffer the first token */ + dmnsn_array_push(tbuffer->buffered, &buffered); bool is_strexp = buffered.type != DMNSN_T_STRING; - if (is_strexp && buffered.type == DMNSN_T_IDENTIFIER) { + if (buffered.type == DMNSN_T_IDENTIFIER) { /* Check if it's a string identifier or a macro */ dmnsn_astnode *inode = dmnsn_find_symbol(symtable, buffered.lval.value); if (!inode || inode->type == DMNSN_AST_STRING) { @@ -129,37 +166,37 @@ dmnsn_include_buffer(int token, dmnsn_token_buffer *prev, if (is_strexp) { /* Grab all the tokens belonging to the string expression */ - int parenlevel = -1; - while (1) { - /* Recursive call - permit other directives inside the condition */ - buffered.type = dmnsn_yylex(&buffered.lval, &buffered.lloc, - filename, symtable, yyscanner); + return dmnsn_buffer_balanced(tbuffer, recursive, + DMNSN_T_LPAREN, DMNSN_T_RPAREN, + filename, symtable, yyscanner); + } - if (buffered.type == DMNSN_T_EOF) { - dmnsn_diagnostic(buffered.lloc.first_filename, buffered.lloc.first_line, - buffered.lloc.first_column, - "syntax error, unexpected end-of-file"); - dmnsn_delete_token_buffer(include_buffer); - return NULL; - } else if (buffered.type == DMNSN_T_LEX_ERROR) { - dmnsn_delete_token_buffer(include_buffer); - return NULL; - } + return 0; +} - dmnsn_array_push(include_buffer->buffered, &buffered); - - if (buffered.type == DMNSN_T_LPAREN) { - if (parenlevel < 0) - parenlevel = 1; - else - ++parenlevel; - } else if (buffered.type == DMNSN_T_RPAREN) { - --parenlevel; - if (parenlevel == 0) { - break; - } - } - } +static dmnsn_token_buffer * +dmnsn_include_buffer(int token, dmnsn_token_buffer *prev, + dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, + const char *filename, dmnsn_symbol_table *symtable, + void *yyscanner) +{ + dmnsn_token_buffer *include_buffer + = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + + /* Buffer the current token */ + dmnsn_buffered_token buffered = { + .type = token, + .lval = *lvalp, + .lloc = *llocp + }; + dmnsn_array_push(include_buffer->buffered, &buffered); + + /* Buffer the following string expression */ + if (dmnsn_buffer_strexp(include_buffer, true, filename, symtable, yyscanner) + != 0) + { + dmnsn_delete_token_buffer(include_buffer); + return NULL; } /* Fake EOF */ @@ -360,36 +397,12 @@ dmnsn_if_buffer(int token, dmnsn_token_buffer *prev, dmnsn_array_push(cond_buffer->buffered, &buffered); /* Grab all the tokens belonging to the #if (...) */ - int parenlevel = -1; - while (1) { - /* Recursive call - permit other directives inside the condition */ - buffered.type = dmnsn_yylex(&buffered.lval, &buffered.lloc, - filename, symtable, yyscanner); - - if (buffered.type == DMNSN_T_EOF) { - dmnsn_diagnostic(buffered.lloc.first_filename, buffered.lloc.first_line, - buffered.lloc.first_column, - "syntax error, unexpected end-of-file"); - dmnsn_delete_token_buffer(cond_buffer); - return NULL; - } else if (buffered.type == DMNSN_T_LEX_ERROR) { - dmnsn_delete_token_buffer(cond_buffer); - return NULL; - } - - dmnsn_array_push(cond_buffer->buffered, &buffered); - - if (buffered.type == DMNSN_T_LPAREN) { - if (parenlevel < 0) - parenlevel = 1; - else - ++parenlevel; - } else if (buffered.type == DMNSN_T_RPAREN) { - --parenlevel; - if (parenlevel == 0) { - break; - } - } + if (dmnsn_buffer_balanced(cond_buffer, true, DMNSN_T_LPAREN, DMNSN_T_RPAREN, + filename, symtable, yyscanner) + != 0) + { + dmnsn_delete_token_buffer(cond_buffer); + return NULL; } /* Fake EOF */ @@ -586,6 +599,39 @@ dmnsn_version_buffer(int token, dmnsn_token_buffer *prev, return tbuffer; } +static dmnsn_token_buffer * +dmnsn_stream_buffer(int token, dmnsn_token_buffer *prev, + dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, + const char *filename, dmnsn_symbol_table *symtable, + void *yyscanner) +{ + dmnsn_token_buffer *tbuffer + = dmnsn_new_token_buffer(DMNSN_T_LEX_VERBATIM, prev, filename); + + /* Buffer the current token */ + dmnsn_buffered_token buffered = { + .type = token, + .lval = *lvalp, + .lloc = *llocp + }; + dmnsn_array_push(tbuffer->buffered, &buffered); + + /* Buffer the following string expression */ + if (dmnsn_buffer_strexp(tbuffer, true, filename, symtable, yyscanner) + != 0) + { + dmnsn_delete_token_buffer(tbuffer); + return NULL; + } + + /* Fake EOF */ + buffered.type = DMNSN_T_EOF; + buffered.lval.value = NULL; + dmnsn_array_push(tbuffer->buffered, &buffered); + + return tbuffer; +} + int dmnsn_yylex_impl(dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, const char *filename, void *yyscanner); @@ -785,6 +831,30 @@ dmnsn_yylex(dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, break; } + case DMNSN_T_DEBUG: + case DMNSN_T_ERROR: + case DMNSN_T_WARNING: + { + dmnsn_token_buffer *tb = dmnsn_stream_buffer( + token, tbuffer, lvalp, llocp, filename, symtable, yyscanner + ); + if (!tb) { + return DMNSN_T_LEX_ERROR; + } + + dmnsn_yyset_extra(tb, yyscanner); + if (dmnsn_ld_yyparse(filename, yyscanner, symtable) != 0) { + dmnsn_yyset_extra(tb->prev, yyscanner); + dmnsn_delete_token_buffer(tb); + return DMNSN_T_LEX_ERROR; + } + + /* Restore the previous extra pointer */ + dmnsn_yyset_extra(tb->prev, yyscanner); + dmnsn_delete_token_buffer(tb); + break; + } + default: return token; } diff --git a/tests/dimension/directives.pov b/tests/dimension/directives.pov index 75c8a81..5137cd2 100644 --- a/tests/dimension/directives.pov +++ b/tests/dimension/directives.pov @@ -21,6 +21,9 @@ #version 3.6; +#debug "debug" +#warning "warning" + #include "directives.inc" #declare R = 1; @@ -30,17 +33,17 @@ #undef Unused #ifdef (Local) - Illegal + #error "Local escaped from include file" #end #ifdef (Unused) - Illegal + #error "#undef failed" #end #declare Counter = 0; #while (Counter < 2) #if (#if (1 = 1) 0 #end = 0 & 0) - `Illegal + #error "Nested #if parsing failed" #else sphere { Center + <0, Counter, 0>, R diff --git a/tests/dimension/directives.sh b/tests/dimension/directives.sh index 7f15cb5..cf21d8b 100755 --- a/tests/dimension/directives.sh +++ b/tests/dimension/directives.sh @@ -22,21 +22,23 @@ directives=$(${top_builddir}/dimension/dimension --tokenize --parse ${srcdir}/directives.pov) directives_exp="$(echo -n \ '(#version (float "3.6") ; + #debug (string "debug") + #warning (string "warning") #include (string "directives.inc") #declare (identifier "R") = (integer "1") ; #local (identifier "Color") = rgb < (integer "1") , (integer "0") , (integer "1") > ; #declare (identifier "Unused") = - (integer "1") ; #undef (identifier "Unused") #ifdef \( (identifier "Local") \) - (identifier "Illegal") + #error (string "Local escaped from include file") #end #ifdef \( (identifier "Unused") \) - (identifier "Illegal") + #error (string "#undef failed") #end #declare (identifier "Counter") = (integer "0") ; #while \( (identifier "Counter") < (integer "2") \) #if \( #if \( (integer "1") = (integer "1") \) (integer "0") #end = (integer "0") & (integer "0") \) - (error) (identifier "Illegal") + #error (string "Nested #if parsing failed") #else sphere { (identifier "Center") + < (integer "0") , (identifier "Counter") , (integer "0") > , (identifier "R") |