There are two changes:
- instead of calling fpvm_do_assign directly, use a callback
- support for pre_frame, per_vertex, and per_pixel prefixes
---
 src/compiler/fpvm.c          |   31 +++++++++++++++++++++++++++----
 src/compiler/parser.y        |   31 ++++++++++++++++++++++++++-----
 src/compiler/parser_helper.c |    2 +-
 src/compiler/parser_helper.h |   16 ++++++++++++----
 src/compiler/parser_itf.h    |    2 +-
 src/compiler/ptest/ptest.c   |   30 ++++++++++++++++++++----------
 src/compiler/scanner.re      |    4 ++++
 src/compiler/test/prefix     |   33 +++++++++++++++++++++++++++++++++
 8 files changed, 124 insertions(+), 25 deletions(-)
 create mode 100755 src/compiler/test/prefix

diff --git a/src/compiler/fpvm.c b/src/compiler/fpvm.c
index 3bdd701..fa1187d 100644
--- a/src/compiler/fpvm.c
+++ b/src/compiler/fpvm.c
@@ -17,6 +17,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include <fpvm/fpvm.h>
 #include <fpvm/ast.h>
@@ -46,7 +47,7 @@ void fpvm_init(struct fpvm_fragment *fragment, int 
vector_mode)
 int fpvm_assign(struct fpvm_fragment *fragment, const char *dest,
     const char *expr)
 {
-       union parser_comm comm;
+       struct parser_comm comm;
        const char *error;
        int res;
 
@@ -59,16 +60,38 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char 
*dest,
 
        dest = unique(dest);
 
-       res = fpvm_do_assign(fragment, dest, comm.parseout);
-       fpvm_parse_free(comm.parseout);
+       res = fpvm_do_assign(fragment, dest, comm.u.parseout);
+       fpvm_parse_free(comm.u.parseout);
 
        return res;
 }
 
 
+static const char *assign_default(struct parser_comm *comm,
+    const char *label, struct ast_node *node)
+{
+       if(fpvm_do_assign(comm->u.fragment, label, node))
+               return NULL;
+       else
+               return strdup(fpvm_get_last_error(comm->u.fragment));
+}
+
+
+static const char *assign_unsupported(struct parser_comm *comm,
+    const char *label, struct ast_node *node)
+{
+       return strdup("assignment mode not supported yet");
+}
+
+
 int fpvm_chunk(struct fpvm_fragment *fragment, const char *chunk)
 {
-       union parser_comm comm = { .fragment = fragment };
+       struct parser_comm comm = {
+               .u.fragment = fragment,
+               .assign_default = assign_default,
+               .assign_per_frame = assign_unsupported,
+               .assign_per_vertex = assign_unsupported,
+       };
        const char *error;
 
        error = fpvm_parse(chunk, TOK_START_ASSIGN, &comm);
diff --git a/src/compiler/parser.y b/src/compiler/parser.y
index 2875fd5..6363cc6 100644
--- a/src/compiler/parser.y
+++ b/src/compiler/parser.y
@@ -31,6 +31,9 @@
        struct yyParser;
        static void yy_parse_failed(struct yyParser *yypParser);
 
+       typedef const char *(*assign_callback)(struct parser_comm *comm,
+           const char *label, struct ast_node *node);
+
        const enum ast_op tok2op[] = {
                [TOK_IDENT]     = op_ident,
                [TOK_CONSTANT]  = op_constant,
@@ -95,13 +98,16 @@
 
 %type node {struct ast_node *}
 %destructor node { free($$); }
+
+%type context {assign_callback}
+
 %syntax_error {
        syntax_error(state);
        yy_parse_failed(yypParser);
 }
 
 start ::= TOK_START_EXPR node(N). {
-       state->comm->parseout = N;
+       state->comm->u.parseout = N;
        state->success = 1;
 }
 
@@ -113,10 +119,9 @@ assignments ::= assignments assignment.
 
 assignments ::= .
 
-assignment ::= ident(I) TOK_ASSIGN node(N) opt_semi. {
-       if(!fpvm_do_assign(state->comm->fragment, I->label, N)) {
-               state->error =
-                   strdup(fpvm_get_last_error(state->comm->fragment));
+assignment ::= context(C) ident(I) TOK_ASSIGN node(N) opt_semi. {
+       state->error = C(state->comm, I->label, N);
+       if(state->error) {
                syntax_error(state);
                yy_parse_failed(yypParser);
                return;
@@ -124,6 +129,22 @@ assignment ::= ident(I) TOK_ASSIGN node(N) opt_semi. {
        fpvm_parse_free(N);
 }
 
+context(C) ::= . {
+       C = state->comm->assign_default;
+}
+
+context(C) ::= TOK_PER_FRAME TOK_ASSIGN. {
+       C = state->comm->assign_per_frame;
+}
+
+context(C) ::= TOK_PER_VERTEX TOK_ASSIGN. {
+       C = state->comm->assign_per_vertex;
+}
+
+context(C) ::= TOK_PER_PIXEL TOK_ASSIGN. {
+       C = state->comm->assign_per_vertex;
+}
+
 opt_semi ::= opt_semi TOK_SEMI.
 
 opt_semi ::= .
diff --git a/src/compiler/parser_helper.c b/src/compiler/parser_helper.c
index 4976e85..a7824a0 100644
--- a/src/compiler/parser_helper.c
+++ b/src/compiler/parser_helper.c
@@ -64,7 +64,7 @@ static const char *alloc_printf(const char *fmt, ...)
 }
 
 const char *fpvm_parse(const char *expr, int start_token,
-    union parser_comm *comm)
+    struct parser_comm *comm)
 {
        struct scanner *s;
        struct parser_state state = {
diff --git a/src/compiler/parser_helper.h b/src/compiler/parser_helper.h
index 8b4babe..a139da2 100644
--- a/src/compiler/parser_helper.h
+++ b/src/compiler/parser_helper.h
@@ -21,13 +21,21 @@
 #include <fpvm/ast.h>
 #include <fpvm/fpvm.h>
 
-union parser_comm {
-       struct ast_node *parseout;
-       struct fpvm_fragment *fragment;
+struct parser_comm {
+       union {
+               struct ast_node *parseout;
+               struct fpvm_fragment *fragment;
+       } u;
+       const char *(*assign_default)(struct parser_comm *comm,
+           const char *label, struct ast_node *node);
+       const char *(*assign_per_frame)(struct parser_comm *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 *fpvm_parse(const char *expr, int start_token,
-    union parser_comm *comm);
+    struct parser_comm *comm);
 void fpvm_parse_free(struct ast_node *node);
 
 #endif /* __PARSER_HELPER_H */
diff --git a/src/compiler/parser_itf.h b/src/compiler/parser_itf.h
index 57c84c1..a3cd934 100644
--- a/src/compiler/parser_itf.h
+++ b/src/compiler/parser_itf.h
@@ -34,7 +34,7 @@ struct id {
 
 struct parser_state {
        int success;
-       union parser_comm *comm;
+       struct parser_comm *comm;
        const char *error;      /* malloc'ed error message or NULL */
        const char *error_label;/* details about the failing token */
        int error_lineno;
diff --git a/src/compiler/ptest/ptest.c b/src/compiler/ptest/ptest.c
index c89fc68..7a005f5 100644
--- a/src/compiler/ptest/ptest.c
+++ b/src/compiler/ptest/ptest.c
@@ -141,19 +141,24 @@ const char *fpvm_get_last_error(struct fpvm_fragment 
*fragment)
 }
 
 
-int fpvm_do_assign(struct fpvm_fragment *fragment, const char *dest,
-    struct ast_node *ast)
+static const char *assign_default(struct parser_comm *comm,
+    const char *label, struct ast_node *node)
 {
-       if (fail) {
-               snprintf(fragment->last_error, FPVM_MAXERRLEN, "%s", fail);
-               return 0;
-       }
+       if (fail)
+               return strdup(fail);
        if (!quiet) {
-               printf("%s = ", dest);
-               dump_ast(ast);
+               printf("%s = ", label);
+               dump_ast(node);
                putchar('\n');
        }
-       return 1;
+       return NULL;
+}
+
+
+static const char *assign_unsupported(struct parser_comm *comm,
+    const char *label, struct ast_node *node)
+{
+       return strdup("assignment mode not supported yet");
 }
 
 
@@ -199,7 +204,12 @@ int main(int argc, char **argv)
        int c;
        const char *buf;
        struct fpvm_fragment fragment;
-       union parser_comm comm = { .fragment = &fragment };
+       struct parser_comm comm = {
+               .u.fragment = &fragment,
+               .assign_default = assign_default,
+               .assign_per_frame = assign_unsupported,
+               .assign_per_vertex = assign_unsupported,
+        };
        const char *error;
 
        while ((c = getopt(argc, argv, "f:q")) != EOF)
diff --git a/src/compiler/scanner.re b/src/compiler/scanner.re
index af15c18..60e0fca 100644
--- a/src/compiler/scanner.re
+++ b/src/compiler/scanner.re
@@ -109,6 +109,10 @@ int scan(struct scanner *s)
                "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; }
diff --git a/src/compiler/test/prefix b/src/compiler/test/prefix
new file mode 100755
index 0000000..518764a
--- /dev/null
+++ b/src/compiler/test/prefix
@@ -0,0 +1,33 @@
+#!/bin/sh
+. ./Common
+
+# WORK IN PROGRESS
+
+###############################################################################
+
+ptest_fail "prefix: per_frame=x = a+b" <<EOF
+per_frame=x = a+b
+EOF
+expect <<EOF
+FPVM, line 1, near "b": assignment mode not supported yet
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "prefix: per_vertex= x = a+b" <<EOF
+per_vertex = x = a+b
+EOF
+expect <<EOF
+FPVM, line 1, near "b": assignment mode not supported yet
+EOF
+
+#------------------------------------------------------------------------------
+
+ptest_fail "prefix: per_pixel=x = a+b" <<EOF
+per_pixel=x = a+b
+EOF
+expect <<EOF
+FPVM, line 1, near "b": assignment mode not supported yet
+EOF
+
+###############################################################################
-- 
1.7.1

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

Reply via email to