This was tricky: since file names are bare and can contain all kinds of
special characters and keywords, we need to switch the scanner into a
different mode, which is a little awkward with re2c.
---
 src/Makefile                 |    2 +-
 src/compiler/parser.y        |   10 ++++
 src/compiler/parser_helper.c |   12 ++++-
 src/compiler/parser_helper.h |    2 +
 src/compiler/ptest/Makefile  |    2 +-
 src/compiler/ptest/ptest.c   |    9 +++
 src/compiler/scanner.h       |   10 ++++
 src/compiler/scanner.re      |  124 ++++++++++++++++++++++++++----------------
 src/compiler/test/image      |   69 +++++++++++++++++++++++
 9 files changed, 188 insertions(+), 52 deletions(-)
 create mode 100755 src/compiler/test/image

diff --git a/src/Makefile b/src/Makefile
index 151b250..50e2c56 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -77,7 +77,7 @@ bandfilters.h: bandfilters.sce
        scilab -nw -nwni -nogui -nb -f bandfilters.sce
 
 %.c: %.re
-       re2c -o $@ $<
+       re2c -c -o $@ $<
 
 %.c: %.y
        lemon $<
diff --git a/src/compiler/parser.y b/src/compiler/parser.y
index 6363cc6..3fe25df 100644
--- a/src/compiler/parser.y
+++ b/src/compiler/parser.y
@@ -129,6 +129,16 @@ assignment ::= context(C) ident(I) TOK_ASSIGN node(N) 
opt_semi. {
        fpvm_parse_free(N);
 }
 
+assignment ::= TOK_IMAGEFILE(I) TOK_ASSIGN TOK_FNAME(N). {
+       state->error = state->comm->assign_image_name(state->comm,
+           atoi(I->label+9), N->label);
+       if(state->error) {
+               syntax_error(state);
+               yy_parse_failed(yypParser);
+               return;
+       }
+}
+
 context(C) ::= . {
        C = state->comm->assign_default;
 }
diff --git a/src/compiler/parser_helper.c b/src/compiler/parser_helper.c
index a7824a0..79c6c9b 100644
--- a/src/compiler/parser_helper.c
+++ b/src/compiler/parser_helper.c
@@ -87,12 +87,20 @@ const char *fpvm_parse(const char *expr, int start_token,
                identifier = malloc(sizeof(struct id));
                identifier->token = tok;
                identifier->lineno = s->lineno;
-               if(tok == TOK_CONSTANT) {
+
+               switch(tok) {
+               case TOK_CONSTANT:
                        identifier->constant = get_constant(s);
                        identifier->label = "";
-               } else {
+                       break;
+               case TOK_FNAME:
                        identifier->label = get_token(s);
+                       break;
+               default:
+                       identifier->label = get_unique_token(s);
+                       break;
                }
+
                state.id = identifier;
                if(tok == TOK_ERROR) {
                        error = alloc_printf(
diff --git a/src/compiler/parser_helper.h b/src/compiler/parser_helper.h
index a139da2..7315cb4 100644
--- a/src/compiler/parser_helper.h
+++ b/src/compiler/parser_helper.h
@@ -32,6 +32,8 @@ struct parser_comm {
            const char *label, struct ast_node *node);
        const char *(*assign_per_vertex)(struct parser_comm *comm,
            const char *label, struct ast_node *node);
+       const char *(*assign_image_name)(struct parser_comm *comm,
+           int number, const char *name);
 };
 
 const char *fpvm_parse(const char *expr, int start_token,
diff --git a/src/compiler/ptest/Makefile b/src/compiler/ptest/Makefile
index b3a463e..1ad5692 100644
--- a/src/compiler/ptest/Makefile
+++ b/src/compiler/ptest/Makefile
@@ -37,7 +37,7 @@ ptest:                $(OBJS)
                $(CC) $(CFLAGS) -c -o $@ $<
 
 %.c:           %.re
-               $(GEN) re2c -o $@ $<
+               $(GEN) re2c -c -o $@ $<
 
 %.c:           %.y
                $(GEN) lemon $<
diff --git a/src/compiler/ptest/ptest.c b/src/compiler/ptest/ptest.c
index 7a005f5..c662625 100644
--- a/src/compiler/ptest/ptest.c
+++ b/src/compiler/ptest/ptest.c
@@ -162,6 +162,14 @@ static const char *assign_unsupported(struct parser_comm 
*comm,
 }
 
 
+static const char *assign_image_name(struct parser_comm *comm,
+    int number, const char *name)
+{
+       if (!quiet)
+               printf("image %d = \"%s\"\n", number, name);
+       return NULL;
+}
+
 static const char *read_stdin(void)
 {
        char *buf = NULL;
@@ -209,6 +217,7 @@ int main(int argc, char **argv)
                .assign_default = assign_default,
                .assign_per_frame = assign_unsupported,
                .assign_per_vertex = assign_unsupported,
+               .assign_image_name = assign_image_name,
         };
        const char *error;
 
diff --git a/src/compiler/scanner.h b/src/compiler/scanner.h
index d41b0c1..aa0226a 100644
--- a/src/compiler/scanner.h
+++ b/src/compiler/scanner.h
@@ -23,7 +23,14 @@
 
 #include "parser.h"
 
+enum scanner_cond {
+       yycN = 1,
+       yycFNAME1,
+       yycFNAME2,
+};
+
 struct scanner {
+       enum scanner_cond cond;
        unsigned char *marker;
        unsigned char *old_cursor;
        unsigned char *cursor;
@@ -39,6 +46,9 @@ int scan(struct scanner *s);
 
 /* get the unique string comprising the current token
  */
+const char *get_unique_token(struct scanner *s);
+
+/* like get_unique_token, but malloc'ed non-unique string */
 const char *get_token(struct scanner *s);
 
 float get_constant(struct scanner *s);
diff --git a/src/compiler/scanner.re b/src/compiler/scanner.re
index 60e0fca..e478f91 100644
--- a/src/compiler/scanner.re
+++ b/src/compiler/scanner.re
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <malloc.h>
@@ -30,6 +31,10 @@
 #define YYMARKER s->marker
 #define YYFILL(n)
 
+#define        YYCONDTYPE              enum scanner_cond
+#define        YYGETCONDITION()        s->cond
+#define        YYSETCONDITION(c)       s->cond = (c)
+
 struct scanner *new_scanner(unsigned char *input)
 {
        struct scanner *s;
@@ -37,6 +42,7 @@ struct scanner *new_scanner(unsigned char *input)
        s = malloc(sizeof(struct scanner));
        if(s == NULL) return NULL;
 
+       s->cond = yycN;
        s->marker = input;
        s->old_cursor = input;
        s->cursor = input;
@@ -73,68 +79,90 @@ int scan(struct scanner *s)
        s->old_cursor = s->cursor;
 
        /*!re2c
-               [\x20\r\t]              { goto std; }
-               "\n"                    { s->lineno++;
+               <*>[\x20\r\t]           { goto std; }
+               <*>"\n"                 { s->lineno++;
+                                         YYSETCONDITION(yycN);
                                          goto std; }
 
-               "//"[^\n\x00]*          { goto std; }
-               "/*"([^*\x00]|("*"+([^*/\x00])))*"*"+"/"
+               <N>"//"[^\n\x00]*       { goto std; }
+               <N>"/*"([^*\x00]|("*"+([^*/\x00])))*"*"+"/"
                                        { s->lineno += nls(s->old_cursor,
                                              s->cursor);
                                          goto std; }
 
-               "[preset]"              { goto std; }
-
-               [0-9]+                  { return TOK_CONSTANT; }
-               [0-9]+ "." [0-9]*       { return TOK_CONSTANT; }
-               [0-9]* "." [0-9]+       { return TOK_CONSTANT; }
-
-               "above"                 { return TOK_ABOVE; }
-               "abs"                   { return TOK_ABS; }
-               "below"                 { return TOK_BELOW; }
-               "cos"                   { return TOK_COS; }
-               "equal"                 { return TOK_EQUAL; }
-               "f2i"                   { return TOK_F2I; }
-               "icos"                  { return TOK_ICOS; }
-               "i2f"                   { return TOK_I2F; }
-               "if"                    { return TOK_IF; }
-               "int"                   { return TOK_INT; }
-               "invsqrt"               { return TOK_INVSQRT; }
-               "isin"                  { return TOK_ISIN; }
-               "max"                   { return TOK_MAX; }
-               "min"                   { return TOK_MIN; }
-               "quake"                 { return TOK_QUAKE; }
-               "sin"                   { return TOK_SIN; }
-               "sqr"                   { return TOK_SQR; }
-               "sqrt"                  { return TOK_SQRT; }
-               "tsign"                 { return TOK_TSIGN; }
-
-               "per_frame"             { return TOK_PER_FRAME; }
-               "per_vertex"            { return TOK_PER_VERTEX; }
-               "per_pixel"             { return TOK_PER_PIXEL; }
-
-               [a-zA-Z_0-9]+           { return TOK_IDENT; }
-
-               "+"                     { return TOK_PLUS; }
-               "-"                     { return TOK_MINUS; }
-               "*"                     { return TOK_MULTIPLY; }
-               "/"                     { return TOK_DIVIDE; }
-               "%"                     { return TOK_PERCENT; }
-               "("                     { return TOK_LPAREN; }
-               ")"                     { return TOK_RPAREN; }
-               ","                     { return TOK_COMMA; }
-               "="                     { return TOK_ASSIGN; }
-               ";"                     { return TOK_SEMI; }
-               [\x00-\xff]             { return TOK_ERROR; }
+               <N>"[preset]"           { goto std; }
+
+               <N>[0-9]+               { return TOK_CONSTANT; }
+               <N>[0-9]+ "." [0-9]*    { return TOK_CONSTANT; }
+               <N>[0-9]* "." [0-9]+    { return TOK_CONSTANT; }
+
+               <N>"above"              { return TOK_ABOVE; }
+               <N>"abs"                { return TOK_ABS; }
+               <N>"below"              { return TOK_BELOW; }
+               <N>"cos"                { return TOK_COS; }
+               <N>"equal"              { return TOK_EQUAL; }
+               <N>"f2i"                { return TOK_F2I; }
+               <N>"icos"               { return TOK_ICOS; }
+               <N>"i2f"                { return TOK_I2F; }
+               <N>"if"                 { return TOK_IF; }
+               <N>"int"                { return TOK_INT; }
+               <N>"invsqrt"            { return TOK_INVSQRT; }
+               <N>"isin"               { return TOK_ISIN; }
+               <N>"max"                { return TOK_MAX; }
+               <N>"min"                { return TOK_MIN; }
+               <N>"quake"              { return TOK_QUAKE; }
+               <N>"sin"                { return TOK_SIN; }
+               <N>"sqr"                { return TOK_SQR; }
+               <N>"sqrt"               { return TOK_SQRT; }
+               <N>"tsign"              { return TOK_TSIGN; }
+
+               <N>"per_frame"          { return TOK_PER_FRAME; }
+               <N>"per_vertex"         { return TOK_PER_VERTEX; }
+               <N>"per_pixel"          { return TOK_PER_PIXEL; }
+
+               <N>"imagefile"[1-9]     { YYSETCONDITION(yycFNAME1);
+                                         return TOK_IMAGEFILE; }
+
+               <N>[a-zA-Z_0-9]+        { return TOK_IDENT; }
+
+               <N>"+"                  { return TOK_PLUS; }
+               <N>"-"                  { return TOK_MINUS; }
+               <N>"*"                  { return TOK_MULTIPLY; }
+               <N>"/"                  { return TOK_DIVIDE; }
+               <N>"%"                  { return TOK_PERCENT; }
+               <N>"("                  { return TOK_LPAREN; }
+               <N>")"                  { return TOK_RPAREN; }
+               <N>","                  { return TOK_COMMA; }
+               <N,FNAME1>"="           { if (YYGETCONDITION() == yycFNAME1)
+                                               YYSETCONDITION(yycFNAME2);
+                                         return TOK_ASSIGN; }
+               <N>";"                  { return TOK_SEMI; }
+
+               <FNAME2>[^ \x00\n\r\t]|[^ \x00\n\r\t][^\n\x00]*[^ \x00\n\r\t]
+                                       { return TOK_FNAME; }
+
+               <*>[\x00-\xff]          { return TOK_ERROR; }
        */
 }
 
-const char *get_token(struct scanner *s)
+const char *get_unique_token(struct scanner *s)
 {
        return unique_n((const char *) s->old_cursor,
            s->cursor - s->old_cursor);
 }
 
+const char *get_token(struct scanner *s)
+{
+       char *buf;
+       int n;
+
+       n = s->cursor - s->old_cursor;
+       buf = malloc(n+1);
+       memcpy(buf, s->old_cursor, n);
+       buf[n] = 0;
+       return buf;
+}
+
 float get_constant(struct scanner *s)
 {
        const unsigned char *p;
diff --git a/src/compiler/test/image b/src/compiler/test/image
new file mode 100755
index 0000000..b410224
--- /dev/null
+++ b/src/compiler/test/image
@@ -0,0 +1,69 @@
+#!/bin/sh
+. ./Common
+
+# WORK IN PROGRESS
+
+###############################################################################
+
+ptest "image: imagefile1=hello" <<EOF
+imagefile1=hello
+EOF
+expect <<EOF
+image 1 = "hello"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile2 = hello" <<EOF
+imagefile2 = hello
+EOF
+expect <<EOF
+image 2 = "hello"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile1 = hel lo" <<EOF
+imagefile1 = hel lo
+EOF
+expect <<EOF
+image 1 = "hel lo"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile2 = hel<nl>lo" <<EOF
+imagefile2 = hel
+lo = u
+EOF
+expect <<EOF
+image 2 = "hel"
+lo = u
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile1 = foo<spc><spc>" "imagefile1 = foo  "
+expect <<EOF
+image 1 = "foo"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile2 = /dev/null" <<EOF
+imagefile2 = /dev/null
+EOF
+expect <<EOF
+image 2 = "/dev/null"
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest "image: imagefile1 = *** test  -  robust & ness ***" <<EOF
+imagefile1 = *** test  -  robust & ness ***
+EOF
+expect <<EOF
+image 1 = "*** test  -  robust & ness ***"
+EOF
+
+###############################################################################
-- 
1.7.1

_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode

Reply via email to