mirror of https://github.com/rui314/chibicc
Add "return" statement
This commit is contained in:
parent
482c26b536
commit
6cc1c1f064
10
chibicc.h
10
chibicc.h
|
@ -15,10 +15,11 @@ typedef struct Node Node;
|
|||
|
||||
// Token
|
||||
typedef enum {
|
||||
TK_IDENT, // Identifiers
|
||||
TK_PUNCT, // Punctuators
|
||||
TK_NUM, // Numeric literals
|
||||
TK_EOF, // End-of-file markers
|
||||
TK_IDENT, // Identifiers
|
||||
TK_PUNCT, // Punctuators
|
||||
TK_KEYWORD, // Keywords
|
||||
TK_NUM, // Numeric literals
|
||||
TK_EOF, // End-of-file markers
|
||||
} TokenKind;
|
||||
|
||||
// Token type
|
||||
|
@ -70,6 +71,7 @@ typedef enum {
|
|||
ND_LT, // <
|
||||
ND_LE, // <=
|
||||
ND_ASSIGN, // =
|
||||
ND_RETURN, // "return"
|
||||
ND_EXPR_STMT, // Expression statement
|
||||
ND_VAR, // Variable
|
||||
ND_NUM, // Integer
|
||||
|
|
|
@ -94,7 +94,12 @@ static void gen_expr(Node *node) {
|
|||
}
|
||||
|
||||
static void gen_stmt(Node *node) {
|
||||
if (node->kind == ND_EXPR_STMT) {
|
||||
switch (node->kind) {
|
||||
case ND_RETURN:
|
||||
gen_expr(node->lhs);
|
||||
printf(" jmp .L.return\n");
|
||||
return;
|
||||
case ND_EXPR_STMT:
|
||||
gen_expr(node->lhs);
|
||||
return;
|
||||
}
|
||||
|
@ -128,6 +133,7 @@ void codegen(Function *prog) {
|
|||
assert(depth == 0);
|
||||
}
|
||||
|
||||
printf(".L.return:\n");
|
||||
printf(" mov %%rbp, %%rsp\n");
|
||||
printf(" pop %%rbp\n");
|
||||
printf(" ret\n");
|
||||
|
|
9
parse.c
9
parse.c
|
@ -61,8 +61,15 @@ static Obj *new_lvar(char *name) {
|
|||
return var;
|
||||
}
|
||||
|
||||
// stmt = expr-stmt
|
||||
// stmt = "return" expr ";"
|
||||
// | expr-stmt
|
||||
static Node *stmt(Token **rest, Token *tok) {
|
||||
if (equal(tok, "return")) {
|
||||
Node *node = new_unary(ND_RETURN, expr(&tok, tok->next));
|
||||
*rest = skip(tok, ";");
|
||||
return node;
|
||||
}
|
||||
|
||||
return expr_stmt(rest, tok);
|
||||
}
|
||||
|
||||
|
|
70
test.sh
70
test.sh
|
@ -16,43 +16,47 @@ assert() {
|
|||
fi
|
||||
}
|
||||
|
||||
assert 0 '0;'
|
||||
assert 42 '42;'
|
||||
assert 21 '5+20-4;'
|
||||
assert 41 ' 12 + 34 - 5 ;'
|
||||
assert 47 '5+6*7;'
|
||||
assert 15 '5*(9-6);'
|
||||
assert 4 '(3+5)/2;'
|
||||
assert 10 '-10+20;'
|
||||
assert 10 '- -10;'
|
||||
assert 10 '- - +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 '0==1;'
|
||||
assert 1 '42==42;'
|
||||
assert 1 '0!=1;'
|
||||
assert 0 '42!=42;'
|
||||
assert 0 'return 0==1;'
|
||||
assert 1 'return 42==42;'
|
||||
assert 1 'return 0!=1;'
|
||||
assert 0 'return 42!=42;'
|
||||
|
||||
assert 1 '0<1;'
|
||||
assert 0 '1<1;'
|
||||
assert 0 '2<1;'
|
||||
assert 1 '0<=1;'
|
||||
assert 1 '1<=1;'
|
||||
assert 0 '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 '1>0;'
|
||||
assert 0 '1>1;'
|
||||
assert 0 '1>2;'
|
||||
assert 1 '1>=0;'
|
||||
assert 1 '1>=1;'
|
||||
assert 0 '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; a;'
|
||||
assert 8 'a=3; z=5; a+z;'
|
||||
assert 3 'a=3; return a;'
|
||||
assert 8 'a=3; z=5; return a+z;'
|
||||
|
||||
assert 3 'a=3; a;'
|
||||
assert 8 'a=3; z=5; a+z;'
|
||||
assert 6 'a=b=3; a+b;'
|
||||
assert 3 'foo=3; foo;'
|
||||
assert 8 'foo123=3; bar=5; 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;'
|
||||
|
||||
echo OK
|
||||
|
|
11
tokenize.c
11
tokenize.c
|
@ -79,7 +79,13 @@ static int read_punct(char *p) {
|
|||
return ispunct(*p) ? 1 : 0;
|
||||
}
|
||||
|
||||
// Tokenize `current_input` and returns new tokens.
|
||||
static void convert_keywords(Token *tok) {
|
||||
for (Token *t = tok; t->kind != TK_EOF; t = t->next)
|
||||
if (equal(t, "return"))
|
||||
t->kind = TK_KEYWORD;
|
||||
}
|
||||
|
||||
// Tokenize a given string and returns new tokens.
|
||||
Token *tokenize(char *p) {
|
||||
current_input = p;
|
||||
Token head = {};
|
||||
|
@ -101,7 +107,7 @@ Token *tokenize(char *p) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Identifier
|
||||
// Identifier or keyword
|
||||
if (is_ident1(*p)) {
|
||||
char *start = p;
|
||||
do {
|
||||
|
@ -123,5 +129,6 @@ Token *tokenize(char *p) {
|
|||
}
|
||||
|
||||
cur = cur->next = new_token(TK_EOF, p, p);
|
||||
convert_keywords(head.next);
|
||||
return head.next;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue