shithub: scc

Download patch

ref: 50d3a85c81eabcd5dcc9cb7f6da8380b07acf65a
parent: c8eab2fc68e164fc11882859499896bbb8e76f3d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Jan 25 09:55:23 EST 2018

[as] Move parser stuff to parser.c

--- a/as/as.h
+++ b/as/as.h
@@ -169,17 +169,18 @@
 #ifdef stdin
 extern int nextline(FILE *fp, struct line *linep);
 #endif
+extern void unexpected(void);
+extern void expect(int token);
+int next(void);
+#define accept(t) (yytoken == (t) ? next() : 0)
+extern void regctx(int mode);
+extern Node *getreg(void);
+extern Node *operand(char **s);
 
 /* expr.c */
-extern Node *operand(char **s);
 extern Node *expr(void);
 extern void deltree(Node *np);
 extern Node *node(int op, Node *l, Node *r);
-extern Node *getreg(void);
-extern void regctx(void);
-extern void unexpected(void);
-extern void expect(int token);
-int next(void);
 
 /* proc.c */
 extern void iarch(void);
@@ -214,3 +215,4 @@
 extern int yytoken;
 extern size_t yylen;
 extern union yylval yylval;
+extern char yytext[];
--- a/as/expr.c
+++ b/as/expr.c
@@ -1,26 +1,16 @@
 static char sccsid[] = "@(#) ./as/expr.c";
 
 #include <ctype.h>
-#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <cstd.h>
 #include "../inc/scc.h"
 #include "as.h"
 
 #define NNODES   10
 
-int yytoken;
-size_t yylen;
-union yylval yylval;
-
 static Alloc *arena;
-static char yytext[INTIDENTSIZ+1], *textp, *endp;
-static int regmode;
 
-#define accept(t) (yytoken == (t) ? next() : 0)
-
 Node *
 node(int op, Node *l, Node *r)
 {
@@ -167,185 +157,6 @@
 	return np;
 }
 
-static int
-follow(int expect1, int expect2, int ifyes1, int ifyes2, int ifno)
-{
-	int c;
-
-	if ((c = *++textp) == expect1)
-		return ifyes1;
-	if (c == expect2)
-		return ifyes2;
-	--textp;
-	return ifno;
-}
-
-static void
-tok2str(void)
-{
-	if ((yylen = endp - textp) > INTIDENTSIZ) {
-		error("token too big");
-		yylen = INTIDENTSIZ;
-	}
-	memcpy(yytext, textp, yylen);
-	yytext[yylen] = '\0';
-	textp = endp;
-}
-
-static int
-iden(void)
-{
-	int c;
-	char *p;
-
-	for ( ; c = *endp; ++endp) {
-		if (isalnum(c))
-			continue;
-		switch (c) {
-		case '\'':
-		case '_':
-		case '-':
-		case '.':
-		case '$':
-			continue;
-		default:
-			goto out_loop;
-		}
-	}
-
-out_loop:
-	tok2str();
-	yylval.sym = lookup(yytext);
-
-	return ((yylval.sym->flags & FTMASK) == FREG) ? REG : IDEN;
-}
-
-static int
-number(void)
-{
-	int c, base = 10;
-	char *p;
-	TUINT n;
-
-	if (*endp == '0') {
-		base = 8;
-		++endp;
-		if (*endp == 'x') {
-			base = 16;
-			++endp;
-		}
-	}
-	for (n = 0; (c = *endp) && isxdigit(c); n += c) {
-		n *= base;
-		c -= '0';
-		if (n >= TUINT_MAX - c*base)
-			error("overflow in number");
-		endp++;
-	}
-	tok2str();
-	yylval.sym = tmpsym(n);
-
-	return NUMBER;
-}
-
-static int
-character(void)
-{
-	int c;
-	char *p;
-
-	while (*endp != '\'')
-		++endp;
-	return NUMBER;
-}
-
-static int
-string(void)
-{
-	int c;
-	char *p;
-
-	for (++endp; *endp != '"'; ++endp)
-		;
-	++endp;
-	tok2str();
-	yylval.sym = tmpsym(0);
-	/* FIXME: this memory is not freed ever */
-	yylval.sym->name.buf = xstrdup(yytext);
-
-	return STRING;
-}
-
-static int
-operator(void)
-{
-	int c;
-
-	++endp;
-	if ((c = *textp) == '>')
-		c = follow('=', '>', LE, SHL, '>');
-	else if (c == '<')
-		c = follow('=', '<', GE, SHR, '>');
-	tok2str();
-
-	return c;
-}
-
-int
-next(void)
-{
-	int c;
-
-	while (isspace(*textp))
-		++textp;
-
-	endp = textp;
-
-	switch (c = *textp) {
-	case '\0':
-		strcpy(yytext, "EOS");
-		yylen = 3;
-		c = EOS;
-		break;
-	case '"':
-		c = string();
-		break;
-	case '\'':
-		c = character();
-		break;
-	case '%':
-		c = (regmode ? iden : operator)();
-		break;
-	case '_':
-		c = iden();
-		break;
-	default:
-		if (isdigit(c))
-			c = number();
-		else if (isalpha(c))
-			c = iden();
-		else
-			c = operator();
-		break;
-	}
-	return yytoken = c;
-}
-
-void
-expect(int token)
-{
-	if (yytoken != token)
-		unexpected();
-	next();
-}
-
-void
-unexpected(void)
-{
-	error("unexpected '%s'", yytext);
-}
-
-
 /*************************************************************************/
 /* grammar functions                                                     */
 /*************************************************************************/
@@ -387,10 +198,6 @@
 	Node *np;
 
 	switch (tok = yytoken) {
-	case '%':
-	case '$':
-	case '.':
-		/* TODO: implement identifiers with %, $ and . */
 	case '!':
 	case '-':
 	case '+':
@@ -485,7 +292,7 @@
 	int op;
 	Node *np;
 
-	regmode = 0;
+	regctx(0);
 	np = and();
 	for (;;) {
 		switch (op = yytoken) {
@@ -495,58 +302,8 @@
 			np = binary(op, np, and());
 			break;
 		default:
+			regctx(1);
 			return np;
 		}
 	}
-}
-
-Node *
-getreg(void)
-{
-	Node *np;
-
-	np = node(REG, NULL, NULL);
-	np->sym = yylval.sym;
-	np->addr = AREG;
-	expect(REG);
-	return np;
-}
-
-void
-regctx(void)
-{
-	regmode = 1;
-}
-
-Node *
-operand(char **strp)
-{
-	int imm = 0;
-	Node *np;
-
-	textp = *strp;
-	regctx();
-	switch (next()) {
-	case EOS:
-		np = NULL;
-		break;
-	case REG:
-		np = getreg();
-		break;
-	case '$':
-		next();
-		imm = 1;
-	default:
-		if (!imm) {
-			np = moperand();
-		} else {
-			np = expr();
-			np->addr = AIMM;
-		}
-	}
-	if (yytoken != ',' && yytoken != EOS)
-		error("trailing characters in expression '%s'", textp);
-	*strp = endp;
-
-	return np;
 }
--- a/as/parser.c
+++ b/as/parser.c
@@ -1,5 +1,6 @@
 static char sccsid[] = "@(#) ./as/parser.c";
 #include <ctype.h>
+#include <limits.h>
 #include <setjmp.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -6,6 +7,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <cstd.h>
 #include "../inc/scc.h"
 #include "as.h"
 
@@ -14,10 +16,194 @@
 
 int nerrors;
 jmp_buf recover;
+char yytext[INTIDENTSIZ+1];
+int yytoken;
+size_t yylen;
+union yylval yylval;
 
+static char *textp, *endp;
+static int regmode;
 static unsigned lineno;
 
+static int
+follow(int expect1, int expect2, int ifyes1, int ifyes2, int ifno)
+{
+	int c;
+
+	if ((c = *++textp) == expect1)
+		return ifyes1;
+	if (c == expect2)
+		return ifyes2;
+	--textp;
+	return ifno;
+}
+
+static void
+tok2str(void)
+{
+	if ((yylen = endp - textp) > INTIDENTSIZ) {
+		error("token too big");
+		yylen = INTIDENTSIZ;
+	}
+	memcpy(yytext, textp, yylen);
+	yytext[yylen] = '\0';
+	textp = endp;
+}
+
+static int
+iden(void)
+{
+	int c;
+	char *p;
+
+	for ( ; c = *endp; ++endp) {
+		if (isalnum(c))
+			continue;
+		switch (c) {
+		case '\'':
+		case '_':
+		case '-':
+		case '.':
+		case '$':
+			continue;
+		default:
+			goto out_loop;
+		}
+	}
+
+out_loop:
+	tok2str();
+	yylval.sym = lookup(yytext);
+
+	return ((yylval.sym->flags & FTMASK) == FREG) ? REG : IDEN;
+}
+
+static int
+number(void)
+{
+	int c, base = 10;
+	char *p;
+	TUINT n;
+
+	if (*endp == '0') {
+		base = 8;
+		++endp;
+		if (*endp == 'x') {
+			base = 16;
+			++endp;
+		}
+	}
+	for (n = 0; (c = *endp) && isxdigit(c); n += c) {
+		n *= base;
+		c -= '0';
+		if (n >= TUINT_MAX - c*base)
+			error("overflow in number");
+		endp++;
+	}
+	tok2str();
+	yylval.sym = tmpsym(n);
+
+	return NUMBER;
+}
+
+static int
+character(void)
+{
+	int c;
+	char *p;
+
+	while (*endp != '\'')
+		++endp;
+	return NUMBER;
+}
+
+static int
+string(void)
+{
+	int c;
+	char *p;
+
+	for (++endp; *endp != '"'; ++endp)
+		;
+	++endp;
+	tok2str();
+	yylval.sym = tmpsym(0);
+	/* FIXME: this memory is not freed ever */
+	yylval.sym->name.buf = xstrdup(yytext);
+
+	return STRING;
+}
+
+static int
+operator(void)
+{
+	int c;
+
+	++endp;
+	if ((c = *textp) == '>')
+		c = follow('=', '>', LE, SHL, '>');
+	else if (c == '<')
+		c = follow('=', '<', GE, SHR, '>');
+	tok2str();
+
+	return c;
+}
+
+int
+next(void)
+{
+	int c;
+
+	while (isspace(*textp))
+		++textp;
+
+	endp = textp;
+
+	switch (c = *textp) {
+	case '\0':
+		strcpy(yytext, "EOS");
+		yylen = 3;
+		c = EOS;
+		break;
+	case '"':
+		c = string();
+		break;
+	case '\'':
+		c = character();
+		break;
+	case '%':
+		c = (regmode ? iden : operator)();
+		break;
+	case '_':
+		c = iden();
+		break;
+	default:
+		if (isdigit(c))
+			c = number();
+		else if (isalpha(c))
+			c = iden();
+		else
+			c = operator();
+		break;
+	}
+	return yytoken = c;
+}
+
 void
+expect(int token)
+{
+	if (yytoken != token)
+		unexpected();
+	next();
+}
+
+void
+unexpected(void)
+{
+	error("unexpected '%s'", yytext);
+}
+
+void
 error(char *msg, ...)
 {
 	va_list va;
@@ -32,6 +218,57 @@
 	if (nerrors == 10)
 		die("as: too many errors");
 	longjmp(recover, 1);
+}
+
+Node *
+getreg(void)
+{
+	Node *np;
+
+	np = node(REG, NULL, NULL);
+	np->sym = yylval.sym;
+	np->addr = AREG;
+	expect(REG);
+	return np;
+}
+
+void
+regctx(int mode)
+{
+	regmode = mode;
+}
+
+Node *
+operand(char **strp)
+{
+	int imm = 0;
+	Node *np;
+
+	textp = *strp;
+	regctx(1);
+	switch (next()) {
+	case EOS:
+		np = NULL;
+		break;
+	case REG:
+		np = getreg();
+		break;
+	case '$':
+		next();
+		imm = 1;
+	default:
+		if (!imm) {
+			np = moperand();
+		} else {
+			np = expr();
+			np->addr = AIMM;
+		}
+	}
+	if (yytoken != ',' && yytoken != EOS)
+		error("trailing characters in expression '%s'", textp);
+	*strp = endp;
+
+	return np;
 }
 
 Node **
--- a/as/target/x80/ins.c
+++ b/as/target/x80/ins.c
@@ -14,6 +14,56 @@
  *	  writers - by Cristian Dinu.
  */
 
+static int
+getclass(Node *np)
+{
+	if (np->addr != AREG)
+		return 0;
+
+	switch (np->sym->value) {
+	case AREG_C:
+		return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS;
+	case AREG_A:
+	case AREG_B:
+	case AREG_D:
+	case AREG_E:
+		return RCLASS | PCLASS | QCLASS;
+	case AREG_H:
+	case AREG_L:
+		return RCLASS;
+	case AREG_IXL:
+	case AREG_IXH:
+		return PCLASS;
+	case AREG_IYL:
+	case AREG_IYH:
+		return QCLASS;
+	case AREG_HL:
+		return DDCLASS | QQCLASS;
+	case AREG_BC:
+	case AREG_DE:
+		return DDCLASS | QQCLASS | PPCLASS | RRCLASS;
+	case AREG_SP:
+		return DDCLASS | PPCLASS | RRCLASS;
+	case AREG_AF:
+		return QQCLASS;
+	case AREG_IX:
+		return PPCLASS;
+	case AREG_IY:
+		return RRCLASS;
+	case AREG_PO:
+	case AREG_PE:
+	case AREG_P:
+	case AREG_M:
+		return CCCLASS;
+	case AREG_NZ:
+	case AREG_Z:
+	case AREG_NC:
+		return CCCLASS | SSCLASS;
+	default:
+		return 0;
+	}
+}
+
 int
 match(Op *op, Node **args)
 {
@@ -162,9 +212,8 @@
 	Node *np, *dir, *off, *reg;
 
 	dir = off = reg = NULL;
-	if (yytoken == '(') {
-		regctx();
-		if (next() != REG) {
+	if (accept('(')) {
+		if (yytoken != REG) {
 			dir = expr();
 		} else {
 			reg = getreg();
@@ -180,7 +229,6 @@
 		}
 	} else {
 		off = expr();
-		regctx();
 		expect('(');
 		reg = getreg();
 	}
@@ -199,56 +247,6 @@
 	np = node(op, np, NULL);
 	np->addr = op;
 	return np;
-}
-
-int
-getclass(Node *np)
-{
-	if (np->addr != AREG)
-		return 0;
-
-	switch (np->sym->value) {
-	case AREG_C:
-		return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS;
-	case AREG_A:
-	case AREG_B:
-	case AREG_D:
-	case AREG_E:
-		return RCLASS | PCLASS | QCLASS;
-	case AREG_H:
-	case AREG_L:
-		return RCLASS;
-	case AREG_IXL:
-	case AREG_IXH:
-		return PCLASS;
-	case AREG_IYL:
-	case AREG_IYH:
-		return QCLASS;
-	case AREG_HL:
-		return DDCLASS | QQCLASS;
-	case AREG_BC:
-	case AREG_DE:
-		return DDCLASS | QQCLASS | PPCLASS | RRCLASS;
-	case AREG_SP:
-		return DDCLASS | PPCLASS | RRCLASS;
-	case AREG_AF:
-		return QQCLASS;
-	case AREG_IX:
-		return PPCLASS;
-	case AREG_IY:
-		return RRCLASS;
-	case AREG_PO:
-	case AREG_PE:
-	case AREG_P:
-	case AREG_M:
-		return CCCLASS;
-	case AREG_NZ:
-	case AREG_Z:
-	case AREG_NC:
-		return CCCLASS | SSCLASS;
-	default:
-		return 0;
-	}
 }
 
 static int
--- a/as/target/x80/proc.h
+++ b/as/target/x80/proc.h
@@ -74,5 +74,3 @@
 	CCCLASS = 1 << 7,
 	SSCLASS = 1 << 8,
 };
-
-extern int getclass(Node *np);