ptest/ allows the FNP parser to run on the host, thus enabling easy
regression testing.
---
src/compiler/Makefile | 9 ++
src/compiler/ptest/Makefile | 63 +++++++++++++
src/compiler/ptest/ptest.c | 211 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 283 insertions(+), 0 deletions(-)
create mode 100644 src/compiler/Makefile
create mode 100644 src/compiler/ptest/Makefile
create mode 100644 src/compiler/ptest/ptest.c
diff --git a/src/compiler/Makefile b/src/compiler/Makefile
new file mode 100644
index 0000000..4090428
--- /dev/null
+++ b/src/compiler/Makefile
@@ -0,0 +1,9 @@
+.PHONY: all clean
+
+all:
+ $(MAKE) -C ptest
+
+# ----- Cleanup ---------------------------------------------------------------
+
+clean:
+ $(MAKE) -C ptest clean
diff --git a/src/compiler/ptest/Makefile b/src/compiler/ptest/Makefile
new file mode 100644
index 0000000..b3a463e
--- /dev/null
+++ b/src/compiler/ptest/Makefile
@@ -0,0 +1,63 @@
+RTEMS_VERSION ?= 4.11
+RTEMS_MAKEFILE_PATH ?= \
+ /opt/rtems-$(RTEMS_VERSION)/lm32-rtems$(RTEMS_VERSION)/milkymist/
+RTEMS_FPVM_H = $(RTEMS_MAKEFILE_PATH)/lib/include/fpvm
+
+CFLAGS = -Wall -g -I.. -I.
+OBJS = ptest.o scanner.o parser.o parser_helper.o unique.o
+
+# ----- Verbosity control -----------------------------------------------------
+
+CC_normal := $(CC)
+
+CC_quiet = @echo " CC " $@ && $(CC_normal)
+GEN_quiet = @echo " GENERATE " $@ &&
+
+ifeq ($(V),1)
+ CC = $(CC_normal)
+ GEN =
+else
+ CC = $(CC_quiet)
+ GEN = $(GEN_quiet)
+endif
+
+# ----- Rules -----------------------------------------------------------------
+
+.PHONY: all clean
+
+all: fpvm ptest
+
+fpvm:
+ $(GEN) ln -s $(RTEMS_FPVM_H) fpvm
+
+ptest: $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $^
+
+%.o: ../%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.c: %.re
+ $(GEN) re2c -o $@ $<
+
+%.c: %.y
+ $(GEN) lemon $<
+
+%.h %.inc: %.ids
+ $(GEN) cd .. && ./idgen `basename $<`
+
+# ----- Dependencies ----------------------------------------------------------
+
+../parser.h: ../parser.c
+scanner.o: ../parser.h
+parser_helper.o: ../parser.h
+ptest.o: ../parser.h
+unique.o: ../fnp.inc
+
+# ----- Cleanup ---------------------------------------------------------------
+
+clean:
+ rm -f $(OBJS)
+ rm -f ../scanner.c
+ rm -f ../parser.c ../parser.h ../parser.out
+ rm -f ../fnp.h ../fnp.inc
+ rm -f fpvm
diff --git a/src/compiler/ptest/ptest.c b/src/compiler/ptest/ptest.c
new file mode 100644
index 0000000..eab3b0d
--- /dev/null
+++ b/src/compiler/ptest/ptest.c
@@ -0,0 +1,211 @@
+/*
+ * ptest.c - FNP parser tester
+ *
+ * Copyright 2011 by Werner Almesberger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "../fpvm.h"
+#include "../parser_helper.h"
+#include "../parser.h"
+
+
+static int quiet = 0;
+
+
+static void dump_ast(const struct ast_node *ast);
+
+
+static void branch(const struct ast_node *ast)
+{
+ if (ast) {
+ putchar(' ');
+ dump_ast(ast);
+ }
+}
+
+
+static void op(const char *s, const struct ast_node *ast)
+{
+ printf("(%s", s);
+ branch(ast->contents.branches.a);
+ branch(ast->contents.branches.b);
+ branch(ast->contents.branches.c);
+ putchar(')');
+}
+
+
+static void dump_ast(const struct ast_node *ast)
+{
+ switch (ast->op) {
+ case op_ident:
+ printf("%s", ast->label);
+ break;
+ case op_constant:
+ printf("%g", ast->contents.constant);
+ break;
+ case op_plus:
+ op("+", ast);
+ break;
+ case op_minus:
+ op("-", ast);
+ break;
+ case op_multiply:
+ op("*", ast);
+ break;
+ case op_divide:
+ op("/", ast);
+ break;
+ case op_percent:
+ op("%", ast);
+ break;
+ case op_abs:
+ op("abs", ast);
+ break;
+ case op_isin:
+ op("isin", ast);
+ break;
+ case op_icos:
+ op("icos", ast);
+ break;
+ case op_sin:
+ op("sin", ast);
+ break;
+ case op_cos:
+ op("cos", ast);
+ break;
+ case op_above:
+ op("above", ast);
+ break;
+ case op_below:
+ op("below", ast);
+ break;
+ case op_equal:
+ op("equal", ast);
+ break;
+ case op_i2f:
+ op("i2f", ast);
+ break;
+ case op_f2i:
+ op("f2i", ast);
+ break;
+ case op_if:
+ op("if", ast);
+ break;
+ case op_tsign:
+ op("tsign", ast);
+ break;
+ case op_quake:
+ op("quake", ast);
+ break;
+ case op_not:
+ op("!", ast);
+ break;
+ case op_sqr:
+ op("sqr", ast);
+ break;
+ case op_sqrt:
+ op("sqrt", ast);
+ break;
+ case op_invsqrt:
+ op("invsqrt", ast);
+ break;
+ case op_min:
+ op("min", ast);
+ break;
+ case op_max:
+ op("max", ast);
+ break;
+ case op_int:
+ op("int", ast);
+ break;
+ default:
+ abort();
+ }
+}
+
+
+int fpvm_do_assign(struct fpvm_fragment *fragment, const char *dest,
+ struct ast_node *ast)
+{
+ if (!quiet) {
+ printf("%s = ", dest);
+ dump_ast(ast);
+ putchar('\n');
+ }
+ return 1;
+}
+
+
+static const char *read_stdin(void)
+{
+ char *buf = NULL;
+ int len = 0, size = 0;
+ ssize_t got;
+
+ do {
+ if (len == size) {
+ size += size ? size : 1024;
+ buf = realloc(buf, size+1);
+ if (!buf) {
+ perror("realloc");
+ exit(1);
+ }
+ }
+ got = read(0, buf+len, size-len);
+ if (got < 0) {
+ perror("read");
+ exit(1);
+ }
+ len += got;
+ }
+ while (got);
+
+ buf[len] = 0;
+
+ return buf;
+}
+
+
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s [-q] [expr]\n", name);
+ exit(1);
+}
+
+
+int main(int argc, char **argv)
+{
+ int c;
+ const char *buf;
+ union parser_comm comm;
+
+ while ((c = getopt(argc, argv, "q")) != EOF)
+ switch (c) {
+ case 'q':
+ quiet = 1;
+ break;
+ default:
+ usage(*argv);
+ }
+ switch (argc-optind) {
+ case 0:
+ buf = read_stdin();
+ break;
+ case 1:
+ buf = argv[optind];
+ break;
+ default:
+ usage(*argv);
+ }
+
+ return !fpvm_parse(buf, TOK_START_ASSIGN, &comm);
+}
--
1.7.1
_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode