diff --git a/.gitignore b/.gitignore index 0d20b64..34f2b04 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *.pyc +*.o +*.a diff --git a/.hgignore b/.hgignore index bb6d589..b8428bb 100644 --- a/.hgignore +++ b/.hgignore @@ -1,3 +1,5 @@ syntax: glob *.pyc +*.o +*.a diff --git a/README.markdown b/README.markdown index f860ef5..53df835 100644 --- a/README.markdown +++ b/README.markdown @@ -180,23 +180,21 @@ TODO ---- -* the compiler generates *horrible* string-handling code. fix! +* libtamsin contains *horrible* string-handling code. fix! * meta-circular implementation of scanner -- what we have is pretty close * meta-circular implementation of parser * meta-circular implementation of interpreter! -* system library +* system library in its own Python module * `bin/tamsin runast astfile.txt` -- for testing the meta-circular parser +* `bin/tamsin runscan scanfile.txt` -- for testing the meta-circular scanner +* `bin/tamsin scan file.tamsin` -- to generate a scanfile ### compiler ### * handle term concatenation -* literal string escape sequences * render NUL as EOF. actually, we want 8-bit clean strings eventually -* implement any -* implement fail * implement ! * implement alnum -* write `-ltamsin` library and link to it ### document ### diff --git a/c_src/build.sh b/c_src/build.sh new file mode 100755 index 0000000..197a8d1 --- /dev/null +++ b/c_src/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +FILES="scanner term tamsin" + +for FILE in $FILES; do + gcc -c $FILE.c -o $FILE.o +done + +ar -r libtamsin.a scanner.o term.o tamsin.o + diff --git a/c_src/scanner.c b/c_src/scanner.c new file mode 100644 index 0000000..060c340 --- /dev/null +++ b/c_src/scanner.c @@ -0,0 +1,19 @@ +#include "tamsin.h" + +char scan(struct scanner *s) { + char c = s->buffer[s->position]; + if (c == '\0') { + return '\0'; + } else { + s->position++; + return c; + } +}; + +void unscan(struct scanner *s) { + s->position = s->reset_position; +} + +void commit(struct scanner *s) { + s->reset_position = s->position; +} diff --git a/c_src/tamsin.c b/c_src/tamsin.c new file mode 100644 index 0000000..c354e80 --- /dev/null +++ b/c_src/tamsin.c @@ -0,0 +1,48 @@ +#include "tamsin.h" + +void tamsin_eof(struct scanner *s) { + char c = scan(s); + unscan(s); + if (c == '\0') { + result = new_term("EOF"); + ok = 1; + } else { + char t[100]; + sprintf(t, "expected EOF found '%c'", c); + result = new_term(t); + ok = 0; + } +} + +void tamsin_any(struct scanner *s) { + char c = scan(s); + if (c == '\0') { + unscan(s); + result = new_term("expected any token, found EOF"); + ok = 0; + } else { + char t[2]; + commit(s); + sprintf(t, "%c", c); + result = new_term(t); + ok = 1; + } +} + +void tamsin_expect(struct scanner *s, char *token) { + char c = scan(s); + if (c == token[0]) { + commit(s); + char s[10]; + strcpy(s, "a"); + s[0] = c; + result = new_term(s); + ok = 1; + } else { + unscan(s); + char s[100]; + sprintf(s, "expected '%c' found '%c'", token[0], c); + result = new_term(s); + ok = 0; + } +}; diff --git a/c_src/tamsin.h b/c_src/tamsin.h new file mode 100644 index 0000000..8036dc0 --- /dev/null +++ b/c_src/tamsin.h @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* terms */ + +struct term { + const char *atom; + struct term_list *subterms; +}; + +struct term_list { + struct term *term; + struct term_list *next; +}; + +struct term *new_term(const char *); +void add_subterm(struct term *, struct term *); +void term_format_r(struct term *t); +char *term_format(struct term *t); + +/* scanner */ + +struct scanner { + char *buffer; + int position; + int reset_position; +}; + +char scan(struct scanner *); +void unscan(struct scanner *); +void commit(struct scanner *); + +/* tamsin */ + +void tamsin_eof(struct scanner *); +void tamsin_any(struct scanner *); +void tamsin_expect(struct scanner *, char *); + +/* global state: result of last action */ + +extern int ok; +extern struct term *result; diff --git a/c_src/term.c b/c_src/term.c new file mode 100644 index 0000000..f344ea9 --- /dev/null +++ b/c_src/term.c @@ -0,0 +1,42 @@ +#include "tamsin.h" + +struct term *new_term(const char *atom) { + struct term *t; + t = malloc(sizeof(struct term)); + t->atom = strdup(atom); + t->subterms = NULL; +} + +void add_subterm(struct term *term, struct term *subterm) { + struct term_list *tl; + tl = malloc(sizeof(struct term_list)); + tl->term = subterm; + tl->next = term->subterms; + term->subterms = tl; +} + +char fmtbuf[1000]; /* yeesh */ + +void term_format_r(struct term *t) { + struct term_list *tl; + + strcat(fmtbuf, t->atom); + if (t->subterms != NULL) { + strcat(fmtbuf, "("); + + for (tl = t->subterms; tl != NULL; tl = tl->next) { + term_format_r(tl->term); + if (tl->next != NULL) { + strcat(fmtbuf, ", "); + } + } + + strcat(fmtbuf, ")"); + } +} + +char *term_format(struct term *t) { + strcpy(fmtbuf, ""); + term_format_r(t); + return fmtbuf; +} diff --git a/loadngo.sh b/loadngo.sh index 1745b05..9c51761 100755 --- a/loadngo.sh +++ b/loadngo.sh @@ -1,6 +1,8 @@ #!/bin/sh -INPUT=`cat` bin/tamsin compile $1 > foo.c && \ - gcc foo.c -o foo && \ - ./foo "$INPUT" + gcc -Ic_src -Lc_src foo.c -o foo -ltamsin && \ + ./foo `cat` +R=$? +rm -f foo.c foo +exit $R diff --git a/src/tamsin/compiler.py b/src/tamsin/compiler.py index 5ac3799..83faed5 100644 --- a/src/tamsin/compiler.py +++ b/src/tamsin/compiler.py @@ -10,140 +10,12 @@ /* * Generated code! Edit at your own risk! */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include <tamsin.h> /* global state: result of last action */ int ok; struct term *result; - -/* terms */ - -struct term { - const char *atom; - struct term_list *subterms; -}; - -struct term_list { - struct term *term; - struct term_list *next; -}; - -struct term *new_term(const char *atom) { - struct term *t; - t = malloc(sizeof(struct term)); - t->atom = strdup(atom); - t->subterms = NULL; -} - -void add_subterm(struct term *term, struct term *subterm) { - struct term_list *tl; - tl = malloc(sizeof(struct term_list)); - tl->term = subterm; - tl->next = term->subterms; - term->subterms = tl; -} - -char fmtbuf[1000]; /* yeesh */ - -void term_format_r(struct term *t) { - struct term_list *tl; - - strcat(fmtbuf, t->atom); - if (t->subterms != NULL) { - strcat(fmtbuf, "("); - - for (tl = t->subterms; tl != NULL; tl = tl->next) { - term_format_r(tl->term); - if (tl->next != NULL) { - strcat(fmtbuf, ", "); - } - } - - strcat(fmtbuf, ")"); - } -} - -char *term_format(struct term *t) { - strcpy(fmtbuf, ""); - term_format_r(t); - return fmtbuf; -} - -/* scanner */ - -struct scanner { - char *buffer; - int position; - int reset_position; -}; - -char scan(struct scanner *s) { - char c = s->buffer[s->position]; - if (c == '\0') { - return '\0'; - } else { - s->position++; - return c; - } -}; - -void unscan(struct scanner *s) { - s->position = s->reset_position; -} - -void commit(struct scanner *s) { - s->reset_position = s->position; -} - -void tamsin_eof(struct scanner *s) { - char c = scan(s); - unscan(s); - if (c == '\0') { - result = new_term("EOF"); - ok = 1; - } else { - char t[100]; - sprintf(t, "expected EOF found '%c'", c); - result = new_term(t); - ok = 0; - } -} - -void tamsin_any(struct scanner *s) { - char c = scan(s); - if (c == '\0') { - unscan(s); - result = new_term("expected any token, found EOF"); - ok = 0; - } else { - char t[2]; - commit(s); - sprintf(t, "%c", c); - result = new_term(t); - ok = 1; - } -} - -void tamsin_expect(struct scanner *s, char *token) { - char c = scan(s); - if (c == token[0]) { - commit(s); - char s[10]; - strcpy(s, "a"); - s[0] = c; - result = new_term(s); - ok = 1; - } else { - unscan(s); - char s[100]; - sprintf(s, "expected '%c' found '%c'", token[0], c); - result = new_term(s); - ok = 0; - } -}; struct scanner * scanner; '''