summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dimension/directives.rules17
-rw-r--r--dimension/tokenize.c236
-rw-r--r--tests/dimension/directives.pov9
-rwxr-xr-xtests/dimension/directives.sh8
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")