From 9fc685a2237b789800b770f3bc1eecb8e1bfdf7b Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 19 Aug 2021 07:52:26 +0000 Subject: c4: added switch statement --- miniany/c4.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'miniany/c4.c') diff --git a/miniany/c4.c b/miniany/c4.c index a36fb4a..9acba4e 100644 --- a/miniany/c4.c +++ b/miniany/c4.c @@ -18,6 +18,9 @@ char *p, *lp, // current position in source code *data; // data/bss pointer int *e, *le, // current position in emitted code + *cas, // case statement patch-up pointer + *brak, // break statement patch-up pointer + *def, // default statement patch-up pointer *id, // currently parsed identifier *sym, // symbol table (simple list of identifiers) tk, // current token @@ -31,7 +34,7 @@ int *e, *le, // current position in emitted code // tokens and classes (operators last and in precedence order) enum { Num = 128, Fun, Sys, Glo, Loc, Id, - Char, Else, Enum, If, Int, Return, Sizeof, Do, While, + Break, Case, Char, Default, Else, Enum, If, Int, Return, Sizeof, Do, Switch, While, Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak }; @@ -59,7 +62,7 @@ void next() while (le < e) { printf("%8.4s", &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ," "OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ," - "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,EXIT,"[*++le * 5]); + "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU,IALP,SCMP,EXIT,"[*++le * 5]); if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n"); } } @@ -293,7 +296,7 @@ void expr(int lev) void stmt() { - int *a, *b; + int *a, *b, *d, i; if (tk == If) { next(); @@ -333,6 +336,43 @@ void stmt() *++e = JMP; *++e = (int)a; *b = (int)(e + 1); } + else if (tk == Switch) { + next(); + if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); } + expr(Assign); + if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); } + a = cas; *++e = JMP; cas = ++e; + b = brak; d = def; brak = def = 0; + stmt(); + *cas = def ? (int)def : (int)(e + 1); cas = a; + while (brak) { a = (int *)*brak; *brak = (int)(e + 1); brak = a; } + brak = b; def = d; + } + else if (tk == Case) { + *++e = JMP; ++e; *e = (int)(e + 7); *++e = PSH; i = *cas; *cas = (int)e; + next(); + expr(Or); + if (e[-1] != IMM) { printf("%d: bad case immediate\n", line); exit(-1); } + *e = *e - i; *++e = SUB; *++e = BNZ; cas = ++e; *e = i + e[-3]; + if (tk == ':') { + next(); + } + else { + printf("%d: colon expected\n", line); exit(-1); + } + stmt(); + } + else if (tk == Break) { + next(); + if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); } + *++e = JMP; *++e = (int)brak; brak = e; + } + else if (tk == Default) { + next(); + if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); } + def = e + 1; + stmt(); + } else if (tk == Return) { next(); if (tk != ';') expr(Assign); @@ -376,10 +416,10 @@ int main(int argc, char **argv) memset(e, 0, poolsz); memset(data, 0, poolsz); - p = "char else enum if int return sizeof do while " + p = "break case char default else enum if int return sizeof do switch while " "EOF EXIT_SUCCESS EXIT_FAILURE NULL " "open read close printf malloc free memset memcmp getchar putstring putnl putchar putint isspace isdigit isalnum isalpha strcmp exit void main"; - i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table + i = Break; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table // add library constants next(); id[Class] = Num; id[Type] = INT; id[Val] = -1; next(); id[Class] = Num; id[Type] = INT; id[Val] = 0; -- cgit v1.2.3-54-g00ecf