summary refs log tree commit diff
path: root/lisc/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'lisc/parse.c')
-rw-r--r--lisc/parse.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/lisc/parse.c b/lisc/parse.c
new file mode 100644
index 0000000..86720b9
--- /dev/null
+++ b/lisc/parse.c
@@ -0,0 +1,296 @@
+/* A really crude parser. */
+#include <ctype.h>
+#include <string.h>
+
+#include "lisc.h"
+
+enum {
+	MaxRefs = 256,
+};
+
+typedef enum Token Token;
+typedef enum PState PState;
+
+enum PState { /* Parsing state in a block. */
+	PErr,
+	PPhi,
+	PIns,
+	PEnd,
+};
+
+enum Token {
+	TAdd,
+	TSub,
+	TDiv,
+	TMod,
+	TPhi,
+	TJmp,
+	TCnd,
+	TRet,
+
+	TNum,
+	TVar,
+	TEq,
+	TComma,
+	TLParen,
+	TRParen,
+	TNL,
+	TEOF,
+};
+
+
+static FILE *inf;
+static char *errstr;
+
+static Sym sym[MaxRef];
+static Ref nref;
+static Blk blk[MaxBlks], *curblk;
+static Phi phi[MaxPhis], *curphi;
+static Ins ins[MaxInss], *curins;
+
+static struct {
+	long long num;
+	char *var;
+} tokval;
+static int lnum;
+
+
+static void
+err(char *s)
+{
+	if (!s)
+		s = errstr;
+	assert(s);
+	fprintf(stderr, "parse error: %s (line %d)\n", s, lnum);
+	exit(1);
+}
+
+static Token
+token()
+{
+	static struct {
+		char *str;
+		Token tok;
+	} tmap[] = {
+		{ "add", TAdd },
+		{ "sub", TSub },
+		{ "div", TDiv },
+		{ "mod", TMod },
+		{ "phi", TPhi },
+		{ "jmp", TJmp },
+		{ "cnd", TCnd },
+		{ "ret", TRet },
+		{ 0 },
+	};
+	static char tok[MaxIdnt];
+	int c, i, var, sgn;
+
+	do
+		c = fgetc(inf);
+	while (isblank(c));
+	switch (c) {
+	case EOF:
+		return TEOF;
+	case ',':
+		return TComma;
+	case '(':
+		return TLParen;
+	case ')':
+		return TRParen;
+	case '=':
+		return TEq;
+	case '\n':
+		lnum++;
+		return TNL;
+	}
+	if (isdigit(c) || c == '-') {
+		if (c == '-') {
+			tokval.num = 0;
+			sgn = -1;
+		} else {
+			tokval.num = c - '0';
+			sgn = 1;
+		}
+		for (;;) {
+			c = fgetc(inf);
+			if (!isdigit(c))
+				break;
+			tokval.num *= 10;
+			tokval.num += c - '0';
+		}
+		ungetc(c, f);
+		tokval.num *= sgn;
+		return TNum;
+	}
+	if (c == '%') {
+		var = 1;
+		c = fgetc(inf);
+	} else
+		var = 0;
+	if (!isalpha(c))
+		err("lexing failure");
+	i = 0;
+	do {
+		if (i >= MaxIdnt-1)
+			err("identifier too long");
+		tok[i++] = c;
+		c = fgetc(inf);
+	} while (isalpha(c) || isdigit(c));
+	tok[i] = 0;
+	ungetc(c, f);
+	if (var) {
+		tokval.var = tok;
+		return TVar;
+	}
+	for (i=0; tmap[i].str; i++)
+		if (strcmp(tok, tmap[i].str) == 0)
+			return tmap[i].tok;
+	err("unknown keyword");
+	return -1;
+}
+
+static Ref
+varref(char *v)
+{
+	Ref r;
+
+	for (r=Temp0; r<nref; r++)
+		if (sym[r].ty == STemp)
+		if (strcmp(v, sym[r].stemp.id) == 0)
+			return r;
+	if (r >= MaxRefs)
+		err("too many references");
+	sym[r].ty = STemp;
+	strcpy(sym[r].stemp.id, v);
+	sym[r].stemp.blk = -1;
+	return nref++;
+}
+
+static Ref
+parseref()
+{
+	Ref r;
+
+	switch (token()) {
+	case TVar:
+		return varref(tokval.var);
+	case TNum:
+		/* Add the constant to the symbol table. */
+		for (r=Temp0; r<nref; r++)
+			if (sym[r].ty == SNum)
+			if (sym[r].snum == tokval.num)
+				return r;
+		if (r >= MaxRefs)
+			err("too many references");
+		sym[r].ty = SNum;
+		sym[r].snum = tokval.num;
+		retunr nref++;
+	default:
+		errstr = "number or variable expected";
+		return R;
+	}
+}
+
+static PState
+parseline(PState ps)
+{
+	Ref args[MaxPreds];
+	Ref r;
+	Token t;
+	int na;
+
+	t = token();
+	switch (t) {
+	default:
+		errstr = "variable or jump expected";
+		return PErr;
+	case TVar:
+		break;
+	case TRet:
+		curblk->jmp.ty = JRet;
+		goto Jump;
+	case TJmp:
+		curblk->jmp.ty = JJmp;
+		goto Jump;
+	case TCnd:
+		curblk->jmp.ty = JCnd;
+		r = parseref();
+		if (r == R) {
+			errstr = "invalid argument for cnd";
+			return PErr;
+		}
+		if (token() != TComma) {
+			errstr = "missing comma";
+			return PErr;
+		}
+		curblk->jmp.arg = r;
+	Jump:
+		if (
+		return PEnd;
+	}
+	r = varref(tokval.var);
+	if (token() != TEq) {
+		errstr = "= expected after variable";
+		return PErr;
+	}
+	switch (token()) {
+	case TAdd:
+		curins->op = OAdd;
+		break;
+	case TSub:
+		curins->op = OSub;
+		break;
+	case TDiv:
+		curins->op = ODiv;
+		break;
+	case TMod:
+		curins->op = OMod;
+		break;
+	case TPhi:
+		return PIns;
+	default:
+		errstr = "invalid instruction";
+		return PErr;
+	}
+	na = 0;
+	for (;;) {
+		x
+	}
+}
+
+
+
+
+
+
+// in main parsing routine, reset lnum to 1
+// also reset curxxx
+// also nsym to Temp0
+// also sym[0..nsym-1].ty = SReg
+
+#if 0
+int main()
+{
+	char *toknames[] = {
+		"TAdd",
+		"TSub",
+		"TDiv",
+		"TMod",
+		"TPhi",
+		"TJmp",
+		"TCnd",
+		"TRet",
+		"TNum",
+		"TVar",
+		"TEq",
+		"TComma",
+		"TLParen",
+		"TRParen",
+		"TNL",
+		"TEOF",
+	};
+	inf = stdin;
+	for (;;)
+		printf("%s\n", toknames[token()]);
+}
+#endif