summaryrefslogtreecommitdiff
path: root/miniany/c4.c
diff options
context:
space:
mode:
Diffstat (limited to 'miniany/c4.c')
-rw-r--r--miniany/c4.c50
1 files changed, 45 insertions, 5 deletions
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;