---
src/Makefile | 2 +-
src/compiler/compiler.c | 248 +++++++++++++-----------------------------
src/compiler/parser_helper.h | 3 +
3 files changed, 82 insertions(+), 171 deletions(-)
diff --git a/src/Makefile b/src/Makefile
index 50e2c56..e4260d3 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -94,7 +94,7 @@ obj/compiler/scanner.o: compiler/parser.h
obj/compiler/parser_helper.o: compiler/parser.h
obj/compiler/fpvm.o: compiler/parser.h
obj/compiler/unique.o: compiler/fnp.inc
-obj/compiler/compiler.o: compiler/infra-fnp.h
+obj/compiler/compiler.o: compiler/infra-fnp.h compiler/parser.h
# boot images for Milkymist One
$(BINDIR)/flickernoise.bin: $(BINDIR)/flickernoise
diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c
index b907c56..1b8146c 100644
--- a/src/compiler/compiler.c
+++ b/src/compiler/compiler.c
@@ -29,6 +29,8 @@
#include "../pixbuf/pixbuf.h"
#include "fpvm.h"
#include "unique.h"
+#include "parser_helper.h"
+#include "parser.h"
#include "compiler.h"
#include "infra-fnp.h"
@@ -326,16 +328,6 @@ static bool schedule_pfv(struct compiler_sc *sc)
return true;
}
-static bool add_per_frame(struct compiler_sc *sc, char *dest, char *val)
-{
- if(!fpvm_assign(&sc->pfv_fragment, dest, val)) {
- comp_report(sc, "failed to add per-frame equation l. %d: %s",
- sc->linenr, fpvm_get_last_error(&sc->pfv_fragment));
- return false;
- }
- return true;
-}
-
/****************************************************************/
/* PER-VERTEX VARIABLES */
/****************************************************************/
@@ -498,179 +490,104 @@ static bool schedule_pvv(struct compiler_sc *sc)
return true;
}
-static bool add_per_vertex(struct compiler_sc *sc, char *dest, char *val)
-{
- if(!fpvm_assign(&sc->pvv_fragment, dest, val)) {
- comp_report(sc, "failed to add per-vertex equation l. %d: %s\n",
- sc->linenr, fpvm_get_last_error(&sc->pvv_fragment));
- return false;
- }
- return true;
-}
-
/****************************************************************/
/* PARSING */
/****************************************************************/
-static bool process_equation(struct compiler_sc *sc, char *equation,
- bool per_vertex)
+static const char *assign_default(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- char *c, *c2;
-
- c = strchr(equation, '=');
- if(!c) {
- comp_report(sc, "error l.%d: malformed equation (%s)",
- sc->linenr, equation);
- return false;
- }
- *c = 0;
-
- if(*equation == 0) {
- comp_report(sc, "error l.%d: missing lvalue", sc->linenr);
- return false;
+ struct compiler_sc *sc = comm->u.sc;
+ int pfv;
+ float v;
+
+ pfv = pfv_from_name(label);
+ if(pfv < 0)
+ return strdup("unknown parameter");
+
+ switch(node->op) {
+ case op_constant:
+ v = node->contents.constant;
+ break;
+ case op_not:
+ if(node->contents.branches.a->op == op_constant) {
+ v = -node->contents.branches.a->contents.constant;
+ break;
+ }
+ /* fall through */
+ default:
+ return strdup("value must be a constant");
}
- c2 = c - 1;
- while((c2 > equation) && (*c2 == ' ')) *c2-- = 0;
-
- c++;
- while(*c == ' ') c++;
- if(*equation == 0) {
- comp_report(sc, "error l.%d: missing lvalue", sc->linenr);
- return false;
- }
- if(*c == 0) {
- comp_report(sc, "error l.%d: missing rvalue", sc->linenr);
- return false;
- }
+ /* patch initial condition or global parameter */
+ pfv_update_patch_requires(sc, pfv);
+ set_initial(sc, pfv, v);
+ return NULL;
+}
- if(per_vertex)
- return add_per_vertex(sc, equation, c);
+static const char *assign_fragment(struct fpvm_fragment *frag,
+ const char *label, struct ast_node *node)
+{
+ if(fpvm_do_assign(frag, label, node))
+ return NULL;
else
- return add_per_frame(sc, equation, c);
+ return strdup(fpvm_get_last_error(frag));
}
-static bool process_equations(struct compiler_sc *sc, char *equations,
- bool per_vertex)
+static const char *assign_per_frame(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- char *c;
-
- while(*equations) {
- c = strchr(equations, ';');
- if(!c)
- return process_equation(sc, equations, per_vertex);
- *c = 0;
- if(!process_equation(sc, equations, per_vertex)) return false;
- equations = c + 1;
- }
- return true;
+ return assign_fragment(&comm->u.sc->pfv_fragment, label, node);
}
-static bool process_top_assign(struct compiler_sc *sc, char *left, char *right)
+static const char *assign_per_vertex(struct parser_comm *comm,
+ const char *label, struct ast_node *node)
{
- int pfv;
-
- while(*right == ' ') right++;
- if(*right == 0) return true;
-
- if(strncmp(left, "imagefile", 9) == 0) {
- int image_n;
- char *totalname;
-
- image_n = atoi(left+9);
- if((image_n < 1) || (image_n > IMAGE_COUNT)) {
- comp_report(sc, "warning l.%d: ignoring image with out
of bounds number %d",
- sc->linenr, image_n);
- return true;
- }
- image_n--;
- if(right[0] == '/')
- totalname = strdup(right);
- else {
- totalname =
- malloc(strlen(sc->basedir) + strlen(right) + 1);
- if(totalname == NULL) return true;
- strcpy(totalname, sc->basedir);
- strcat(totalname, right);
- }
- pixbuf_dec_ref(sc->p->images[image_n]);
- sc->p->images[image_n] = pixbuf_get(totalname);
- free(totalname);
- return true;
- }
-
- pfv = pfv_from_name(left);
- if(pfv >= 0) {
- /* patch initial condition or global parameter */
- pfv_update_patch_requires(sc, pfv);
- set_initial(sc, pfv, atof(right));
- return true;
- }
-
- if(strncmp(left, "per_frame", 9) == 0)
- /* per-frame equation */
- return process_equations(sc, right, false);
-
- if((strncmp(left, "per_vertex", 10) == 0) ||
- (strncmp(left, "per_pixel", 9) == 0))
- /* per-vertex equation */
- return process_equations(sc, right, true);
-
- comp_report(sc, "warning l.%d: ignoring unknown parameter %s",
- sc->linenr, left);
-
- return true;
+ return assign_fragment(&comm->u.sc->pvv_fragment, label, node);
}
-static bool process_line(struct compiler_sc *sc, char *line)
+static const char *assign_image_name(struct parser_comm *comm,
+ int number, const char *name)
{
- char *c;
-
- while(*line == ' ') line++;
- if(*line == 0) return true;
- if(*line == '[') return true;
-
- c = strstr(line, "//");
- if(c) *c = 0;
-
- c = line + strlen(line) - 1;
- while((c >= line) && (*c == ' ')) *c-- = 0;
- if(*line == 0) return true;
-
- c = strchr(line, '=');
- if(!c) {
- comp_report(sc, "error l.%d: '=' expected", sc->linenr);
- return false;
+ struct compiler_sc *sc = comm->u.sc;
+ char *totalname;
+
+ if(number > IMAGE_COUNT)
+ return strdup("image number out of bounds");
+ number--;
+
+ if(*name == '/')
+ totalname = strdup(name);
+ else {
+ totalname = malloc(strlen(sc->basedir) + strlen(name) + 1);
+ if(totalname == NULL)
+ return strdup("out of memory");
+ strcpy(totalname, sc->basedir);
+ strcat(totalname, name);
}
- *c = 0;
- return process_top_assign(sc, line, c+1);
+ pixbuf_dec_ref(sc->p->images[number]);
+ sc->p->images[number] = pixbuf_get(totalname);
+ free(totalname);
+ return NULL;
}
-static bool parse_patch(struct compiler_sc *sc, char *patch_code)
+static bool parse_patch(struct compiler_sc *sc, const char *patch_code)
{
- char *eol;
-
- while(*patch_code) {
- sc->linenr++;
- eol = strchr(patch_code, '\n');
- if(!eol) {
- if(!process_line(sc, patch_code))
- return false;
- else
- return true;
- }
- *eol = 0;
- if(*patch_code == 0) {
- patch_code = eol + 1;
- continue;
- }
- if(*(eol - 1) == '\r') *(eol - 1) = 0;
- if(!process_line(sc, patch_code))
- return false;
- patch_code = eol + 1;
+ struct parser_comm comm = {
+ .u.sc = sc,
+ .assign_default = assign_default,
+ .assign_per_frame = assign_per_frame,
+ .assign_per_vertex = assign_per_vertex,
+ .assign_image_name = assign_image_name,
+ };
+ const char *error;
+
+ error = fpvm_parse(patch_code, TOK_START_ASSIGN, &comm);
+ if(error) {
+ sc->rmc(error);
+ free((void *) error);
}
-
- return true;
+ return !error;
}
struct patch *patch_compile(const char *basedir, const char *patch_code,
@@ -678,7 +595,6 @@ struct patch *patch_compile(const char *basedir, const char
*patch_code,
{
struct compiler_sc *sc;
struct patch *p;
- char *patch_code_copy;
int i;
sc = malloc(sizeof(struct compiler_sc));
@@ -706,16 +622,8 @@ struct patch *patch_compile(const char *basedir, const
char *patch_code,
if(!init_pfv(sc)) goto fail;
if(!init_pvv(sc)) goto fail;
- patch_code_copy = strdup(patch_code);
- if(patch_code_copy == NULL) {
- rmc("Failed to allocate memory for patch code");
+ if(!parse_patch(sc, patch_code))
goto fail;
- }
- if(!parse_patch(sc, patch_code_copy)) {
- free(patch_code_copy);
- goto fail;
- }
- free(patch_code_copy);
unique_free();
if(!finalize_pfv(sc)) goto fail;
diff --git a/src/compiler/parser_helper.h b/src/compiler/parser_helper.h
index 7315cb4..2cc6300 100644
--- a/src/compiler/parser_helper.h
+++ b/src/compiler/parser_helper.h
@@ -21,10 +21,13 @@
#include <fpvm/ast.h>
#include <fpvm/fpvm.h>
+struct compiler_sc;
+
struct parser_comm {
union {
struct ast_node *parseout;
struct fpvm_fragment *fragment;
+ struct compiler_sc *sc;
} u;
const char *(*assign_default)(struct parser_comm *comm,
const char *label, struct ast_node *node);
--
1.7.1
_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode