diff --git a/parse.c b/parse.c index beaee1a2e9c307b1b4deb88f700b0219d425ebf3..9f8ae31309a1002890637ecccf7463e2732ef218 100644 --- a/parse.c +++ b/parse.c @@ -501,7 +501,7 @@ static Node *funcall(Token **rest, Token *tok) { return node; } -// primary = "(" expr ")" | ident func-args? | num +// primary = "(" expr ")" | "sizeof" unary | ident func-args? | num static Node *primary(Token **rest, Token *tok) { if (equal(tok, "(")) { Node *node = expr(&tok, tok->next); @@ -509,6 +509,12 @@ static Node *primary(Token **rest, Token *tok) { return node; } + if (equal(tok, "sizeof")) { + Node *node = unary(rest, tok->next); + add_type(node); + return new_num(node->ty->size, tok); + } + if (tok->kind == TK_IDENT) { // Function call if (equal(tok->next, "(")) diff --git a/test.sh b/test.sh index 6e50a022da627a07e9b7912e94aed4cccc5ddfc5..c413a7753ecd6dd6b551c64a73e85242d86e1574 100755 --- a/test.sh +++ b/test.sh @@ -137,4 +137,17 @@ assert 3 'int main() { int x[2][3]; int *y=x; y[3]=3; return x[1][0]; }' assert 4 'int main() { int x[2][3]; int *y=x; y[4]=4; return x[1][1]; }' assert 5 'int main() { int x[2][3]; int *y=x; y[5]=5; return x[1][2]; }' +assert 8 'int main() { int x; return sizeof(x); }' +assert 8 'int main() { int x; return sizeof x; }' +assert 8 'int main() { int *x; return sizeof(x); }' +assert 32 'int main() { int x[4]; return sizeof(x); }' +assert 96 'int main() { int x[3][4]; return sizeof(x); }' +assert 32 'int main() { int x[3][4]; return sizeof(*x); }' +assert 8 'int main() { int x[3][4]; return sizeof(**x); }' +assert 9 'int main() { int x[3][4]; return sizeof(**x) + 1; }' +assert 9 'int main() { int x[3][4]; return sizeof **x + 1; }' +assert 8 'int main() { int x[3][4]; return sizeof(**x + 1); }' +assert 8 'int main() { int x=1; return sizeof(x=2); }' +assert 1 'int main() { int x=1; sizeof(x=2); return x; }' + echo OK diff --git a/tokenize.c b/tokenize.c index f91c213a1ad62cfc8098d95b3e77fdb63abe1c38..e02f01a155ab1a3f8dc357c6634e79f0e8f0b267 100644 --- a/tokenize.c +++ b/tokenize.c @@ -82,7 +82,9 @@ static bool is_ident2(char c) { } static bool is_keyword(Token *tok) { - static char *kw[] = {"return", "if", "else", "for", "while", "int"}; + static char *kw[] = { + "return", "if", "else", "for", "while", "int", "sizeof", + }; for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) if (equal(tok, kw[i]))