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);