Add goto and labeled statement

This commit is contained in:
Rui Ueyama 2019-08-15 14:57:36 +09:00
parent 08f3970c58
commit 3ccdb2974f
5 changed files with 35 additions and 1 deletions

View File

@ -123,6 +123,8 @@ typedef enum {
ND_BLOCK, // { ... }
ND_BREAK, // "break"
ND_CONTINUE, // "continue"
ND_GOTO, // "goto"
ND_LABEL, // Labeled statement
ND_FUNCALL, // Function call
ND_EXPR_STMT, // Expression statement
ND_STMT_EXPR, // Statement expression
@ -160,6 +162,9 @@ struct Node {
char *funcname;
Node *args;
// Goto or labeled statement
char *label_name;
Var *var; // Used if kind == ND_VAR
long val; // Used if kind == ND_NUM
};

View File

@ -401,6 +401,13 @@ static void gen(Node *node) {
error_tok(node->tok, "stray continue");
printf(" jmp .L.continue.%d\n", contseq);
return;
case ND_GOTO:
printf(" jmp .L.label.%s.%s\n", funcname, node->label_name);
return;
case ND_LABEL:
printf(".L.label.%s.%s:\n", funcname, node->label_name);
gen(node->lhs);
return;
case ND_FUNCALL: {
int nargs = 0;
for (Node *arg = node->args; arg; arg = arg->next) {

18
parse.c
View File

@ -719,6 +719,8 @@ static Node *stmt(void) {
// | "{" stmt* "}"
// | "break" ";"
// | "continue" ";"
// | "goto" ident ";"
// | ident ":" stmt
// | declaration
// | expr ";"
static Node *stmt2(void) {
@ -802,6 +804,22 @@ static Node *stmt2(void) {
return new_node(ND_CONTINUE, tok);
}
if (tok = consume("goto")) {
Node *node = new_node(ND_GOTO, tok);
node->label_name = expect_ident();
expect(";");
return node;
}
if (tok = consume_ident()) {
if (consume(":")) {
Node *node = new_unary(ND_LABEL, stmt(), tok);
node->label_name = strndup(tok->str, tok->len);
return node;
}
token = tok;
}
if (is_typename())
return declaration();

4
tests
View File

@ -438,6 +438,10 @@ int main() {
assert(5, ({ int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } j; }), "int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } j;");
assert(11, ({ int i=0; int j=0; while(!i) { while (j++!=10) continue; break; } j; }), "int i=0; int j=0; while(!i) { while (j++!=10) continue; break; } j;");
assert(3, ({ int i=0; goto a; a: i++; b: i++; c: i++; i; }), "int i=0; goto a; a: i++; b: i++; c: i++; i;");
assert(2, ({ int i=0; goto e; d: i++; e: i++; f: i++; i; }), "int i=0; goto d; d: i++; e: i++; f: i++; i;");
assert(1, ({ int i=0; goto i; g: i++; h: i++; i: i++; i; }), "int i=0; goto g; h: i++; i: i++; j: i++; i;");
printf("OK\n");
return 0;
}

View File

@ -150,7 +150,7 @@ static char *starts_with_reserved(char *p) {
static char *kw[] = {"return", "if", "else", "while", "for", "int",
"char", "sizeof", "struct", "typedef", "short",
"long", "void", "_Bool", "enum", "static", "break",
"continue"};
"continue", "goto"};
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) {
int len = strlen(kw[i]);