Add continue statement

This commit is contained in:
Rui Ueyama 2020-08-27 21:59:19 +09:00
parent b3047f2317
commit 3c83dfd8af
5 changed files with 31 additions and 3 deletions

View File

@ -144,8 +144,9 @@ struct Node {
Node *init;
Node *inc;
// "break" label
// "break" and "continue" labels
char *brk_label;
char *cont_label;
// Block or statement expression
Node *body;

View File

@ -362,6 +362,7 @@ static void gen_stmt(Node *node) {
println(" je %s", node->brk_label);
}
gen_stmt(node->then);
println("%s:", node->cont_label);
if (node->inc)
gen_expr(node->inc);
println(" jmp .L.begin.%d", c);

21
parse.c
View File

@ -71,8 +71,9 @@ static Obj *current_fn;
static Node *gotos;
static Node *labels;
// Current "goto" jump target.
// Current "goto" and "continue" jump targets.
static char *brk_label;
static char *cont_label;
static bool is_typename(Token *tok);
static Type *declspec(Token **rest, Token *tok, VarAttr *attr);
@ -586,6 +587,7 @@ static bool is_typename(Token *tok) {
// | "while" "(" expr ")" stmt
// | "goto" ident ";"
// | "break" ";"
// | "continue" ";"
// | ident ":" stmt
// | "{" compound-stmt
// | expr-stmt
@ -619,7 +621,9 @@ static Node *stmt(Token **rest, Token *tok) {
enter_scope();
char *brk = brk_label;
char *cont = cont_label;
brk_label = node->brk_label = new_unique_name();
cont_label = node->cont_label = new_unique_name();
if (is_typename(tok)) {
Type *basety = declspec(&tok, tok, NULL);
@ -640,6 +644,7 @@ static Node *stmt(Token **rest, Token *tok) {
leave_scope();
brk_label = brk;
cont_label = cont;
return node;
}
@ -650,9 +655,14 @@ static Node *stmt(Token **rest, Token *tok) {
tok = skip(tok, ")");
char *brk = brk_label;
char *cont = cont_label;
brk_label = node->brk_label = new_unique_name();
cont_label = node->cont_label = new_unique_name();
node->then = stmt(rest, tok);
brk_label = brk;
cont_label = cont;
return node;
}
@ -674,6 +684,15 @@ static Node *stmt(Token **rest, Token *tok) {
return node;
}
if (equal(tok, "continue")) {
if (!cont_label)
error_tok(tok, "stray continue");
Node *node = new_node(ND_GOTO, tok);
node->unique_label = cont_label;
*rest = skip(tok->next, ";");
return node;
}
if (tok->kind == TK_IDENT && equal(tok->next, ":")) {
Node *node = new_node(ND_LABEL, tok);
node->label = strndup(tok->loc, tok->len);

View File

@ -47,6 +47,13 @@ int main() {
ASSERT(3, ({ int i=0; for(;i<10;i++) { for (;;) break; if (i == 3) break; } i; }));
ASSERT(4, ({ int i=0; while (1) { while(1) break; if (i++ == 3) break; } i; }));
ASSERT(10, ({ int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } i; }));
ASSERT(6, ({ int i=0; int j=0; for (;i<10;i++) { if (i>5) continue; j++; } j; }));
ASSERT(10, ({ int i=0; int j=0; for(;!i;) { for (;j!=10;j++) continue; break; } j; }));
ASSERT(11, ({ int i=0; int j=0; while (i++<10) { if (i>5) continue; j++; } i; }));
ASSERT(5, ({ 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; }));
printf("OK\n");
return 0;
}

View File

@ -131,7 +131,7 @@ static bool is_keyword(Token *tok) {
static char *kw[] = {
"return", "if", "else", "for", "while", "int", "sizeof", "char",
"struct", "union", "short", "long", "void", "typedef", "_Bool",
"enum", "static", "goto", "break",
"enum", "static", "goto", "break", "continue",
};
for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)