scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 06b6530a32e99483eec6a54b9510de6f40d0e6f0
parent ce6c64b4ef06cc210573c019a6255abbc0b024d2
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 25 Jan 2018 14:55:23 +0100

[as] Move parser stuff to parser.c

Diffstat:
Mas/as.h | 14++++++++------
Mas/expr.c | 247+------------------------------------------------------------------------------
Mas/parser.c | 237+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mas/target/x80/ins.c | 106+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mas/target/x80/proc.h | 2--
5 files changed, 299 insertions(+), 307 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -169,17 +169,18 @@ extern void error(char *msg, ...); #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 endpass; extern int yytoken; extern size_t yylen; extern union yylval yylval; +extern char yytext[]; diff --git a/as/expr.c b/as/expr.c @@ -1,25 +1,15 @@ 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 @@ unaryop(int op, Node *np) 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 @@ unary(void) Node *np; switch (tok = yytoken) { - case '%': - case '$': - case '.': - /* TODO: implement identifiers with %, $ and . */ case '!': case '-': case '+': @@ -485,7 +292,7 @@ expr(void) int op; Node *np; - regmode = 0; + regctx(0); np = and(); for (;;) { switch (op = yytoken) { @@ -495,58 +302,8 @@ expr(void) 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; -} diff --git a/as/parser.c b/as/parser.c @@ -1,11 +1,13 @@ static char sccsid[] = "@(#) ./as/parser.c"; #include <ctype.h> +#include <limits.h> #include <setjmp.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <cstd.h> #include "../inc/scc.h" #include "as.h" @@ -14,9 +16,193 @@ static char sccsid[] = "@(#) ./as/parser.c"; 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, ...) { @@ -34,6 +220,57 @@ error(char *msg, ...) 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 ** getargs(char *s) { diff --git a/as/target/x80/ins.c b/as/target/x80/ins.c @@ -14,6 +14,56 @@ static char sccsid[] = "@(#) ./as/target/x80/ins.c"; * 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 @@ moperand(void) 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 @@ moperand(void) } } else { off = expr(); - regctx(); expect('('); reg = getreg(); } @@ -201,56 +249,6 @@ moperand(void) 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 reg2int(Node *np) { diff --git a/as/target/x80/proc.h b/as/target/x80/proc.h @@ -74,5 +74,3 @@ enum { CCCLASS = 1 << 7, SSCLASS = 1 << 8, }; - -extern int getclass(Node *np);