mirror of https://github.com/rui314/chibicc
Add goto and labeled statement
This commit is contained in:
parent
08f3970c58
commit
3ccdb2974f
5
chibi.h
5
chibi.h
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
18
parse.c
|
@ -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
4
tests
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue