Add { ... }

This commit is contained in:
Rui Ueyama 2020-09-04 13:38:41 +09:00
parent 6cc1c1f064
commit 18ac283a5d
4 changed files with 69 additions and 46 deletions

View File

@ -72,6 +72,7 @@ typedef enum {
ND_LE, // <=
ND_ASSIGN, // =
ND_RETURN, // "return"
ND_BLOCK, // { ... }
ND_EXPR_STMT, // Expression statement
ND_VAR, // Variable
ND_NUM, // Integer
@ -83,6 +84,10 @@ struct Node {
Node *next; // Next node
Node *lhs; // Left-hand side
Node *rhs; // Right-hand side
// Block
Node *body;
Obj *var; // Used if kind == ND_VAR
int val; // Used if kind == ND_NUM
};

View File

@ -95,6 +95,10 @@ static void gen_expr(Node *node) {
static void gen_stmt(Node *node) {
switch (node->kind) {
case ND_BLOCK:
for (Node *n = node->body; n; n = n->next)
gen_stmt(n);
return;
case ND_RETURN:
gen_expr(node->lhs);
printf(" jmp .L.return\n");
@ -128,10 +132,8 @@ void codegen(Function *prog) {
printf(" mov %%rsp, %%rbp\n");
printf(" sub $%d, %%rsp\n", prog->stack_size);
for (Node *n = prog->body; n; n = n->next) {
gen_stmt(n);
assert(depth == 0);
}
gen_stmt(prog->body);
assert(depth == 0);
printf(".L.return:\n");
printf(" mov %%rbp, %%rsp\n");

26
parse.c
View File

@ -4,6 +4,7 @@
// accumulated to this list.
Obj *locals;
static Node *compound_stmt(Token **rest, Token *tok);
static Node *expr(Token **rest, Token *tok);
static Node *expr_stmt(Token **rest, Token *tok);
static Node *assign(Token **rest, Token *tok);
@ -62,6 +63,7 @@ static Obj *new_lvar(char *name) {
}
// stmt = "return" expr ";"
// | "{" compound-stmt
// | expr-stmt
static Node *stmt(Token **rest, Token *tok) {
if (equal(tok, "return")) {
@ -70,9 +72,25 @@ static Node *stmt(Token **rest, Token *tok) {
return node;
}
if (equal(tok, "{"))
return compound_stmt(rest, tok->next);
return expr_stmt(rest, tok);
}
// compound-stmt = stmt* "}"
static Node *compound_stmt(Token **rest, Token *tok) {
Node head = {};
Node *cur = &head;
while (!equal(tok, "}"))
cur = cur->next = stmt(&tok, tok);
Node *node = new_node(ND_BLOCK);
node->body = head.next;
*rest = tok->next;
return node;
}
// expr-stmt = expr ";"
static Node *expr_stmt(Token **rest, Token *tok) {
Node *node = new_unary(ND_EXPR_STMT, expr(&tok, tok));
@ -223,14 +241,10 @@ static Node *primary(Token **rest, Token *tok) {
// program = stmt*
Function *parse(Token *tok) {
Node head = {};
Node *cur = &head;
while (tok->kind != TK_EOF)
cur = cur->next = stmt(&tok, tok);
tok = skip(tok, "{");
Function *prog = calloc(1, sizeof(Function));
prog->body = head.next;
prog->body = compound_stmt(&tok, tok);
prog->locals = locals;
return prog;
}

74
test.sh
View File

@ -16,47 +16,49 @@ assert() {
fi
}
assert 0 'return 0;'
assert 42 'return 42;'
assert 21 'return 5+20-4;'
assert 41 'return 12 + 34 - 5 ;'
assert 47 'return 5+6*7;'
assert 15 'return 5*(9-6);'
assert 4 'return (3+5)/2;'
assert 10 'return -10+20;'
assert 10 'return - -10;'
assert 10 'return - - +10;'
assert 0 '{ return 0; }'
assert 42 '{ return 42; }'
assert 21 '{ return 5+20-4; }'
assert 41 '{ return 12 + 34 - 5 ; }'
assert 47 '{ return 5+6*7; }'
assert 15 '{ return 5*(9-6); }'
assert 4 '{ return (3+5)/2; }'
assert 10 '{ return -10+20; }'
assert 10 '{ return - -10; }'
assert 10 '{ return - - +10; }'
assert 0 'return 0==1;'
assert 1 'return 42==42;'
assert 1 'return 0!=1;'
assert 0 'return 42!=42;'
assert 0 '{ return 0==1; }'
assert 1 '{ return 42==42; }'
assert 1 '{ return 0!=1; }'
assert 0 '{ return 42!=42; }'
assert 1 'return 0<1;'
assert 0 'return 1<1;'
assert 0 'return 2<1;'
assert 1 'return 0<=1;'
assert 1 'return 1<=1;'
assert 0 'return 2<=1;'
assert 1 '{ return 0<1; }'
assert 0 '{ return 1<1; }'
assert 0 '{ return 2<1; }'
assert 1 '{ return 0<=1; }'
assert 1 '{ return 1<=1; }'
assert 0 '{ return 2<=1; }'
assert 1 'return 1>0;'
assert 0 'return 1>1;'
assert 0 'return 1>2;'
assert 1 'return 1>=0;'
assert 1 'return 1>=1;'
assert 0 'return 1>=2;'
assert 1 '{ return 1>0; }'
assert 0 '{ return 1>1; }'
assert 0 '{ return 1>2; }'
assert 1 '{ return 1>=0; }'
assert 1 '{ return 1>=1; }'
assert 0 '{ return 1>=2; }'
assert 3 'a=3; return a;'
assert 8 'a=3; z=5; return a+z;'
assert 3 '{ a=3; return a; }'
assert 8 '{ a=3; z=5; return a+z; }'
assert 3 'a=3; return a;'
assert 8 'a=3; z=5; return a+z;'
assert 6 'a=b=3; return a+b;'
assert 3 'foo=3; return foo;'
assert 8 'foo123=3; bar=5; return foo123+bar;'
assert 3 '{ a=3; return a; }'
assert 8 '{ a=3; z=5; return a+z; }'
assert 6 '{ a=b=3; return a+b; }'
assert 3 '{ foo=3; return foo; }'
assert 8 '{ foo123=3; bar=5; return foo123+bar; }'
assert 1 'return 1; 2; 3;'
assert 2 '1; return 2; 3;'
assert 3 '1; 2; return 3;'
assert 1 '{ return 1; 2; 3; }'
assert 2 '{ 1; return 2; 3; }'
assert 3 '{ 1; 2; return 3; }'
assert 3 '{ {1; {2;} return 3;} }'
echo OK