Compare commits
8 commits
switch-sta
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f098f3ea8 | ||
|
|
6884cb4de9 | ||
|
|
567db57ef2 | ||
|
|
461f117cda | ||
|
|
80db11debf | ||
|
|
32b33ff4f6 | ||
|
|
e78a343e1d | ||
|
|
021abbc0b4 |
2 changed files with 146 additions and 196 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
c4 - C in four functions
|
c4 - C in four functions
|
||||||
========================
|
========================
|
||||||
|
|
||||||
An exercise in minimalism. **This branch adds switch statement support.**
|
An exercise in minimalism.
|
||||||
|
|
||||||
Try the following:
|
Try the following:
|
||||||
|
|
||||||
|
|
|
||||||
340
c4.c
340
c4.c
|
|
@ -1,15 +1,15 @@
|
||||||
// c4.c - C in four functions
|
// c4.c - C in four functions
|
||||||
|
|
||||||
// char, int, and pointer types
|
// char, int, and pointer types
|
||||||
// if, while, return, switch, and expression statements
|
// if, while, return, and expression statements
|
||||||
// just enough features to allow self-compilation and a bit more
|
// just enough features to allow self-compilation and a bit more
|
||||||
|
|
||||||
// Written by Robert Swierczek
|
// Written by Robert Swierczek
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
char *p, *lp, // current position in source code
|
char *p, *lp, // current position in source code
|
||||||
|
|
@ -18,9 +18,6 @@ char *p, *lp, // current position in source code
|
||||||
int *e, *le, // current position in emitted code
|
int *e, *le, // current position in emitted code
|
||||||
*id, // currently parsed identifier
|
*id, // currently parsed identifier
|
||||||
*sym, // symbol table (simple list of identifiers)
|
*sym, // symbol table (simple list of identifiers)
|
||||||
*cas, // case statement patch-up pointer
|
|
||||||
*brk, // break statement patch-up pointer
|
|
||||||
*def, // default statement patch-up pointer
|
|
||||||
tk, // current token
|
tk, // current token
|
||||||
ival, // current token value
|
ival, // current token value
|
||||||
ty, // current expression type
|
ty, // current expression type
|
||||||
|
|
@ -32,14 +29,14 @@ int *e, *le, // current position in emitted code
|
||||||
// tokens and classes (operators last and in precedence order)
|
// tokens and classes (operators last and in precedence order)
|
||||||
enum {
|
enum {
|
||||||
Num = 128, Fun, Sys, Glo, Loc, Id,
|
Num = 128, Fun, Sys, Glo, Loc, Id,
|
||||||
Break, Case, Char, Default, Else, Enum, If, Int, Return, Sizeof, Switch, While,
|
Char, Else, Enum, If, Int, Return, Sizeof, While,
|
||||||
Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak
|
Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak
|
||||||
};
|
};
|
||||||
|
|
||||||
// opcodes
|
// opcodes
|
||||||
enum { LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,
|
enum { 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 ,
|
OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,
|
||||||
OPEN,READ,CLOS,PRTF,MALC,MSET,MCMP,EXIT };
|
OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT };
|
||||||
|
|
||||||
// types
|
// types
|
||||||
enum { CHAR, INT, PTR };
|
enum { CHAR, INT, PTR };
|
||||||
|
|
@ -53,7 +50,23 @@ void next()
|
||||||
|
|
||||||
while (tk = *p) {
|
while (tk = *p) {
|
||||||
++p;
|
++p;
|
||||||
if ((tk >= 'a' && tk <= 'z') || (tk >= 'A' && tk <= 'Z') || tk == '_') {
|
if (tk == '\n') {
|
||||||
|
if (src) {
|
||||||
|
printf("%d: %.*s", line, p - lp, lp);
|
||||||
|
lp = p;
|
||||||
|
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,EXIT,"[*++le * 5]);
|
||||||
|
if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++line;
|
||||||
|
}
|
||||||
|
else if (tk == '#') {
|
||||||
|
while (*p != 0 && *p != '\n') ++p;
|
||||||
|
}
|
||||||
|
else if ((tk >= 'a' && tk <= 'z') || (tk >= 'A' && tk <= 'Z') || tk == '_') {
|
||||||
pp = p - 1;
|
pp = p - 1;
|
||||||
while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_')
|
while ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_')
|
||||||
tk = tk * 147 + *p++;
|
tk = tk * 147 + *p++;
|
||||||
|
|
@ -78,25 +91,7 @@ void next()
|
||||||
tk = Num;
|
tk = Num;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (tk) {
|
else if (tk == '/') {
|
||||||
case '\n':
|
|
||||||
if (src) {
|
|
||||||
printf("%d: %.*s", line, p - lp, lp);
|
|
||||||
lp = p;
|
|
||||||
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,MSET,MCMP,EXIT,"[*++le * 5]);
|
|
||||||
if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++line;
|
|
||||||
case ' ': case '\t': case '\v': case '\f': case '\r':
|
|
||||||
break;
|
|
||||||
case '#':
|
|
||||||
while (*p != 0 && *p != '\n') ++p;
|
|
||||||
break;
|
|
||||||
case '/':
|
|
||||||
if (*p == '/') {
|
if (*p == '/') {
|
||||||
++p;
|
++p;
|
||||||
while (*p != 0 && *p != '\n') ++p;
|
while (*p != 0 && *p != '\n') ++p;
|
||||||
|
|
@ -105,40 +100,33 @@ void next()
|
||||||
tk = Div;
|
tk = Div;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case '\'':
|
else if (tk == '\'' || tk == '"') {
|
||||||
case '"':
|
|
||||||
pp = data;
|
pp = data;
|
||||||
while (*p != 0 && *p != tk) {
|
while (*p != 0 && *p != tk) {
|
||||||
if ((ival = *p++) == '\\') {
|
if ((ival = *p++) == '\\') {
|
||||||
switch (ival = *p++) {
|
if ((ival = *p++) == 'n') ival = '\n';
|
||||||
case 'n': ival = '\n'; break;
|
|
||||||
case 't': ival = '\t'; break;
|
|
||||||
case 'v': ival = '\v'; break;
|
|
||||||
case 'f': ival = '\f'; break;
|
|
||||||
case 'r': ival = '\r';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (tk == '"') *data++ = ival;
|
if (tk == '"') *data++ = ival;
|
||||||
}
|
}
|
||||||
++p;
|
++p;
|
||||||
if (tk == '"') ival = (int)pp; else tk = Num;
|
if (tk == '"') ival = (int)pp; else tk = Num;
|
||||||
return;
|
return;
|
||||||
case '=': if (*p == '=') { ++p; tk = Eq; } else tk = Assign; return;
|
|
||||||
case '+': if (*p == '+') { ++p; tk = Inc; } else tk = Add; return;
|
|
||||||
case '-': if (*p == '-') { ++p; tk = Dec; } else tk = Sub; return;
|
|
||||||
case '!': if (*p == '=') { ++p; tk = Ne; } return;
|
|
||||||
case '<': if (*p == '=') { ++p; tk = Le; } else if (*p == '<') { ++p; tk = Shl; } else tk = Lt; return;
|
|
||||||
case '>': if (*p == '=') { ++p; tk = Ge; } else if (*p == '>') { ++p; tk = Shr; } else tk = Gt; return;
|
|
||||||
case '|': if (*p == '|') { ++p; tk = Lor; } else tk = Or; return;
|
|
||||||
case '&': if (*p == '&') { ++p; tk = Lan; } else tk = And; return;
|
|
||||||
case '^': tk = Xor; return;
|
|
||||||
case '%': tk = Mod; return;
|
|
||||||
case '*': tk = Mul; return;
|
|
||||||
case '[': tk = Brak; return;
|
|
||||||
case '?': tk = Cond; return;
|
|
||||||
default: return;
|
|
||||||
}
|
}
|
||||||
|
else if (tk == '=') { if (*p == '=') { ++p; tk = Eq; } else tk = Assign; return; }
|
||||||
|
else if (tk == '+') { if (*p == '+') { ++p; tk = Inc; } else tk = Add; return; }
|
||||||
|
else if (tk == '-') { if (*p == '-') { ++p; tk = Dec; } else tk = Sub; return; }
|
||||||
|
else if (tk == '!') { if (*p == '=') { ++p; tk = Ne; } return; }
|
||||||
|
else if (tk == '<') { if (*p == '=') { ++p; tk = Le; } else if (*p == '<') { ++p; tk = Shl; } else tk = Lt; return; }
|
||||||
|
else if (tk == '>') { if (*p == '=') { ++p; tk = Ge; } else if (*p == '>') { ++p; tk = Shr; } else tk = Gt; return; }
|
||||||
|
else if (tk == '|') { if (*p == '|') { ++p; tk = Lor; } else tk = Or; return; }
|
||||||
|
else if (tk == '&') { if (*p == '&') { ++p; tk = Lan; } else tk = And; return; }
|
||||||
|
else if (tk == '^') { tk = Xor; return; }
|
||||||
|
else if (tk == '%') { tk = Mod; return; }
|
||||||
|
else if (tk == '*') { tk = Mul; return; }
|
||||||
|
else if (tk == '[') { tk = Brak; return; }
|
||||||
|
else if (tk == '?') { tk = Cond; return; }
|
||||||
|
else if (tk == '~' || tk == ';' || tk == '{' || tk == '}' || tk == '(' || tk == ')' || tk == ']' || tk == ',' || tk == ':') return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,23 +134,22 @@ void expr(int lev)
|
||||||
{
|
{
|
||||||
int t, *d;
|
int t, *d;
|
||||||
|
|
||||||
switch (tk) {
|
if (!tk) { printf("%d: unexpected eof in expression\n", line); exit(-1); }
|
||||||
case 0: printf("%d: unexpected eof in expression\n", line); exit(-1);
|
else if (tk == Num) { *++e = IMM; *++e = ival; next(); ty = INT; }
|
||||||
case Num: *++e = IMM; *++e = ival; next(); ty = INT; break;
|
else if (tk == '"') {
|
||||||
case '"':
|
|
||||||
*++e = IMM; *++e = ival; next();
|
*++e = IMM; *++e = ival; next();
|
||||||
while (tk == '"') next();
|
while (tk == '"') next();
|
||||||
data = (char *)((int)data + sizeof(int) & -sizeof(int)); ty = PTR;
|
data = (char *)((int)data + sizeof(int) & -sizeof(int)); ty = PTR;
|
||||||
break;
|
}
|
||||||
case Sizeof:
|
else if (tk == Sizeof) {
|
||||||
next(); if (tk == '(') next(); else { printf("%d: open paren expected in sizeof\n", line); exit(-1); }
|
next(); if (tk == '(') next(); else { printf("%d: open paren expected in sizeof\n", line); exit(-1); }
|
||||||
ty = INT; if (tk == Int) next(); else if (tk == Char) { next(); ty = CHAR; }
|
ty = INT; if (tk == Int) next(); else if (tk == Char) { next(); ty = CHAR; }
|
||||||
while (tk == Mul) { next(); ty = ty + PTR; }
|
while (tk == Mul) { next(); ty = ty + PTR; }
|
||||||
if (tk == ')') next(); else { printf("%d: close paren expected in sizeof\n", line); exit(-1); }
|
if (tk == ')') next(); else { printf("%d: close paren expected in sizeof\n", line); exit(-1); }
|
||||||
*++e = IMM; *++e = (ty == CHAR) ? sizeof(char) : sizeof(int);
|
*++e = IMM; *++e = (ty == CHAR) ? sizeof(char) : sizeof(int);
|
||||||
ty = INT;
|
ty = INT;
|
||||||
break;
|
}
|
||||||
case Id:
|
else if (tk == Id) {
|
||||||
d = id; next();
|
d = id; next();
|
||||||
if (tk == '(') {
|
if (tk == '(') {
|
||||||
next();
|
next();
|
||||||
|
|
@ -182,8 +169,8 @@ void expr(int lev)
|
||||||
else { printf("%d: undefined variable\n", line); exit(-1); }
|
else { printf("%d: undefined variable\n", line); exit(-1); }
|
||||||
*++e = ((ty = d[Type]) == CHAR) ? LC : LI;
|
*++e = ((ty = d[Type]) == CHAR) ? LC : LI;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case '(':
|
else if (tk == '(') {
|
||||||
next();
|
next();
|
||||||
if (tk == Int || tk == Char) {
|
if (tk == Int || tk == Char) {
|
||||||
t = (tk == Int) ? INT : CHAR; next();
|
t = (tk == Int) ? INT : CHAR; next();
|
||||||
|
|
@ -196,26 +183,26 @@ void expr(int lev)
|
||||||
expr(Assign);
|
expr(Assign);
|
||||||
if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); }
|
if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); }
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case Mul:
|
else if (tk == Mul) {
|
||||||
next(); expr(Inc);
|
next(); expr(Inc);
|
||||||
if (ty > INT) ty = ty - PTR; else { printf("%d: bad dereference\n", line); exit(-1); }
|
if (ty > INT) ty = ty - PTR; else { printf("%d: bad dereference\n", line); exit(-1); }
|
||||||
*++e = (ty == CHAR) ? LC : LI;
|
*++e = (ty == CHAR) ? LC : LI;
|
||||||
break;
|
}
|
||||||
case And:
|
else if (tk == And) {
|
||||||
next(); expr(Inc);
|
next(); expr(Inc);
|
||||||
if (*e == LC || *e == LI) --e; else { printf("%d: bad address-of\n", line); exit(-1); }
|
if (*e == LC || *e == LI) --e; else { printf("%d: bad address-of\n", line); exit(-1); }
|
||||||
ty = ty + PTR;
|
ty = ty + PTR;
|
||||||
break;
|
}
|
||||||
case '!': next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; break;
|
else if (tk == '!') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = 0; *++e = EQ; ty = INT; }
|
||||||
case '~': next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; break;
|
else if (tk == '~') { next(); expr(Inc); *++e = PSH; *++e = IMM; *++e = -1; *++e = XOR; ty = INT; }
|
||||||
case Add: next(); expr(Inc); ty = INT; break;
|
else if (tk == Add) { next(); expr(Inc); ty = INT; }
|
||||||
case Sub:
|
else if (tk == Sub) {
|
||||||
next(); *++e = IMM;
|
next(); *++e = IMM;
|
||||||
if (tk == Num) { *++e = -ival; next(); } else { *++e = -1; *++e = PSH; expr(Inc); *++e = MUL; }
|
if (tk == Num) { *++e = -ival; next(); } else { *++e = -1; *++e = PSH; expr(Inc); *++e = MUL; }
|
||||||
ty = INT;
|
ty = INT;
|
||||||
break;
|
}
|
||||||
case Inc: case Dec:
|
else if (tk == Inc || tk == Dec) {
|
||||||
t = tk; next(); expr(Inc);
|
t = tk; next(); expr(Inc);
|
||||||
if (*e == LC) { *e = PSH; *++e = LC; }
|
if (*e == LC) { *e = PSH; *++e = LC; }
|
||||||
else if (*e == LI) { *e = PSH; *++e = LI; }
|
else if (*e == LI) { *e = PSH; *++e = LI; }
|
||||||
|
|
@ -224,19 +211,17 @@ void expr(int lev)
|
||||||
*++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char);
|
*++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char);
|
||||||
*++e = (t == Inc) ? ADD : SUB;
|
*++e = (t == Inc) ? ADD : SUB;
|
||||||
*++e = (ty == CHAR) ? SC : SI;
|
*++e = (ty == CHAR) ? SC : SI;
|
||||||
break;
|
|
||||||
default: printf("%d: bad expression\n", line); exit(-1);
|
|
||||||
}
|
}
|
||||||
|
else { printf("%d: bad expression\n", line); exit(-1); }
|
||||||
|
|
||||||
while (tk >= lev) { // "precedence climbing" or "Top Down Operator Precedence" method
|
while (tk >= lev) { // "precedence climbing" or "Top Down Operator Precedence" method
|
||||||
t = ty;
|
t = ty;
|
||||||
switch (tk) {
|
if (tk == Assign) {
|
||||||
case Assign:
|
|
||||||
next();
|
next();
|
||||||
if (*e == LC || *e == LI) *e = PSH; else { printf("%d: bad lvalue in assignment\n", line); exit(-1); }
|
if (*e == LC || *e == LI) *e = PSH; else { printf("%d: bad lvalue in assignment\n", line); exit(-1); }
|
||||||
expr(Assign); *++e = ((ty = t) == CHAR) ? SC : SI;
|
expr(Assign); *++e = ((ty = t) == CHAR) ? SC : SI;
|
||||||
break;
|
}
|
||||||
case Cond:
|
else if (tk == Cond) {
|
||||||
next();
|
next();
|
||||||
*++e = BZ; d = ++e;
|
*++e = BZ; d = ++e;
|
||||||
expr(Assign);
|
expr(Assign);
|
||||||
|
|
@ -244,35 +229,35 @@ void expr(int lev)
|
||||||
*d = (int)(e + 3); *++e = JMP; d = ++e;
|
*d = (int)(e + 3); *++e = JMP; d = ++e;
|
||||||
expr(Cond);
|
expr(Cond);
|
||||||
*d = (int)(e + 1);
|
*d = (int)(e + 1);
|
||||||
break;
|
}
|
||||||
case Lor: next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; break;
|
else if (tk == Lor) { next(); *++e = BNZ; d = ++e; expr(Lan); *d = (int)(e + 1); ty = INT; }
|
||||||
case Lan: next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; break;
|
else if (tk == Lan) { next(); *++e = BZ; d = ++e; expr(Or); *d = (int)(e + 1); ty = INT; }
|
||||||
case Or: next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; break;
|
else if (tk == Or) { next(); *++e = PSH; expr(Xor); *++e = OR; ty = INT; }
|
||||||
case Xor: next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; break;
|
else if (tk == Xor) { next(); *++e = PSH; expr(And); *++e = XOR; ty = INT; }
|
||||||
case And: next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; break;
|
else if (tk == And) { next(); *++e = PSH; expr(Eq); *++e = AND; ty = INT; }
|
||||||
case Eq: next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; break;
|
else if (tk == Eq) { next(); *++e = PSH; expr(Lt); *++e = EQ; ty = INT; }
|
||||||
case Ne: next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; break;
|
else if (tk == Ne) { next(); *++e = PSH; expr(Lt); *++e = NE; ty = INT; }
|
||||||
case Lt: next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; break;
|
else if (tk == Lt) { next(); *++e = PSH; expr(Shl); *++e = LT; ty = INT; }
|
||||||
case Gt: next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; break;
|
else if (tk == Gt) { next(); *++e = PSH; expr(Shl); *++e = GT; ty = INT; }
|
||||||
case Le: next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; break;
|
else if (tk == Le) { next(); *++e = PSH; expr(Shl); *++e = LE; ty = INT; }
|
||||||
case Ge: next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; break;
|
else if (tk == Ge) { next(); *++e = PSH; expr(Shl); *++e = GE; ty = INT; }
|
||||||
case Shl: next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; break;
|
else if (tk == Shl) { next(); *++e = PSH; expr(Add); *++e = SHL; ty = INT; }
|
||||||
case Shr: next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; break;
|
else if (tk == Shr) { next(); *++e = PSH; expr(Add); *++e = SHR; ty = INT; }
|
||||||
case Add:
|
else if (tk == Add) {
|
||||||
next(); *++e = PSH; expr(Mul);
|
next(); *++e = PSH; expr(Mul);
|
||||||
if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; }
|
if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; }
|
||||||
*++e = ADD;
|
*++e = ADD;
|
||||||
break;
|
}
|
||||||
case Sub:
|
else if (tk == Sub) {
|
||||||
next(); *++e = PSH; expr(Mul);
|
next(); *++e = PSH; expr(Mul);
|
||||||
if (t > PTR && t == ty) { *++e = SUB; *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = DIV; ty = INT; }
|
if (t > PTR && t == ty) { *++e = SUB; *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = DIV; ty = INT; }
|
||||||
else if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; *++e = SUB; }
|
else if ((ty = t) > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; *++e = SUB; }
|
||||||
else *++e = SUB;
|
else *++e = SUB;
|
||||||
break;
|
}
|
||||||
case Mul: next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; break;
|
else if (tk == Mul) { next(); *++e = PSH; expr(Inc); *++e = MUL; ty = INT; }
|
||||||
case Div: next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; break;
|
else if (tk == Div) { next(); *++e = PSH; expr(Inc); *++e = DIV; ty = INT; }
|
||||||
case Mod: next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; break;
|
else if (tk == Mod) { next(); *++e = PSH; expr(Inc); *++e = MOD; ty = INT; }
|
||||||
case Inc: case Dec:
|
else if (tk == Inc || tk == Dec) {
|
||||||
if (*e == LC) { *e = PSH; *++e = LC; }
|
if (*e == LC) { *e = PSH; *++e = LC; }
|
||||||
else if (*e == LI) { *e = PSH; *++e = LI; }
|
else if (*e == LI) { *e = PSH; *++e = LI; }
|
||||||
else { printf("%d: bad lvalue in post-increment\n", line); exit(-1); }
|
else { printf("%d: bad lvalue in post-increment\n", line); exit(-1); }
|
||||||
|
|
@ -282,26 +267,24 @@ void expr(int lev)
|
||||||
*++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char);
|
*++e = PSH; *++e = IMM; *++e = (ty > PTR) ? sizeof(int) : sizeof(char);
|
||||||
*++e = (tk == Inc) ? SUB : ADD;
|
*++e = (tk == Inc) ? SUB : ADD;
|
||||||
next();
|
next();
|
||||||
break;
|
}
|
||||||
case Brak:
|
else if (tk == Brak) {
|
||||||
next(); *++e = PSH; expr(Assign);
|
next(); *++e = PSH; expr(Assign);
|
||||||
if (tk == ']') next(); else { printf("%d: close bracket expected\n", line); exit(-1); }
|
if (tk == ']') next(); else { printf("%d: close bracket expected\n", line); exit(-1); }
|
||||||
if (t > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; }
|
if (t > PTR) { *++e = PSH; *++e = IMM; *++e = sizeof(int); *++e = MUL; }
|
||||||
else if (t < PTR) { printf("%d: pointer type expected\n", line); exit(-1); }
|
else if (t < PTR) { printf("%d: pointer type expected\n", line); exit(-1); }
|
||||||
*++e = ADD;
|
*++e = ADD;
|
||||||
*++e = ((ty = t - PTR) == CHAR) ? LC : LI;
|
*++e = ((ty = t - PTR) == CHAR) ? LC : LI;
|
||||||
break;
|
|
||||||
default: printf("%d: compiler error tk=%d\n", line, tk); exit(-1);
|
|
||||||
}
|
}
|
||||||
|
else { printf("%d: compiler error tk=%d\n", line, tk); exit(-1); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stmt()
|
void stmt()
|
||||||
{
|
{
|
||||||
int *a, *b, *d, i;
|
int *a, *b;
|
||||||
|
|
||||||
switch (tk) {
|
if (tk == If) {
|
||||||
case If:
|
|
||||||
next();
|
next();
|
||||||
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
|
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
|
||||||
expr(Assign);
|
expr(Assign);
|
||||||
|
|
@ -314,8 +297,8 @@ void stmt()
|
||||||
stmt();
|
stmt();
|
||||||
}
|
}
|
||||||
*b = (int)(e + 1);
|
*b = (int)(e + 1);
|
||||||
return;
|
}
|
||||||
case While:
|
else if (tk == While) {
|
||||||
next();
|
next();
|
||||||
a = e + 1;
|
a = e + 1;
|
||||||
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
|
if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
|
||||||
|
|
@ -325,54 +308,22 @@ void stmt()
|
||||||
stmt();
|
stmt();
|
||||||
*++e = JMP; *++e = (int)a;
|
*++e = JMP; *++e = (int)a;
|
||||||
*b = (int)(e + 1);
|
*b = (int)(e + 1);
|
||||||
return;
|
}
|
||||||
case Switch:
|
else if (tk == Return) {
|
||||||
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 = brk; d = def; brk = def = 0;
|
|
||||||
stmt();
|
|
||||||
*cas = def ? (int)def : (int)(e + 1); cas = a;
|
|
||||||
while (brk) { a = (int *)*brk; *brk = (int)(e + 1); brk = a; }
|
|
||||||
brk = b; def = d;
|
|
||||||
return;
|
|
||||||
case 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();
|
|
||||||
return;
|
|
||||||
case Break:
|
|
||||||
next();
|
|
||||||
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
|
|
||||||
*++e = JMP; *++e = (int)brk; brk = e;
|
|
||||||
return;
|
|
||||||
case Default:
|
|
||||||
next();
|
|
||||||
if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); }
|
|
||||||
def = e + 1;
|
|
||||||
stmt();
|
|
||||||
return;
|
|
||||||
case Return:
|
|
||||||
next();
|
next();
|
||||||
if (tk != ';') expr(Assign);
|
if (tk != ';') expr(Assign);
|
||||||
*++e = LEV;
|
*++e = LEV;
|
||||||
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
|
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
|
||||||
return;
|
}
|
||||||
case '{':
|
else if (tk == '{') {
|
||||||
next();
|
next();
|
||||||
while (tk != '}') stmt();
|
while (tk != '}') stmt();
|
||||||
next();
|
next();
|
||||||
return;
|
}
|
||||||
case ';':
|
else if (tk == ';') {
|
||||||
next();
|
next();
|
||||||
return;
|
}
|
||||||
default:
|
else {
|
||||||
expr(Assign);
|
expr(Assign);
|
||||||
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
|
if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
|
||||||
}
|
}
|
||||||
|
|
@ -401,9 +352,9 @@ int main(int argc, char **argv)
|
||||||
memset(e, 0, poolsz);
|
memset(e, 0, poolsz);
|
||||||
memset(data, 0, poolsz);
|
memset(data, 0, poolsz);
|
||||||
|
|
||||||
p = "break case char default else enum if int return sizeof switch while "
|
p = "char else enum if int return sizeof while "
|
||||||
"open read close printf malloc memset memcmp exit void main";
|
"open read close printf malloc free memset memcmp exit void main";
|
||||||
i = Break; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
|
i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
|
||||||
i = OPEN; while (i <= EXIT) { next(); id[Class] = Sys; id[Type] = INT; id[Val] = i++; } // add library to symbol table
|
i = OPEN; while (i <= EXIT) { next(); id[Class] = Sys; id[Type] = INT; id[Val] = i++; } // add library to symbol table
|
||||||
next(); id[Tk] = Char; // handle void type
|
next(); id[Tk] = Char; // handle void type
|
||||||
next(); idmain = id; // keep track of main
|
next(); idmain = id; // keep track of main
|
||||||
|
|
@ -512,7 +463,7 @@ int main(int argc, char **argv)
|
||||||
if (src) return 0;
|
if (src) return 0;
|
||||||
|
|
||||||
// setup stack
|
// setup stack
|
||||||
sp = (int *)((int)sp + poolsz);
|
bp = sp = (int *)((int)sp + poolsz);
|
||||||
*--sp = EXIT; // call exit if main returns
|
*--sp = EXIT; // call exit if main returns
|
||||||
*--sp = PSH; t = sp;
|
*--sp = PSH; t = sp;
|
||||||
*--sp = argc;
|
*--sp = argc;
|
||||||
|
|
@ -527,51 +478,50 @@ int main(int argc, char **argv)
|
||||||
printf("%d> %.4s", cycle,
|
printf("%d> %.4s", cycle,
|
||||||
&"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,"
|
&"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 ,"
|
"OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,"
|
||||||
"OPEN,READ,CLOS,PRTF,MALC,MSET,MCMP,EXIT,"[i * 5]);
|
"OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,EXIT,"[i * 5]);
|
||||||
if (i <= ADJ) printf(" %d\n", *pc); else printf("\n");
|
if (i <= ADJ) printf(" %d\n", *pc); else printf("\n");
|
||||||
}
|
}
|
||||||
switch (i) {
|
if (i == LEA) a = (int)(bp + *pc++); // load local address
|
||||||
case LEA: a = (int)(bp + *pc++); break; // load local address
|
else if (i == IMM) a = *pc++; // load global address or immediate
|
||||||
case IMM: a = *pc++; break; // load global address or immediate
|
else if (i == JMP) pc = (int *)*pc; // jump
|
||||||
case JMP: pc = (int *)*pc; break; // jump
|
else if (i == JSR) { *--sp = (int)(pc + 1); pc = (int *)*pc; } // jump to subroutine
|
||||||
case JSR: *--sp = (int)(pc + 1); pc = (int *)*pc; break; // jump to subroutine
|
else if (i == BZ) pc = a ? pc + 1 : (int *)*pc; // branch if zero
|
||||||
case BZ: pc = a ? pc + 1 : (int *)*pc; break; // branch if zero
|
else if (i == BNZ) pc = a ? (int *)*pc : pc + 1; // branch if not zero
|
||||||
case BNZ: pc = a ? (int *)*pc : pc + 1; break; // branch if not zero
|
else if (i == ENT) { *--sp = (int)bp; bp = sp; sp = sp - *pc++; } // enter subroutine
|
||||||
case ENT: *--sp = (int)bp; bp = sp; sp = sp - *pc++; break; // enter subroutine
|
else if (i == ADJ) sp = sp + *pc++; // stack adjust
|
||||||
case ADJ: sp = sp + *pc++; break; // stack adjust
|
else if (i == LEV) { sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; } // leave subroutine
|
||||||
case LEV: sp = bp; bp = (int *)*sp++; pc = (int *)*sp++; break; // leave subroutine
|
else if (i == LI) a = *(int *)a; // load int
|
||||||
case LI: a = *(int *)a; break; // load int
|
else if (i == LC) a = *(char *)a; // load char
|
||||||
case LC: a = *(char *)a; break; // load char
|
else if (i == SI) *(int *)*sp++ = a; // store int
|
||||||
case SI: *(int *)*sp++ = a; break; // store int
|
else if (i == SC) a = *(char *)*sp++ = a; // store char
|
||||||
case SC: a = *(char *)*sp++ = a; break; // store char
|
else if (i == PSH) *--sp = a; // push
|
||||||
case PSH: *--sp = a; break; // push
|
|
||||||
|
|
||||||
case OR: a = *sp++ | a; break;
|
else if (i == OR) a = *sp++ | a;
|
||||||
case XOR: a = *sp++ ^ a; break;
|
else if (i == XOR) a = *sp++ ^ a;
|
||||||
case AND: a = *sp++ & a; break;
|
else if (i == AND) a = *sp++ & a;
|
||||||
case EQ: a = *sp++ == a; break;
|
else if (i == EQ) a = *sp++ == a;
|
||||||
case NE: a = *sp++ != a; break;
|
else if (i == NE) a = *sp++ != a;
|
||||||
case LT: a = *sp++ < a; break;
|
else if (i == LT) a = *sp++ < a;
|
||||||
case GT: a = *sp++ > a; break;
|
else if (i == GT) a = *sp++ > a;
|
||||||
case LE: a = *sp++ <= a; break;
|
else if (i == LE) a = *sp++ <= a;
|
||||||
case GE: a = *sp++ >= a; break;
|
else if (i == GE) a = *sp++ >= a;
|
||||||
case SHL: a = *sp++ << a; break;
|
else if (i == SHL) a = *sp++ << a;
|
||||||
case SHR: a = *sp++ >> a; break;
|
else if (i == SHR) a = *sp++ >> a;
|
||||||
case ADD: a = *sp++ + a; break;
|
else if (i == ADD) a = *sp++ + a;
|
||||||
case SUB: a = *sp++ - a; break;
|
else if (i == SUB) a = *sp++ - a;
|
||||||
case MUL: a = *sp++ * a; break;
|
else if (i == MUL) a = *sp++ * a;
|
||||||
case DIV: a = *sp++ / a; break;
|
else if (i == DIV) a = *sp++ / a;
|
||||||
case MOD: a = *sp++ % a; break;
|
else if (i == MOD) a = *sp++ % a;
|
||||||
|
|
||||||
case OPEN: a = open((char *)sp[1], *sp); break;
|
else if (i == OPEN) a = open((char *)sp[1], *sp);
|
||||||
case READ: a = read(sp[2], (char *)sp[1], *sp); break;
|
else if (i == READ) a = read(sp[2], (char *)sp[1], *sp);
|
||||||
case CLOS: a = close(*sp); break;
|
else if (i == CLOS) a = close(*sp);
|
||||||
case PRTF: t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); break;
|
else if (i == PRTF) { t = sp + pc[1]; a = printf((char *)t[-1], t[-2], t[-3], t[-4], t[-5], t[-6]); }
|
||||||
case MALC: a = (int)malloc(*sp); break;
|
else if (i == MALC) a = (int)malloc(*sp);
|
||||||
case MSET: a = (int)memset((char *)sp[2], sp[1], *sp); break;
|
else if (i == FREE) free((void *)*sp);
|
||||||
case MCMP: a = memcmp((char *)sp[2], (char *)sp[1], *sp); break;
|
else if (i == MSET) a = (int)memset((char *)sp[2], sp[1], *sp);
|
||||||
case EXIT: printf("exit(%d) cycle = %d\n", *sp, cycle); return *sp;
|
else if (i == MCMP) a = memcmp((char *)sp[2], (char *)sp[1], *sp);
|
||||||
default: printf("unknown instruction = %d! cycle = %d\n", i, cycle); return -1;
|
else if (i == EXIT) { printf("exit(%d) cycle = %d\n", *sp, cycle); return *sp; }
|
||||||
}
|
else { printf("unknown instruction = %d! cycle = %d\n", i, cycle); return -1; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue