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