selfhost: port switch — N_SWITCH parser + cgen + scratch slot
This commit is contained in:
@@ -176,6 +176,63 @@ fn parsefor(p: *parser) *node = {
|
||||
return n;
|
||||
};
|
||||
|
||||
fn parseswitch(p: *parser) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
let pc: i32 = p.curcol;
|
||||
advance(p); // past `switch`
|
||||
expecttok(p, tkind.TK_LPAREN, "expected '(' after switch");
|
||||
let n: *node = newnode(p.a, nkind.N_SWITCH, pf, pl, pc);
|
||||
n.lhs = parseexpr(p);
|
||||
expecttok(p, tkind.TK_RPAREN, "expected ')' after switch expression");
|
||||
expecttok(p, tkind.TK_LBRACE, "expected '{' to open switch body");
|
||||
let head: *node = nil;
|
||||
let tail: *node = nil;
|
||||
for (p.curkind == tkind.TK_CASE) {
|
||||
let cpf: str = p.curfile;
|
||||
let cpl: i32 = p.curline;
|
||||
let cpc: i32 = p.curcol;
|
||||
advance(p); // past `case`
|
||||
let cs: *node = newnode(p.a, nkind.N_CASE, cpf, cpl, cpc);
|
||||
let eh: *node = nil;
|
||||
let et: *node = nil;
|
||||
if (p.curkind != tkind.TK_COLON) {
|
||||
p.nocast = 1;
|
||||
for (true) {
|
||||
let e: *node = parseexpr(p);
|
||||
if (eh == nil) { eh = e; }
|
||||
else { et.next = e; };
|
||||
et = e;
|
||||
if (!accepttok(p, tkind.TK_COMMA)) { break; };
|
||||
};
|
||||
p.nocast = 0;
|
||||
};
|
||||
cs.list = eh;
|
||||
expecttok(p, tkind.TK_COLON, "expected ':' after case label");
|
||||
let bh: *node = nil;
|
||||
let bt: *node = nil;
|
||||
for (p.curkind != tkind.TK_CASE) {
|
||||
if (p.curkind == tkind.TK_RBRACE) { break; };
|
||||
if (p.curkind == tkind.TK_EOF) { break; };
|
||||
let s: *node = parsestmt(p);
|
||||
if (s != nil) {
|
||||
if (bh == nil) { bh = s; }
|
||||
else { bt.next = s; };
|
||||
bt = s;
|
||||
};
|
||||
};
|
||||
let blk: *node = newnode(p.a, nkind.N_BLOCK, cpf, cpl, cpc);
|
||||
blk.list = bh;
|
||||
cs.body = blk;
|
||||
if (head == nil) { head = cs; }
|
||||
else { tail.next = cs; };
|
||||
tail = cs;
|
||||
};
|
||||
expecttok(p, tkind.TK_RBRACE, "expected '}' to close switch");
|
||||
n.list = head;
|
||||
return n;
|
||||
};
|
||||
|
||||
fn parsestmt(p: *parser) *node = {
|
||||
let pf: str = p.curfile;
|
||||
let pl: i32 = p.curline;
|
||||
@@ -202,6 +259,11 @@ fn parsestmt(p: *parser) *node = {
|
||||
expecttok(p, tkind.TK_SEMI, "expected ';' after for");
|
||||
return n;
|
||||
};
|
||||
if (p.curkind == tkind.TK_SWITCH) {
|
||||
let n: *node = parseswitch(p);
|
||||
expecttok(p, tkind.TK_SEMI, "expected ';' after switch");
|
||||
return n;
|
||||
};
|
||||
if (p.curkind == tkind.TK_RETURN) {
|
||||
advance(p);
|
||||
let n: *node = newnode(p.a, nkind.N_RETURN, pf, pl, pc);
|
||||
|
||||
Reference in New Issue
Block a user