summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorOri Bernstein <ori@odin.theasylum>2011-11-05 01:32:46 -0400
committerOri Bernstein <ori@odin.theasylum>2011-11-05 01:34:58 -0400
commit76d42756c93a7f8e1519268b8eb693ba36db4652 (patch)
treecd51bfe84f24f8aba6fd4aaf0885cb03b0e13f73 /parse
downloadmc-76d42756c93a7f8e1519268b8eb693ba36db4652.tar.gz
Initial commit
Diffstat (limited to 'parse')
-rw-r--r--parse/Makefile18
-rw-r--r--parse/dump.c84
-rw-r--r--parse/gram.y475
-rw-r--r--parse/lits.def7
-rw-r--r--parse/main.c55
-rw-r--r--parse/names.c56
-rw-r--r--parse/node.c181
-rw-r--r--parse/nodes.def9
-rw-r--r--parse/ops.def51
-rw-r--r--parse/parse.h210
-rw-r--r--parse/tok.c488
-rw-r--r--parse/type.c157
-rw-r--r--parse/types.def41
-rw-r--r--parse/util.c66
14 files changed, 1898 insertions, 0 deletions
diff --git a/parse/Makefile b/parse/Makefile
new file mode 100644
index 0000000..9693c1b
--- /dev/null
+++ b/parse/Makefile
@@ -0,0 +1,18 @@
+BIN=pt
+OBJ=dump.o \
+ main.o \
+ names.o \
+ node.o \
+ gram.o \
+ tok.o \
+ type.o \
+ util.o
+
+CLEAN=gram.c
+
+include ../mk/lexyacc.mk
+include ../mk/c.mk
+
+ops.o: ../mc/ops.c
+ $(CC) -c $(CFLAGS) $<
+
diff --git a/parse/dump.c b/parse/dump.c
new file mode 100644
index 0000000..af483c6
--- /dev/null
+++ b/parse/dump.c
@@ -0,0 +1,84 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+static void indent(FILE *fd, int depth)
+{
+ int i;
+ for (i = 0; i < 4*depth; i++)
+ fprintf(fd, " ");
+}
+
+static void dumpnode(Node *n, FILE *fd, int depth)
+{
+ int i;
+
+
+ indent(fd, depth);
+ fprintf(fd, "%s", nodestr(n->type));
+ switch(n->type) {
+ case Nfile:
+ fprintf(fd, "(name = %s)\n", n->file.name);
+ break;
+ case Nblock:
+ for (i = 0; i < n->block.nstmts; i++)
+ dumpnode(n->block.stmts[i], fd, depth+1);
+ break;
+ case Nifstmt:
+ dumpnode(n->ifstmt.cond, fd, depth+1);
+ dumpnode(n->ifstmt.iftrue, fd, depth+1);
+ dumpnode(n->ifstmt.iffalse, fd, depth+1);
+ break;
+ case Nloopstmt:
+ dumpnode(n->loopstmt.init, fd, depth+1);
+ dumpnode(n->loopstmt.cond, fd, depth+1);
+ dumpnode(n->loopstmt.incr, fd, depth+1);
+ dumpnode(n->loopstmt.body, fd, depth+1);
+ break;
+ case Nuse:
+ fprintf(fd, " (name = %s, islocal = %d)\n", n->use.name, n->use.islocal);
+ break;
+ case Nexpr:
+ fprintf(fd, " (op = %s, isconst = %d)\n", opstr(n->expr.op), n->expr.isconst);
+ for (i = 0; i < n->expr.nargs; i++)
+ dumpnode(n->expr.args[i], fd, depth+1);
+ break;
+ case Nlit:
+ indent(fd, depth);
+ switch (n->lit.littype) {
+ case Lchr: fprintf(fd, "Lchr %c\n", n->lit.chrval); break;
+ case Lbool: fprintf(fd, "Lbool %s\n", n->lit.boolval ? "true" : "false"); break;
+ case Lint: fprintf(fd, "Lint %ld\n", n->lit.intval); break;
+ case Lflt: fprintf(fd, "Lflt %lf\n", n->lit.fltval); break;
+ /*
+ case Lfunc: fprintf("Lfunc %s\n", n->lit.chrval); break;
+ case Larray: fprintf("Larray %c\n", n->lit.chrval); break;
+ */
+ default: die("Bad literal type"); break;
+ }
+ break;
+ case Nname:
+ fprintf(fd, "(");
+ for (i = 0; i < n->name.nparts; i++) {
+ if (i != 0)
+ fprintf(fd, ".");
+ fprintf(fd, "%s", n->name.parts[i]);
+ }
+ fprintf(fd, ")\n");
+ break;
+ }
+}
+
+void dump(Node *n, FILE *fd)
+{
+ dumpnode(n, fd, 0);
+}
diff --git a/parse/gram.y b/parse/gram.y
new file mode 100644
index 0000000..183939f
--- /dev/null
+++ b/parse/gram.y
@@ -0,0 +1,475 @@
+%{
+#define YYERROR_VERBOSE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+void yyerror(const char *s);
+int yylex(void);
+Op binop(int toktype);
+Stab *curscope;
+%}
+
+%token<tok> TError
+%token<tok> TPlus /* + */
+%token<tok> TMinus /* - */
+%token<tok> TStar /* * */
+%token<tok> TDiv /* / */
+%token<tok> TInc /* ++ */
+%token<tok> TDec /* -- */
+%token<tok> TMod /* % */
+%token<tok> TAsn /* = */
+%token<tok> TAddeq /* += */
+%token<tok> TSubeq /* -= */
+%token<tok> TMuleq /* *= */
+%token<tok> TDiveq /* /= */
+%token<tok> TModeq /* %= */
+%token<tok> TBoreq /* |= */
+%token<tok> TBxoreq /* ^= */
+%token<tok> TBandeq /* &= */
+%token<tok> TBsleq /* <<= */
+%token<tok> TBsreq /* >>= */
+
+%token<tok> TBor /* | */
+%token<tok> TBxor /* ^ */
+%token<tok> TBand /* & */
+%token<tok> TBsl /* << */
+%token<tok> TBsr /* >> */
+%token<tok> TBnot /* ~ */
+
+%token<tok> TEq /* == */
+%token<tok> TGt /* > */
+%token<tok> TLt /* < */
+%token<tok> TGe /* >= */
+%token<tok> TLe /* <= */
+%token<tok> TNe /* != */
+
+%token<tok> TLor /* || */
+%token<tok> TLand /* && */
+%token<tok> TLnot /* ! */
+
+%token<tok> TObrace /* { */
+%token<tok> TCbrace /* } */
+%token<tok> TOparen /* ( */
+%token<tok> TCparen /* ) */
+%token<tok> TOsqbrac /* [ */
+%token<tok> TCsqbrac /* ] */
+%token<tok> TAt /* @ */
+
+%token<tok> TType /* type */
+%token<tok> TFor /* for */
+%token<tok> TWhile /* while */
+%token<tok> TIf /* if */
+%token<tok> TElse /* else */
+%token<tok> TElif /* else */
+%token<tok> TMatch /* match */
+%token<tok> TDefault /* default */
+%token<tok> TGoto /* goto */
+
+%token<tok><tok> TIntlit
+%token<tok><tok> TStrlit
+%token<tok><tok> TFloatlit
+%token<tok><tok> TChrlit
+%token<tok><tok> TBoollit
+
+%token<tok> TEnum /* enum */
+%token<tok> TStruct /* struct */
+%token<tok> TUnion /* union */
+
+%token<tok> TConst /* const */
+%token<tok> TVar /* var */
+%token<tok> TExtern /* extern */
+
+%token<tok> TExport /* export */
+%token<tok> TProtect /* protect */
+
+%token<tok> TEllipsis /* ... */
+%token<tok> TEndln /* ; or \n */
+%token<tok> TEndblk /* ;; */
+%token<tok> TColon /* : */
+%token<tok> TDot /* . */
+%token<tok> TComma /* , */
+%token<tok> TRet /* -> */
+%token<tok> TUse /* use */
+%token<tok> TPkg /* pkg */
+%token<tok><tok> TSizeof /* sizeof */
+
+%token<tok> TIdent
+%token<tok> TEof
+
+%start module
+
+%type <ty> type structdef uniondef enumdef compoundtype functype funcsig
+
+%type <tok> asnop cmpop addop mulop shiftop
+
+%type <node> exprln retexpr expr atomicexpr literal asnexpr lorexpr landexpr borexpr
+%type <node> bandexpr cmpexpr addexpr mulexpr shiftexpr prefixexpr postfixexpr
+%type <node> funclit arraylit arglist name
+%type <node> decl declvariants declbody declcore structelt enumelt unionelt
+
+%type <nodelist> argdefs structbody enumbody unionbody
+
+%union {
+ struct {
+ Node **nodes;
+ size_t nnodes;
+ } nodelist;
+ struct {
+ Type **types;
+ size_t ntypes;
+ } tylist;
+ Node *node;
+ Tok *tok;
+ Type *ty;
+}
+
+
+%%
+
+module : file
+ ;
+
+file : toplev
+ | file toplev
+ ;
+
+toplev
+ : decl
+ | use
+ | package
+ | typedef
+ | TEndln
+ ;
+
+decl : declvariants TEndln
+ ;
+
+use : TUse TIdent TEndln
+ | TUse TStrlit TEndln
+ ;
+
+package : TPkg TIdent TAsn pkgbody TEndblk {}
+ ;
+
+
+pkgbody : pkgitem
+ | pkgbody pkgitem
+ ;
+
+pkgitem : decl
+ | type
+ | visdef
+ | TEndln
+ ;
+
+visdef : TExport TColon
+ | TProtect TColon
+ ;
+
+
+declvariants
+ : TVar declbody {$2->decl.isconst = 0; $$ = $2;}
+ | TConst declbody {$2->decl.isconst = 1; $$ = $2;}
+ | TExtern TVar declbody {$3->decl.isconst = 0; $$ = $3;}
+ | TExtern TConst declbody {$3->decl.isconst = 0; $$ = $3;}
+ ;
+
+declbody: declcore TAsn expr {$$ = $1; $1->decl.init = $3;}
+ | declcore
+ ;
+
+declcore: name {$$ = mkdecl(line, mksym(line, $1, mktyvar(line)));}
+ | name TColon type {$$ = mkdecl(line, mksym(line, $1, $3));}
+ ;
+
+name : TIdent {$$ = mkname(line, $1->str);}
+ | TIdent TDot name {$$ = $3; setns($3, $1->str);}
+ ;
+
+typedef : TType TIdent TAsn type TEndln
+ | TType TIdent TEndln
+ ;
+
+type : structdef
+ | uniondef
+ | enumdef
+ | compoundtype
+ ;
+
+compoundtype
+ : functype {$$ = $1;}
+ | type TOsqbrac TComma TCsqbrac {$$ = mktyslice(line, $1);}
+ | type TOsqbrac expr TCsqbrac {$$ = mktyarray(line, $1, $3);}
+ | type TStar {$$ = mktyptr(line, $1);}
+ | name {$$ = mktynamed(line, $1);}
+ | TAt TIdent {$$ = mktyparam(line, $2->str);}
+ ;
+
+functype: TOparen funcsig TCparen {$$ = $2;}
+ ;
+
+funcsig : argdefs {$$ = mktyfunc(line, $1.nodes, $1.nnodes, mktyvar(line));}
+ | argdefs TRet type {$$ = mktyfunc(line, $1.nodes, $1.nnodes, $3);}
+ ;
+
+argdefs : declcore {$$.nodes = NULL; $$.nnodes = 0; nlappend(&$$.nodes, &$$.nnodes, $1);}
+ | argdefs TComma declcore {nlappend(&$$.nodes, &$$.nnodes, $3);}
+ ;
+
+structdef
+ : TStruct structbody TEndblk {$$ = mktystruct($1->line, $2.nodes, $2.nnodes);}
+ ;
+
+structbody
+ : structelt {$$.nnodes = 0; nlappend(&$$.nodes, &$$.nnodes, $1);}
+ | structbody structelt {if ($2) {nlappend(&$$.nodes, &$$.nnodes, $2);}}
+ ;
+
+structelt
+ : declcore TEndln {$$ = $1;}
+ | visdef TEndln {$$ = NULL;}
+ ;
+
+uniondef
+ : TUnion unionbody TEndblk {$$ = mktyunion(line, $2.nodes, $2.nnodes);}
+ ;
+
+unionbody
+ : unionelt {$$.nnodes = 0; nlappend(&$$.nodes, &$$.nnodes, $1);}
+ | unionbody unionelt {if ($2) {nlappend(&$$.nodes, &$$.nnodes, $2);}}
+ ;
+
+unionelt
+ : TIdent type TEndln {$$ = NULL; die("unionelt impl");}
+ | visdef TEndln {$$ = NULL;}
+ ;
+
+enumdef : TEnum enumbody TEndblk {$$ = mktyenum($1->line, $2.nodes, $2.nnodes);}
+ ;
+
+enumbody: enumelt {$$.nnodes = 0; nlappend(&$$.nodes, &$$.nnodes, $1);}
+ | enumbody enumelt {if ($2) {nlappend(&$$.nodes, &$$.nnodes, $2);}}
+ ;
+
+enumelt : TIdent TEndln {$$ = NULL; die("enumelt impl");}
+ | TIdent TAsn exprln {$$ = NULL; die("enumelt impl");}
+ ;
+
+retexpr : TRet exprln {$$ = mkexpr(line, Oret, $2, NULL);}
+ | exprln
+ ;
+
+exprln : expr TEndln
+ ;
+
+expr : asnexpr{dump($1, stdout);}
+ ;
+
+asnexpr : lorexpr asnop asnexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | lorexpr
+ ;
+
+asnop : TAsn
+ | TAddeq /* += */
+ | TSubeq /* -= */
+ | TMuleq /* *= */
+ | TDiveq /* /= */
+ | TModeq /* %= */
+ | TBoreq /* |= */
+ | TBxoreq /* ^= */
+ | TBandeq /* &= */
+ | TBsleq /* <<= */
+ | TBsreq /* >>= */
+ ;
+
+lorexpr : lorexpr TLor landexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | landexpr
+ ;
+
+landexpr: landexpr TLand borexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | borexpr
+ ;
+
+borexpr : borexpr TBor bandexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | bandexpr
+ ;
+
+bandexpr: bandexpr TBand cmpexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | cmpexpr
+ ;
+
+cmpexpr : cmpexpr cmpop addexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | addexpr
+ ;
+
+cmpop : TEq | TGt | TLt | TGe | TLe | TNe ;
+
+addexpr : addexpr addop mulexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | mulexpr
+ ;
+
+addop : TPlus | TMinus ;
+
+mulexpr : mulexpr mulop shiftexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | shiftexpr
+ ;
+
+mulop : TStar | TDiv | TMod
+ ;
+
+shiftexpr
+ : shiftexpr shiftop prefixexpr {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | prefixexpr
+ ;
+
+shiftop : TBsl | TBsr;
+
+prefixexpr
+ : TInc postfixexpr {$$ = mkexpr($1->line, Opreinc, $2, NULL);}
+ | TDec postfixexpr {$$ = mkexpr($1->line, Opredec, $2, NULL);}
+ | TStar postfixexpr {$$ = mkexpr($1->line, Oderef, $2, NULL);}
+ | TBand postfixexpr {$$ = mkexpr($1->line, Oaddr, $2, NULL);}
+ | TLnot postfixexpr {$$ = mkexpr($1->line, Olnot, $2, NULL);}
+ | TBnot postfixexpr {$$ = mkexpr($1->line, Obnot, $2, NULL);}
+ | TMinus postfixexpr {$$ = mkexpr($1->line, Oneg, $2, NULL);}
+ | TPlus postfixexpr {$$ = $2;}
+ | postfixexpr
+ ;
+
+postfixexpr
+ : postfixexpr TDot TIdent {
+ $$ = mkexpr($1->line, Omemb, $1, mkname($3->line, $3->str), NULL);
+ }
+ | postfixexpr TInc {$$ = mkexpr($1->line, Opostinc, $1, NULL);}
+ | postfixexpr TDec {$$ = mkexpr($1->line, Opostdec, $1, NULL);}
+ | postfixexpr TOsqbrac expr TCsqbrac {$$ = mkexpr($1->line, Oidx, $1, $3);}
+ | postfixexpr TOsqbrac expr TComma expr TCsqbrac {
+ $$ = mkexpr($1->line, Oslice, $1, $3, $5, NULL);
+ }
+ | postfixexpr TOparen arglist TCparen {$$ = mkexpr($1->line, Ocall, $1, $3);}
+ | atomicexpr
+ ;
+
+arglist : asnexpr
+ | arglist TComma asnexpr
+ ;
+
+atomicexpr
+ : TIdent {$$ = mkexpr(line, Ovar, mkname(line, $1->str), NULL);}
+ | literal
+ | TOparen expr TCparen {$$ = $2;}
+ | TSizeof atomicexpr {$$ = mkexpr($1->line, Osize, $2, NULL);}
+ ;
+
+literal : funclit {$$ = $1;}
+ | arraylit {$$ = $1;}
+ | TStrlit {$$ = mkstr($1->line, $1->str);}
+ | TIntlit {$$ = mkint($1->line, strtol($1->str, NULL, 0));}
+ | TChrlit {$$ = mkchar($1->line, *$1->str);} /* FIXME: expand escapes, unicode */
+ | TFloatlit {$$ = mkfloat($1->line, strtod($1->str, NULL));}
+ | TBoollit {$$ = mkbool($1->line, !strcmp($1->str, "true"));}
+ ;
+
+funclit : TObrace params TEndln blockbody TCbrace {$$ = NULL; die("unimpl funclit");}
+ ;
+
+params : declcore
+ | params TComma declcore
+ ;
+
+arraylit : TOsqbrac arraybody TCsqbrac {$$ = NULL; die("Unimpl arraylit");}
+ ;
+
+arraybody
+ : expr
+ | arraybody TComma expr
+ ;
+
+stmt : retexpr
+ | label
+ | ifstmt
+ ;
+
+ifstmt : TIf exprln blockbody elifblocks TElse block
+ | TIf exprln blockbody elifblocks TEndblk
+ | TIf exprln blockbody TElse block
+ | TIf exprln block
+ ;
+
+elifblocks
+ : TElif exprln blockbody
+ | elifblocks TElif exprln blockbody
+ ;
+
+block : blockbody TEndblk
+ ;
+
+blockbody
+ : stmt
+ | blockbody stmt
+ ;
+
+label : TColon TIdent
+ ;
+
+%%
+
+void yyerror(const char *s)
+{
+ fprintf(stderr, "%d: %s", line, s);
+ if (curtok->str)
+ fprintf(stderr, " near %s", curtok->str);
+ fprintf(stderr, "\n");
+}
+
+Op binop(int tt)
+{
+ Op o;
+ switch (tt) {
+ case TPlus: o = Oadd; break;
+ case TMinus: o = Osub; break;
+ case TStar: o = Omul; break;
+ case TDiv: o = Odiv; break;
+ case TMod: o = Omod; break;
+ case TAsn: o = Oasn; break;
+ case TAddeq: o = Oaddeq; break;
+ case TSubeq: o = Osubeq; break;
+ case TMuleq: o = Omuleq; break;
+ case TDiveq: o = Odiveq; break;
+ case TModeq: o = Omodeq; break;
+ case TBoreq: o = Oboreq; break;
+ case TBxoreq: o = Obxoreq; break;
+ case TBandeq: o = Obandeq; break;
+ case TBsleq: o = Obsleq; break;
+ case TBsreq: o = Obsreq; break;
+ case TBor: o = Obor; break;
+ case TBxor: o = Obxor; break;
+ case TBand: o = Oband; break;
+ case TBsl: o = Obsl; break;
+ case TBsr: o = Obsr; break;
+ case TEq: o = Oeq; break;
+ case TGt: o = Ogt; break;
+ case TLt: o = Olt; break;
+ case TGe: o = Oge; break;
+ case TLe: o = Ole; break;
+ case TNe: o = One; break;
+ case TLor: o = Olor; break;
+ case TLand: o = Oland; break;
+ default:
+ die("Unimplemented binop\n");
+ break;
+ }
+ return o;
+}
+
diff --git a/parse/lits.def b/parse/lits.def
new file mode 100644
index 0000000..8ee460a
--- /dev/null
+++ b/parse/lits.def
@@ -0,0 +1,7 @@
+L(Lchr)
+L(Lbool)
+L(Lint)
+L(Lflt)
+L(Lstr)
+L(Lfunc)
+L(Larray)
diff --git a/parse/main.c b/parse/main.c
new file mode 100644
index 0000000..2ab0d61
--- /dev/null
+++ b/parse/main.c
@@ -0,0 +1,55 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+Node *file;
+char *outfile;
+
+static void usage(char *prog)
+{
+ printf("%s [-h] [-o outfile] inputs\n", prog);
+ printf("\t-h\tPrint this help\n");
+ printf("\t-o\tOutput to outfile\n");
+}
+
+int main(int argc, char **argv)
+{
+ int opt;
+ int i;
+
+ while ((opt = getopt(argc, argv, "ho:")) != -1) {
+ switch (opt) {
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'h':
+ default:
+ usage(argv[0]);
+ exit(0);
+ break;
+ }
+ }
+
+ for (i = optind; i < argc; i++) {
+ tokinit(argv[i]);
+ file = mkfile(argv[i]);
+ yyparse();
+ gen();
+ }
+
+ return 0;
+}
+
+void gen()
+{
+ printf("GEN!\n");
+}
diff --git a/parse/names.c b/parse/names.c
new file mode 100644
index 0000000..e3f626f
--- /dev/null
+++ b/parse/names.c
@@ -0,0 +1,56 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+char *optab[] = {
+#define O(op) #op,
+#include "ops.def"
+#undef O
+};
+
+char *nodetab[] = {
+#define N(nt) #nt,
+#include "nodes.def"
+#undef N
+};
+
+char *littab[] = {
+#define L(lt) #lt,
+#include "lits.def"
+#undef L
+};
+
+char *tidtab[] = {
+#define Ty(t) #t,
+#include "types.def"
+#undef Ty
+};
+
+char *opstr(Op o)
+{
+ return optab[o];
+}
+
+char *nodestr(Ntype nt)
+{
+ return nodetab[nt];
+}
+
+char *litstr(Littype lt)
+{
+ return littab[lt];
+}
+
+char *tidstr(Ty tid)
+{
+ return tidtab[tid];
+}
diff --git a/parse/node.c b/parse/node.c
new file mode 100644
index 0000000..1e2683c
--- /dev/null
+++ b/parse/node.c
@@ -0,0 +1,181 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+static Node *mknode(int line, Ntype nt)
+{
+ Node *n;
+
+ n = zalloc(sizeof(Node));
+ n->type = nt;
+ n->line = line;
+ return n;
+}
+
+Node *mkfile(char *name)
+{
+ Node *n;
+
+ n = mknode(-1, Nfile);
+ n->file.name = strdup(name);
+ return n;
+}
+
+Node *mkuse(int line, char *use, int islocal)
+{
+ Node *n;
+
+ n = mknode(line, Nuse);
+ n->use.name = strdup(use);
+ n->use.islocal = islocal;
+
+ return n;
+}
+
+Node *mkexpr(int line, Op op, ...)
+{
+ Node *n;
+ va_list ap;
+ Node *arg;
+
+ n = mknode(line, Nexpr);
+ n->expr.op = op;
+ va_start(ap, op);
+ while ((arg = va_arg(ap, Node*)) != NULL)
+ nlappend(&n->expr.args, &n->expr.nargs, arg);
+ va_end(ap);
+
+ return n;
+}
+
+Node *mkif(int line, Node *cond, Node *iftrue, Node *iffalse)
+{
+ Node *n;
+
+ n = mknode(line, Nifstmt);
+ n->ifstmt.cond = cond;
+ n->ifstmt.iftrue = iftrue;
+ n->ifstmt.iffalse = iffalse;
+
+ return n;
+}
+
+Node *mkloop(int line, Node *init, Node *cond, Node *incr, Node *body)
+{
+ Node *n;
+
+ n = mknode(line, Nloopstmt);
+ n->loopstmt.init = init;
+ n->loopstmt.cond = init;
+ n->loopstmt.incr = incr;
+ n->loopstmt.body = body;
+
+ return n;
+}
+
+Node *mkstr(int line, char *val)
+{
+ Node *n;
+
+ n = mknode(line, Nlit);
+ n->lit.littype = Lstr;
+ n->lit.strval = strdup(val);
+
+ return n;
+}
+
+Node *mkint(int line, uint64_t val)
+{
+ Node *n;
+
+ n = mknode(line, Nlit);
+ n->lit.littype = Lint;
+ n->lit.intval = val;
+
+ return n;
+}
+
+Node *mkchar(int line, uint32_t val)
+{
+ Node *n;
+
+ n = mknode(line, Nlit);
+ n->lit.littype = Lchr;
+ n->lit.chrval = val;
+
+ return n;
+}
+
+Node *mkfloat(int line, double val)
+{
+ Node *n;
+
+ n = mknode(line, Nlit);
+ n->lit.littype = Lflt;
+ n->lit.fltval = val;
+
+ return n;
+}
+
+Node *mkname(int line, char *name)
+{
+ Node *n;
+
+ n = mknode(line, Nname);
+ n->name.nparts = 1;
+ n->name.parts = xalloc(sizeof(char*));
+ n->name.parts[0] = strdup(name);
+
+ return n;
+}
+
+Node *mkdecl(int line, Sym *sym)
+{
+ die("Fixme: mkdecl");
+ return NULL;
+}
+
+void setns(Node *n, char *name)
+{
+ int i;
+
+ n->name.nparts++;
+ n->name.parts = xrealloc(n->name.parts, n->name.nparts);
+ for (i = n->name.nparts - 1; i > 0; i++)
+ n->name.parts[i] = n->name.parts[i-1];
+ n->name.parts[0] = strdup(name);
+}
+
+Node *mkbool(int line, int val)
+{
+ Node *n;
+
+ n = mknode(line, Nlit);
+ n->lit.littype = Lbool;
+ n->lit.boolval = val;
+
+ return n;
+}
+
+Sym *mksym(int line, Node *name, Type *ty)
+{
+ die("Fixme: mksym");
+ return NULL;
+}
+
+void nlappend(Node ***nl, size_t *len, Node *n)
+{
+ *nl = xrealloc(nl, (*len + 1)*sizeof(Node*));
+ (*nl)[*len] = n;
+ (*len)++;
+}
diff --git a/parse/nodes.def b/parse/nodes.def
new file mode 100644
index 0000000..3fb771f
--- /dev/null
+++ b/parse/nodes.def
@@ -0,0 +1,9 @@
+N(Nfile)
+N(Nblock)
+N(Nifstmt)
+N(Nloopstmt)
+N(Nuse)
+N(Nexpr)
+N(Nlit)
+N(Nname)
+N(Ndecl)
diff --git a/parse/ops.def b/parse/ops.def
new file mode 100644
index 0000000..8315c63
--- /dev/null
+++ b/parse/ops.def
@@ -0,0 +1,51 @@
+O(Obad)
+O(Oadd)
+O(Osub)
+O(Omul)
+O(Odiv)
+O(Omod)
+O(Oneg)
+O(Obor)
+O(Oband)
+O(Obxor)
+O(Obsl)
+O(Obsr)
+O(Obnot)
+O(Opreinc)
+O(Opostinc)
+O(Opredec)
+O(Opostdec)
+O(Oaddr)
+O(Oderef)
+O(Onegl)
+O(Olor)
+O(Oland)
+O(Olnot)
+O(Oeq)
+O(One)
+O(Ogt)
+O(Oge)
+O(Olt)
+O(Ole)
+O(Oasn)
+O(Oaddeq)
+O(Osubeq)
+O(Omuleq)
+O(Odiveq)
+O(Omodeq)
+O(Oboreq)
+O(Obandeq)
+O(Obxoreq)
+O(Obsleq)
+O(Obsreq)
+O(Oidx)
+O(Oslice)
+O(Omemb)
+O(Osize)
+O(Ocall)
+O(Ocast)
+O(Oret)
+O(Ogoto)
+O(Ovar)
+O(Olit)
+O(Olbl)
diff --git a/parse/parse.h b/parse/parse.h
new file mode 100644
index 0000000..1376c4a
--- /dev/null
+++ b/parse/parse.h
@@ -0,0 +1,210 @@
+
+typedef unsigned char uchar;
+typedef struct Tok Tok;
+typedef struct Node Node;
+typedef struct Type Type;
+typedef struct Stab Stab;
+typedef struct Sym Sym;
+
+typedef enum {
+#define O(op) op,
+#include "ops.def"
+#undef O
+} Op;
+
+typedef enum {
+#define N(nt) nt,
+#include "nodes.def"
+#undef N
+} Ntype;
+
+typedef enum {
+#define L(lt) lt,
+#include "lits.def"
+#undef L
+} Littype;
+
+typedef enum {
+#define Ty(t) t,
+#include "types.def"
+#undef Ty
+} Ty;
+
+struct Tok {
+ int type;
+ int line;
+ char *str;
+};
+
+struct Stab {
+ int ntypes;
+ Type **types;
+ int nsyms;
+ Sym **syms;
+};
+
+struct Sym {
+ Node *name;
+ Type *type;
+};
+
+struct Type {
+ Ty type;
+ int tid;
+ union {
+ Node *name; /* Tyname: unresolved name */
+ Type **fnsub; /* Tyfunc: return, args */
+ Type **tusub; /* Tytuple: element types */
+ Type *pbase; /* Typtr: pointer target */
+ Type *sbase; /* Tyslice: slice target */
+ struct { /* Tyarray: array target and size */
+ Type *abase;
+ Node *asize;
+ };
+ char *pname; /* Typaram: name of type parameter */
+ Node **sdecls; /* Tystruct: decls in struct */
+ Node **udecls; /* Tyunion: decls in union */
+ Node **edecls; /* Tyenum: decls in enum */
+ };
+};
+
+struct Node {
+ int line;
+ int type;
+ union {
+ struct {
+ char *name;
+ size_t nstmts;
+ Node **stmts;
+ Stab **globals;
+ } file;
+
+ struct {
+ Op op;
+ int isconst;
+ size_t nargs;
+ Node **args;
+ } expr;
+
+ struct {
+ size_t nparts;
+ char **parts;
+ } name;
+
+ struct {
+ int islocal;
+ char *name;
+ } use;
+
+ struct {
+ Littype littype;
+ Type *type;
+ union {
+ uint64_t intval;
+ double fltval;
+ uint32_t chrval;
+ char *strval;
+ int boolval;
+ };
+ } lit;
+
+ struct {
+ Node *init;
+ Node *cond;
+ Node *incr;
+ Node *body;
+ } loopstmt;
+
+ struct {
+ Node *cond;
+ Node *iftrue;
+ Node *iffalse;
+ } ifstmt;
+
+ struct {
+ Stab *scope;
+ size_t nstmts;
+ Node **stmts;
+ } block;
+
+ struct {
+ Sym *sym;
+ Node *init;
+ int isconst;
+ } decl;
+ };
+};
+
+/* globals */
+extern char *filename;
+extern int line;
+extern int ignorenl;
+extern Tok *curtok;
+extern Node *file;
+
+/* util functions */
+void *zalloc(size_t size);
+void *xalloc(size_t size);
+void *xrealloc(void *p, size_t size);
+void die(char *msg, ...);
+void fatal(int line, char *fmt, ...);
+
+/* parsing etc */
+void tokinit(char *file);
+int yylex(void);
+int yyparse(void);
+
+/* stab creation */
+Stab *mkstab();
+Stab *stput(Sym *decl);
+Sym *stget(char *name);
+Sym *mksym(int line, Node *name, Type *ty);
+
+/* type ccreation */
+Type *mktyvar(int line);
+Type *mktyparam(int line, char *name);
+Type *mktynamed(int line, Node *name);
+Type *mktyarray(int line, Type *base, Node *sz);
+Type *mktyslice(int line, Type *base);
+Type *mktyptr(int line, Type *base);
+Type *mktyfunc(int line, Node **args, size_t nargs, Type *ret);
+Type *mktystruct(int line, Node **decls, size_t ndecls);
+Type *mktyunion(int line, Node **decls, size_t ndecls);
+Type *mktyenum(int line, Node **decls, size_t ndecls);
+
+void tlappend(Type ***tl, int *len, Type *t);
+
+/* tree creation */
+Node *mkfile(char *name);
+Node *mkuse(int line, char *use, int islocal);
+Node *mkexpr(int line, Op op, ...); /* NULL terminated */
+Node *mklit(int line, Littype lt, void *val);
+Node *mkif(int line, Node *cond, Node *iftrue, Node *iffalse);
+Node *mkloop(int line, Node *init, Node *cond, Node *incr, Node *body);
+
+Node *mkbool(int line, int val);
+Node *mkint(int line, uint64_t val);
+Node *mkchar(int line, uint32_t val);
+Node *mkstr(int line, char *s);
+Node *mkfloat(int line, double flt);
+Node *mkfunc(int line, Node **args, Node *body);
+Node *mkarray(int line, Node **vals);
+Node *mkname(int line, char *name);
+Node *mkdecl(int line, Sym *sym);
+
+
+void addstmt(Node *file, Node *stmt);
+void setns(Node *n, char *name);
+
+/* debug */
+void dump(Node *t, FILE *fd);
+char *opstr(Op o);
+char *nodestr(Ntype nt);
+char *litstr(Littype lt);
+char *tidstr(Ty tid);
+
+/* convenience macro */
+void nlappend(Node ***nl, size_t *len, Node *n);
+
+/* backend functions */
+void gen();
diff --git a/parse/tok.c b/parse/tok.c
new file mode 100644
index 0000000..54a4901
--- /dev/null
+++ b/parse/tok.c
@@ -0,0 +1,488 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <err.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+#include "gram.h"
+
+char *filename;
+int line;
+int ignorenl;
+Tok *curtok;
+
+static int fidx;
+static int fbufsz;
+static char *fbuf;
+
+static int peekn(int n)
+{
+ if (fidx + n >= fbufsz)
+ return '\0';
+ else
+ return fbuf[fidx];
+}
+
+static int peek()
+{
+ return peekn(0);
+}
+
+static int next()
+{
+ int c;
+
+ c = peek();
+ fidx++;
+ return c;
+}
+
+void unget()
+{
+ fidx--;
+ assert(fidx >= 0);
+}
+
+int match(char c)
+{
+ if (peek() == c) {
+ next();
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+Tok *mktok(int tt)
+{
+ Tok *t;
+
+ t = zalloc(sizeof(Tok));
+ t->type = tt;
+ t->line = line;
+ return t;
+}
+
+static int identchar(int c)
+{
+ return isalnum(c) || c == '_';
+}
+
+static void eatcomment()
+{
+ int depth;
+ int startln;
+ int c;
+
+ depth = 0;
+ startln = line;
+ while (1) {
+ c = next();
+ switch (c) {
+ case '/':
+ if (peekn(1) == '*')
+ depth++;
+ break;
+ case '*':
+ if (peekn(1) == '/')
+ depth--;
+ break;
+ case '\n':
+ line++;
+ break;
+ case EOF:
+ fatal(line, "File ended within comment starting at line %d", startln);
+ break;
+ }
+ }
+}
+
+void eatspace()
+{
+ int c;
+
+ while (1) {
+ c = peek();
+ if ((!ignorenl && c == '\n'))
+ break;
+ else if (isspace(c))
+ next();
+ else if (c == '/' && peekn(1) == '*')
+ eatcomment(c);
+ else
+ break;
+ }
+}
+
+int kwd(char *s)
+{
+ int i;
+ struct {char* kw; int tt;} kwmap[] = {
+ {"type", TType},
+ {"for", TFor},
+ {"while", TWhile},
+ {"if", TIf},
+ {"else", TElse},
+ {"elif", TElif},
+ {"match", TMatch},
+ {"default", TDefault},
+ {"goto", TGoto},
+ {"enum", TEnum},
+ {"struct", TStruct},
+ {"union", TUnion},
+ {"const", TConst},
+ {"var", TVar},
+ {"extern", TExtern},
+ {"export", TExport},
+ {"protect", TProtect},
+ {"use", TUse},
+ {"pkg", TPkg},
+ {"sizeof", TSizeof},
+ {"true", TBoollit},
+ {"false", TBoollit},
+ {NULL, 0}
+ };
+
+ for (i = 0; kwmap[i].kw; i++)
+ if (!strcmp(kwmap[i].kw, s))
+ return kwmap[i].tt;
+
+ return TIdent;
+}
+
+Tok *kwident()
+{
+ char buf[1024];
+ char c;
+ int i;
+ Tok *t;
+
+ i = 0;
+ for (c = peek(); i < 1023 && identchar(c); c = peek()) {
+ next();
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+ t = mktok(kwd(buf));
+ t->str = strdup(buf);
+ return t;
+}
+
+Tok *strlit()
+{
+ Tok *t;
+ int sstart; /* start of string within input buf */
+ int c;
+
+ assert(next() == '"');
+
+ sstart = fidx;
+ while (1) {
+ c = next();
+ /* we don't unescape here, but on output */
+ if (c == '"')
+ break;
+ else if (c == '\\')
+ c = next();
+
+ if (c == '\0')
+ fatal(line, "Unexpected EOF within string");
+ else if (c == '\n')
+ fatal(line, "Newlines not allowed in strings");
+ };
+ t = mktok(TStrlit);
+ t->str = strndup(&fbuf[sstart], fidx - sstart);
+ return t;
+}
+
+Tok *charlit()
+{
+ Tok *t;
+ int sstart; /* start of string within input buf */
+ int c;
+
+ assert(next() == '\'');
+
+ sstart = fidx;
+ while (1) {
+ c = next();
+ /* we don't unescape here, but on output */
+ if (c == '\'')
+ break;
+ else if (c == '\\')
+ c = next();
+
+ if (c == '\0')
+ fatal(line, "Unexpected EOF within char lit");
+ else if (c == '\n')
+ fatal(line, "Newlines not allowed in char lit");
+ };
+ t = mktok(TChrlit);
+ t->str = strndup(&fbuf[sstart], fidx - sstart);
+ return t;
+}
+
+Tok *oper()
+{
+ int tt;
+ char c;
+
+ c = next();
+ switch (c) {
+ case '{': tt = TObrace; break;
+ case '}': tt = TCbrace; break;
+ case '(': tt = TOparen; break;
+ case ')': tt = TCparen; break;
+ case '[': tt = TOsqbrac; break;
+ case ']': tt = TCsqbrac; break;
+ case ',': tt = TComma; break;
+ case ':': tt = TColon; break;
+ case '~': tt = TBnot; break;
+ case ';':
+ if (match(';'))
+ tt = TEndblk;
+ else
+ tt = TEndln;
+ break;
+ case '.':
+ if (match('.')) {
+ if (match('.'))
+ tt = TEllipsis;
+ else
+ unget();
+ } else {
+ tt = TDot;
+ }
+ break;
+ case '+':
+ if (match('='))
+ tt = TAddeq;
+ else if (match('+'))
+ tt = TInc;
+ else
+ tt = TPlus;
+ break;
+ case '-':
+ if (match('='))
+ tt = TSubeq;
+ else if (match('+'))
+ tt = TDec;
+ else if (match('>'))
+ tt = TRet;
+ else
+ tt = TMinus;
+ break;
+ case '*':
+ if (match('='))
+ tt = TMuleq;
+ else
+ tt = TStar;
+ break;
+ case '/':
+ if (match('='))
+ tt = TDiveq;
+ else
+ tt = TDiv;
+ break;
+ case '%':
+ if (match('='))
+ tt = TModeq;
+ else
+ tt = TMod;
+ break;
+ case '=':
+ if (match('='))
+ tt = TEq;
+ else
+ tt = TAsn;
+ break;
+ case '|':
+ if (match('='))
+ tt = TBoreq;
+ else if (match('|'))
+ tt = TLor;
+ else
+ tt = TBor;
+ break;
+ case '&':
+ if (match('='))
+ tt = TBandeq;
+ else if (match('|'))
+ tt = TLand;
+ else
+ tt = TBand;
+ break;
+ case '^':
+ if (match('='))
+ tt = TBxoreq;
+ else
+ tt = TBxor;
+ break;
+ case '<':
+ if (match('=')) {
+ tt = TLe;
+ } else if (match('<')) {
+ if (match('='))
+ tt = TBsleq;
+ else
+ tt = TBsl;
+ } else {
+ tt = TLt;
+ }
+ break;
+ case '>':
+ if (match('=')) {
+ tt = TGe;
+ } else if (match('<')) {
+ if (match('='))
+ tt = TBsreq;
+ else
+ tt = TBsr;
+ } else {
+ tt = TGt;
+ }
+ break;
+
+ case '!':
+ if (match('='))
+ tt = TNe;
+ else
+ tt = TLnot;
+ break;
+ default:
+ tt = TError;
+ fatal(line, "Junk character %c", c);
+ break;
+ }
+ return mktok(tt);
+};
+
+Tok *number(int base)
+{
+ Tok *t;
+ int start;
+ char *endp;
+ int c;
+ int isfloat;
+
+ t = NULL;
+ isfloat = 0;
+ start = fidx;
+ for (c = peek(); isxdigit(c) || c == '.'; c = peek()) {
+ next();
+ if (c == '.')
+ isfloat = 1;
+ }
+
+ /* we only support base 10 floats */
+ if (isfloat && base == 10) {
+ strtod(&fbuf[start], &endp);
+ if (endp == &fbuf[fidx]) {
+ t = mktok(TFloatlit);
+ t->str = strndup(&fbuf[start], fidx - start);
+ }
+ } else {
+ strtol(&fbuf[start], &endp, base);
+ if (endp == &fbuf[fidx]) {
+ t = mktok(TIntlit);
+ t->str = strndup(&fbuf[start], fidx - start);
+ }
+ }
+
+ return t;
+}
+
+Tok *numlit()
+{
+ Tok *t;
+
+ /* check for 0x or 0b prefix */
+ if (match('0')) {
+ if (match('x'))
+ t = number(16);
+ else if (match('b'))
+ t = number(2);
+ else
+ t = number(10);
+ } else {
+ t = number(10);
+ }
+
+ return t;
+}
+
+Tok *toknext()
+{
+ Tok *t;
+ int c;
+
+ eatspace();
+ c = peek();
+ if (c == '\0') {
+ t = mktok(0);
+ } else if (c == '\n') {
+ line++;
+ next();
+ t = mktok(TEndln);
+ } else if (isalpha(c) || c == '_') {
+ t = kwident();
+ } else if (c == '"') {
+ t = strlit();
+ } else if (c == '\'') {
+ t = charlit();
+ } else if (isdigit(c)) {
+ t = numlit();
+ } else {
+ t = oper();
+ }
+
+ if (!t || t->type == TError)
+ fatal(line, "Unable to parse token starting with %c", c);
+
+ return t;
+}
+
+void tokinit(char *file)
+{
+ int fd;
+ int n;
+ int nread;
+
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
+ err(errno, "Unable to open file %s", file);
+ fbuf = malloc(4096);
+ while (1) {
+ n = read(fd, fbuf, 4096);
+ if (n < 0)
+ fatal(errno, "Error reading file %s", file);
+ if (n == 0)
+ break;
+ if (!fbuf)
+ die("Out of memory reading %s", file);
+ nread += n;
+ fbuf = realloc(fbuf, nread + 4096);
+ }
+
+ fbufsz = nread;
+ line = 1;
+ fidx = 0;
+ filename = strdup(file);
+}
+
+int yylex()
+{
+ curtok = toknext();
+ yylval.tok = curtok;
+ return curtok->type;
+}
diff --git a/parse/type.c b/parse/type.c
new file mode 100644
index 0000000..f80edca
--- /dev/null
+++ b/parse/type.c
@@ -0,0 +1,157 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+typedef struct Typename Typename;
+struct Typename {
+ Ty ty;
+ char *name;
+};
+
+Typename typenames[] = {
+ {Tyvoid, "void"},
+ {Tychar, "char"},
+ {Tybyte, "byte"},
+ {Tyint8, "int8"},
+ {Tyint16, "int16"},
+ {Tyint32, "int32"},
+ {Tyint64, "int64"},
+ {Tyuint8, "uint8"},
+ {Tyuint16, "uint16"},
+ {Tyuint32, "uint32"},
+ {Tyuint64, "uint64"},
+ {Tyfloat32, "float32"},
+ {Tyfloat64, "float64"},
+ {Tybad, NULL}
+};
+
+
+static int nexttid = 0;
+static Type *mktype(Ty ty)
+{
+ Type *t;
+
+ t = xalloc(sizeof(Type));
+ t->type = ty;
+ t->tid = nexttid++;
+ return t;
+}
+
+Type *mktyvar(int line)
+{
+ Type *t;
+
+ t = mktype(Tyvar);
+ return t;
+}
+
+Type *mktyparam(int line, char *name)
+{
+ Type *t;
+
+ t = mktype(Tyvar);
+ t->pname = strdup(name);
+ return t;
+}
+
+Type *mktynamed(int line, Node *name)
+{
+ int i;
+ Type *t;
+
+ /* is it a built in type? */
+ if (name->name.nparts == 1)
+ for (i = 0; typenames[i].name; i++)
+ if (!strcmp(typenames[i].name, name->name.parts[0]))
+ return mktype(typenames[i].ty);
+
+ /* if not, resolve it in the type inference stage */
+ t = mktype(Tyname);
+ t->name = name;
+ return t;
+}
+
+Type *mktyarray(int line, Type *base, Node *sz)
+{
+ Type *t;
+
+ t = mktype(Tyarray);
+ t->abase = base;
+ t->asize = sz;
+
+ return t;
+}
+
+Type *mktyslice(int line, Type *base)
+{
+ Type *t;
+
+ t = mktype(Tyslice);
+ t->sbase = base;
+ return t;
+}
+
+Type *mktyptr(int line, Type *base)
+{
+ Type *t;
+
+ t = mktype(Typtr);
+ t->pbase = base;
+ return t;
+}
+
+Type *mktyfunc(int line, Node **args, size_t nargs, Type *ret)
+{
+ Type *t;
+ Type **sub;
+
+ t = mktype(Tyfunc);
+ sub = xalloc((1 + nargs)*sizeof(Type));
+ sub[0] = ret;
+ die("pull out subtypes for fn");
+ t->fnsub = sub;
+ return t;
+}
+
+Type *mktystruct(int line, Node **decls, size_t ndecls)
+{
+ Type *t;
+
+ t = mktype(Tystruct);
+ t->sdecls = decls;
+ return t;
+}
+
+Type *mktyunion(int line, Node **decls, size_t ndecls)
+{
+ Type *t;
+
+ t = mktype(Tyunion);
+ t->udecls = decls;
+ return t;
+}
+
+Type *mktyenum(int line, Node **decls, size_t ndecls)
+{
+ Type *t;
+
+ t = mktype(Tyenum);
+ t->edecls = decls;
+ return t;
+}
+
+void tlappend(Type ***tl, int *len, Type *t)
+{
+ *tl = xrealloc(tl, (*len + 1)*sizeof(Type*));
+ (*tl)[*len] = t;
+ (*len)++;
+}
diff --git a/parse/types.def b/parse/types.def
new file mode 100644
index 0000000..aea6614
--- /dev/null
+++ b/parse/types.def
@@ -0,0 +1,41 @@
+Ty(Tybad)
+Ty(Tyvoid)
+
+/* start integer types.
+ * Keep them ordered between start
+ * and end for faster
+ * comparisons.*/
+Ty(Tybool)
+Ty(Tychar)
+
+Ty(Tyint8)
+Ty(Tyint16)
+Ty(Tyint)
+Ty(Tyint32)
+Ty(Tyint64)
+Ty(Tylong)
+
+Ty(Tybyte)
+Ty(Tyuint8)
+Ty(Tyuint16)
+Ty(Tyuint)
+Ty(Tyuint32)
+Ty(Tyuint64)
+Ty(Tyulong)
+/*end integer types*/
+Ty(Tyfloat32)
+Ty(Tyfloat64)
+Ty(Tyvalist)
+/*end numerical types*/
+Ty(Typtr)
+Ty(Tyslice)
+Ty(Tyarray)
+Ty(Tyfunc)
+Ty(Tytuple)
+Ty(Tyvar)
+Ty(Typaram)
+Ty(Tyname)
+Ty(Tystruct)
+Ty(Tyunion)
+Ty(Tyenum)
+
diff --git a/parse/util.c b/parse/util.c
new file mode 100644
index 0000000..f68d7f9
--- /dev/null
+++ b/parse/util.c
@@ -0,0 +1,66 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "parse.h"
+
+void *zalloc(size_t sz)
+{
+ void *mem;
+
+ mem = calloc(1, sz);
+ if (!mem)
+ die("Out of memory");
+ return mem;
+}
+
+
+void *xalloc(size_t sz)
+{
+ void *mem;
+
+ mem = malloc(sz);
+ if (!mem)
+ die("Out of memory");
+ return mem;
+}
+
+void *xrealloc(void *mem, size_t sz)
+{
+ mem = realloc(mem, sz);
+ if (!mem)
+ die("Out of memory");
+ return mem;
+}
+
+void die(char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
+}
+
+void fatal(int line, char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ fprintf(stderr, "%s:%d: ", filename, line);
+ vfprintf(stderr, msg, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ exit(1);
+}