shithub: mc

Download patch

ref: 76d42756c93a7f8e1519268b8eb693ba36db4652
author: Ori Bernstein <[email protected]>
date: Fri Nov 4 21:32:46 EDT 2011

Initial commit

--- /dev/null
+++ b/Makefile
@@ -1,0 +1,7 @@
+SUB = parse
+
+-include config.mk
+include mk/c.mk
+
+check:
+	make -C test check
--- /dev/null
+++ b/mk/c.mk
@@ -1,0 +1,73 @@
+DEPSDIR = .deps
+DEPS=$(addprefix $(DEPSDIR)/, $(OBJ:.o=.d))
+
+CFLAGS += -Wall -Werror
+CFLAGS += -g
+CFLAGS += -MMD -MP -MF ${DEPSDIR}/$(subst /,-,$*).d
+
+.PHONY: clean clean-gen clean-bin clean-obj clean-misc clean-backups
+.PHONY: all
+
+all: subdirs $(BIN) $(LIB) $(EXTRA)
+install: subdirs-install install-bin install-lib install-hdr install-pc
+
+$(LIB): $(OBJ)
+	$(AR) -rcs $@ $^
+
+$(BIN): $(OBJ) $(EXTRADEP)
+	$(CC) -o $@ $(OBJ) $(LDFLAGS) 
+
+subdirs:
+	@for i in $(SUB); do (\
+	    cd $$i && \
+	    $(MAKE) || \
+	    exit 1 \
+	) || exit 1; done
+
+subdirs-clean:
+	@for i in $(SUB); do (\
+	    cd $$i && \
+	    $(MAKE) clean|| \
+	    exit 1 \
+	); done
+
+subdirs-install:
+	@for i in $(SUB); do (\
+	    cd $$i && \
+	    $(MAKE) install|| \
+	    exit 1 \
+	); done
+
+
+clean: subdirs-clean 
+	rm -f ${BIN} ${OBJ} ${CLEAN}
+
+
+install-bin: $(INSTBIN)
+	mkdir -p $(INST_ROOT)/bin
+	test -z "$(INSTBIN)" || install $(INSTBIN) $(INST_ROOT)/bin
+
+install-lib: $(INSTLIB)
+	mkdir -p $(INST_ROOT)/lib
+	test -z "$(INSTLIB)" || install $(INSTLIB) $(INST_ROOT)/lib
+
+install-hdr: $(INSTHDR)
+	mkdir -p $(INST_ROOT)/$(HDRDIR)/include
+	test -z "$(INSTHDR)" || install $(INSTHDR) $(INST_ROOT)/include
+
+install-pc: $(INSTPKG)
+	mkdir -p $(INST_ROOT)/pkgconfig
+	test -z "$(INSTPC)" || install $(INSTPC) $(INST_ROOT)/pkgconfig
+
+clean-backups:
+	find ./ -name .*.sw* -exec rm -f {} \;
+	find ./ -name *.bak -exec rm -f {} \;
+
+%.o: %.c .deps
+	$(CC) -c $(CFLAGS) $<
+
+.deps: 
+	mkdir -p $(DEPSDIR)
+
+	
+-include $(DEPS)
--- /dev/null
+++ b/mk/lexyacc.mk
@@ -1,0 +1,9 @@
+NECFLAGS = $(subst -Werror,,$(subst -Wall,,$(CFLAGS)))
+
+%.o: %.y .deps
+	yacc -d -o$*.c $<
+	$(CC) -c $(NECFLAGS) $*.c
+
+%.o: %.l .deps
+	flex -o$*.c $<
+	$(CC) -c $(NECFLAGS) $*.c
--- /dev/null
+++ b/parse/Makefile
@@ -1,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) $<
+
--- /dev/null
+++ b/parse/dump.c
@@ -1,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);
+}
--- /dev/null
+++ b/parse/gram.y
@@ -1,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;
+}
+
--- /dev/null
+++ b/parse/lits.def
@@ -1,0 +1,7 @@
+L(Lchr)
+L(Lbool)
+L(Lint)
+L(Lflt)
+L(Lstr)
+L(Lfunc)
+L(Larray)
--- /dev/null
+++ b/parse/main.c
@@ -1,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");
+}
--- /dev/null
+++ b/parse/names.c
@@ -1,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];
+}
--- /dev/null
+++ b/parse/node.c
@@ -1,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)++;
+}
--- /dev/null
+++ b/parse/nodes.def
@@ -1,0 +1,9 @@
+N(Nfile)
+N(Nblock)
+N(Nifstmt)
+N(Nloopstmt)
+N(Nuse)
+N(Nexpr)
+N(Nlit)
+N(Nname)
+N(Ndecl)
--- /dev/null
+++ b/parse/ops.def
@@ -1,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)
--- /dev/null
+++ b/parse/parse.h
@@ -1,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();
--- /dev/null
+++ b/parse/tok.c
@@ -1,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;
+}
--- /dev/null
+++ b/parse/type.c
@@ -1,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)++;
+}
--- /dev/null
+++ b/parse/types.def
@@ -1,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)
+
--- /dev/null
+++ b/parse/util.c
@@ -1,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);
+}