From 7eef42c72cc172a1ed8087e842905f42e737131d Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 5 Feb 2010 11:58:41 -0500 Subject: "Support" the #version directive. --- dimension/common.rules | 2 +- dimension/common.terminals | 2 +- dimension/directives.rules | 7 +++++ dimension/lexer.l | 1 + dimension/tokenize.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 2 deletions(-) (limited to 'dimension') diff --git a/dimension/common.rules b/dimension/common.rules index 61c0bfd..0bf2557 100644 --- a/dimension/common.rules +++ b/dimension/common.rules @@ -450,7 +450,7 @@ COLOR_KEYWORD_ITEM: "identifier" { if (!symbol) { dmnsn_diagnostic(@1.first_filename, @1.first_line, @1.first_column, - "unbound identifier '%s'", $1); + "Unbound identifier '%s'", $1); free($1); YYERROR; } else if (symbol->type != DMNSN_AST_COLOR) { diff --git a/dimension/common.terminals b/dimension/common.terminals index eaeeba3..9da3b42 100644 --- a/dimension/common.terminals +++ b/dimension/common.terminals @@ -513,7 +513,7 @@ %token DMNSN_T_STATISTICS %token DMNSN_T_SWITCH %token DMNSN_T_UNDEF "#undef" -%token DMNSN_T_VERSION +%token DMNSN_T_VERSION "#version" %token DMNSN_T_WARNING %token DMNSN_T_WHILE "#while" %token DMNSN_T_WRITE diff --git a/dimension/directives.rules b/dimension/directives.rules index 4fa77df..eb03df4 100644 --- a/dimension/directives.rules +++ b/dimension/directives.rules @@ -42,6 +42,13 @@ LANGUAGE_DIRECTIVE: "#declare" "identifier" "=" RVALUE { dmnsn_new_ast_integer(node ? 0 : 1)); free($3); } + | "#version" FLOAT ";" { + dmnsn_diagnostic(@$.first_filename, @$.first_line, + @$.first_column, + "WARNING: POV-Ray #version" + " backwards-compatibility not supported"); + dmnsn_delete_astnode($2); + } RVALUE: ARITH_EXPR ";" %dprec 2 { $$ = dmnsn_eval($1, symtable); diff --git a/dimension/lexer.l b/dimension/lexer.l index 953ef9b..90c4807 100644 --- a/dimension/lexer.l +++ b/dimension/lexer.l @@ -216,6 +216,7 @@ unsigned long wchar; "#include" RETURN_TOKEN(DMNSN_T_INCLUDE); "#local" RETURN_TOKEN(DMNSN_T_LOCAL); "#undef" RETURN_TOKEN(DMNSN_T_UNDEF); +"#version" RETURN_TOKEN(DMNSN_T_VERSION); "#while" RETURN_TOKEN(DMNSN_T_WHILE); (?# Identifiers) diff --git a/dimension/tokenize.c b/dimension/tokenize.c index 5d18eea..63435c9 100644 --- a/dimension/tokenize.c +++ b/dimension/tokenize.c @@ -381,6 +381,50 @@ dmnsn_while_buffer(int token, dmnsn_token_buffer *prev, return tbuffer; } +static dmnsn_token_buffer * +dmnsn_version_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); + + /* Buffer the current token */ + dmnsn_buffered_token buffered = { + .type = token, + .lval = *lvalp, + .lloc = *llocp + }; + dmnsn_array_push(tbuffer->buffered, &buffered); + + while (buffered.type != DMNSN_T_SEMICOLON) { + /* Recursive call */ + buffered.type = dmnsn_yylex(&buffered.lval, &buffered.lloc, + filename, symtable, yyscanner); + + if (buffered.type == DMNSN_T_EOF) { + dmnsn_diagnostic(filename, buffered.lloc.first_line, + buffered.lloc.first_column, + "syntax error, unexpected end-of-file"); + dmnsn_delete_token_buffer(tbuffer); + return NULL; + } else if (buffered.type == DMNSN_T_LEX_ERROR) { + dmnsn_delete_token_buffer(tbuffer); + return NULL; + } + + dmnsn_array_push(tbuffer->buffered, &buffered); + } + + /* 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); @@ -533,6 +577,28 @@ dmnsn_yylex(dmnsn_parse_item *lvalp, dmnsn_parse_location *llocp, continue; } + case DMNSN_T_VERSION: + { + dmnsn_token_buffer *tb = dmnsn_version_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; } -- cgit v1.2.3