summary refs log tree commit diff
path: root/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c127
1 files changed, 88 insertions, 39 deletions
diff --git a/parse.c b/parse.c
index 86a16b8..c1dc863 100644
--- a/parse.c
+++ b/parse.c
@@ -94,7 +94,16 @@ typedef enum {
 } PState;
 
 enum {
-	Txxx = NPubOp,
+	Txxx = 0,
+
+	/* aliases */
+	Tloadw = NPubOp,
+	Tloadl,
+	Tloads,
+	Tloadd,
+	Talloc1,
+	Talloc2,
+
 	Tcall,
 	Tphi,
 	Tjmp,
@@ -131,9 +140,43 @@ enum {
 	Trbrace,
 	Tnl,
 	Teof,
+
+	Ntok
 };
 
+static char *kwmap[Ntok] = {
+	[Tloadw] = "loadw",
+	[Tloadl] = "loadl",
+	[Tloads] = "loads",
+	[Tloadd] = "loadd",
+	[Talloc1] = "alloc1",
+	[Talloc2] = "alloc2",
+	[Tcall] = "call",
+	[Tphi] = "phi",
+	[Tjmp] = "jmp",
+	[Tjnz] = "jnz",
+	[Tret] = "ret",
+	[Texport] = "export",
+	[Tfunc] = "function",
+	[Ttype] = "type",
+	[Tdata] = "data",
+	[Talign] = "align",
+	[Tl] = "l",
+	[Tw] = "w",
+	[Th] = "h",
+	[Tb] = "b",
+	[Td] = "d",
+	[Ts] = "s",
+	[Tz] = "z",
+};
+
+enum {
+	/* found using tools/lexh.c */
+	K = 2948605,
+	M = 23,
+};
 
+static char lexh[1 << (32-M)];
 static FILE *inf;
 static char *inpath;
 static int thead;
@@ -169,38 +212,42 @@ err(char *s, ...)
 	exit(1);
 }
 
+static inline long
+tokh(char *s)
+{
+	uint32_t h;
+
+	h = 0;
+	for (; *s; ++s)
+		h = *s + 5*h;
+	return h*K >> M;
+}
+
+static void
+lexinit()
+{
+	static int done;
+	int i;
+	long h;
+
+	if (done)
+		return;
+	for (i=0; i<NPubOp; ++i)
+		if (opdesc[i].name)
+			kwmap[i] = opdesc[i].name;
+	assert(Ntok <= CHAR_MAX);
+	for (i=0; i<Ntok; ++i)
+		if (kwmap[i]) {
+			h = tokh(kwmap[i]);
+			assert(lexh[h] == Txxx);
+			lexh[h] = i;
+		}
+	done = 1;
+}
+
 static int
 lex()
 {
-	static struct {
-		char *str;
-		int tok;
-	} tmap[] = {
-		{ "call", Tcall },
-		{ "phi", Tphi },
-		{ "jmp", Tjmp },
-		{ "jnz", Tjnz },
-		{ "ret", Tret },
-		{ "export", Texport },
-		{ "function", Tfunc },
-		{ "type", Ttype },
-		{ "data", Tdata },
-		{ "align", Talign },
-		{ "l", Tl },
-		{ "w", Tw },
-		{ "h", Th },
-		{ "b", Tb },
-		{ "d", Td },
-		{ "s", Ts },
-		{ "z", Tz },
-		{ "loadw", Oload }, /* for convenience */
-		{ "loadl", Oload },
-		{ "loads", Oload },
-		{ "loadd", Oload },
-		{ "alloc1", Oalloc },
-		{ "alloc2", Oalloc },
-		{ 0, Txxx }
-	};
 	static char tok[NString];
 	int c, i, esc;
 	int t;
@@ -293,15 +340,12 @@ Alpha:		c = fgetc(inf);
 	if (t != Txxx) {
 		return t;
 	}
-	for (i=0; i<NPubOp; i++)
-		if (opdesc[i].name)
-		if (strcmp(tok, opdesc[i].name) == 0)
-			return i;
-	for (i=0; tmap[i].str; i++)
-		if (strcmp(tok, tmap[i].str) == 0)
-			return tmap[i].tok;
-	err("unknown keyword %s", tokval.str);
-	return Txxx;
+	t = lexh[tokh(tok)];
+	if (t == Txxx || strcmp(kwmap[t], tok) != 0) {
+		err("unknown keyword %s", tok);
+		return Txxx;
+	}
+	return t;
 }
 
 static int
@@ -602,6 +646,10 @@ DoOp:
 			arg[1] = R;
 		goto Ins;
 	}
+	if (op >= Tloadw && op <= Tloadd)
+		op = Oload;
+	if (op == Talloc1 || op == Talloc2)
+		op = Oalloc;
 	if (k == 4)
 		err("size class must be w, l, s, or d");
 	if (op >= NPubOp)
@@ -1010,6 +1058,7 @@ parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
 {
 	int t, export;
 
+	lexinit();
 	inf = f;
 	inpath = path;
 	lnum = 1;