mirror of https://github.com/rui314/chibicc
Handle block scope
This commit is contained in:
parent
6c0a42926a
commit
ca8b2434c9
59
parse.c
59
parse.c
|
@ -18,11 +18,28 @@
|
|||
|
||||
#include "chibicc.h"
|
||||
|
||||
// Scope for local or global variables.
|
||||
typedef struct VarScope VarScope;
|
||||
struct VarScope {
|
||||
VarScope *next;
|
||||
char *name;
|
||||
Obj *var;
|
||||
};
|
||||
|
||||
// Represents a block scope.
|
||||
typedef struct Scope Scope;
|
||||
struct Scope {
|
||||
Scope *next;
|
||||
VarScope *vars;
|
||||
};
|
||||
|
||||
// All local variable instances created during parsing are
|
||||
// accumulated to this list.
|
||||
static Obj *locals;
|
||||
static Obj *globals;
|
||||
|
||||
static Scope *scope = &(Scope){};
|
||||
|
||||
static Type *declspec(Token **rest, Token *tok);
|
||||
static Type *declarator(Token **rest, Token *tok, Type *ty);
|
||||
static Node *declaration(Token **rest, Token *tok);
|
||||
|
@ -39,16 +56,22 @@ static Node *postfix(Token **rest, Token *tok);
|
|||
static Node *unary(Token **rest, Token *tok);
|
||||
static Node *primary(Token **rest, Token *tok);
|
||||
|
||||
// Find a local variable by name.
|
||||
static void enter_scope(void) {
|
||||
Scope *sc = calloc(1, sizeof(Scope));
|
||||
sc->next = scope;
|
||||
scope = sc;
|
||||
}
|
||||
|
||||
static void leave_scope(void) {
|
||||
scope = scope->next;
|
||||
}
|
||||
|
||||
// Find a variable by name.
|
||||
static Obj *find_var(Token *tok) {
|
||||
for (Obj *var = locals; var; var = var->next)
|
||||
if (strlen(var->name) == tok->len && !strncmp(tok->loc, var->name, tok->len))
|
||||
return var;
|
||||
|
||||
for (Obj *var = globals; var; var = var->next)
|
||||
if (strlen(var->name) == tok->len && !strncmp(tok->loc, var->name, tok->len))
|
||||
return var;
|
||||
|
||||
for (Scope *sc = scope; sc; sc = sc->next)
|
||||
for (VarScope *sc2 = sc->vars; sc2; sc2 = sc2->next)
|
||||
if (equal(tok, sc2->name))
|
||||
return sc2->var;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -84,10 +107,20 @@ static Node *new_var_node(Obj *var, Token *tok) {
|
|||
return node;
|
||||
}
|
||||
|
||||
static VarScope *push_scope(char *name, Obj *var) {
|
||||
VarScope *sc = calloc(1, sizeof(VarScope));
|
||||
sc->name = name;
|
||||
sc->var = var;
|
||||
sc->next = scope->vars;
|
||||
scope->vars = sc;
|
||||
return sc;
|
||||
}
|
||||
|
||||
static Obj *new_var(char *name, Type *ty) {
|
||||
Obj *var = calloc(1, sizeof(Obj));
|
||||
var->name = name;
|
||||
var->ty = ty;
|
||||
push_scope(name, var);
|
||||
return var;
|
||||
}
|
||||
|
||||
|
@ -291,9 +324,11 @@ static Node *stmt(Token **rest, Token *tok) {
|
|||
// compound-stmt = (declaration | stmt)* "}"
|
||||
static Node *compound_stmt(Token **rest, Token *tok) {
|
||||
Node *node = new_node(ND_BLOCK, tok);
|
||||
|
||||
Node head = {};
|
||||
Node *cur = &head;
|
||||
|
||||
enter_scope();
|
||||
|
||||
while (!equal(tok, "}")) {
|
||||
if (is_typename(tok))
|
||||
cur = cur->next = declaration(&tok, tok);
|
||||
|
@ -302,6 +337,8 @@ static Node *compound_stmt(Token **rest, Token *tok) {
|
|||
add_type(cur);
|
||||
}
|
||||
|
||||
leave_scope();
|
||||
|
||||
node->body = head.next;
|
||||
*rest = tok->next;
|
||||
return node;
|
||||
|
@ -614,12 +651,14 @@ static Token *function(Token *tok, Type *basety) {
|
|||
fn->is_function = true;
|
||||
|
||||
locals = NULL;
|
||||
enter_scope();
|
||||
create_param_lvars(ty->params);
|
||||
fn->params = locals;
|
||||
|
||||
tok = skip(tok, "{");
|
||||
fn->body = compound_stmt(&tok, tok);
|
||||
fn->locals = locals;
|
||||
leave_scope();
|
||||
return tok;
|
||||
}
|
||||
|
||||
|
|
4
test.sh
4
test.sh
|
@ -217,4 +217,8 @@ assert 2 'int main() { /* return 1; */ return 2; }'
|
|||
assert 2 'int main() { // return 1;
|
||||
return 2; }'
|
||||
|
||||
assert 2 'int main() { int x=2; { int x=3; } return x; }'
|
||||
assert 2 'int main() { int x=2; { int x=3; } { int y=4; return x; }}'
|
||||
assert 3 'int main() { int x=2; { x=3; } return x; }'
|
||||
|
||||
echo OK
|
||||
|
|
Loading…
Reference in New Issue