Skip to content

Commit

Permalink
Add ?: operator
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Sep 28, 2020
1 parent 1fd27bf commit 1d0e942
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 2 deletions.
1 change: 1 addition & 0 deletions chibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ typedef enum {
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // =
ND_COND, // ?:
ND_COMMA, // ,
ND_MEMBER, // . (struct member access)
ND_ADDR, // unary &
Expand Down
12 changes: 12 additions & 0 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@ static void gen_expr(Node *node) {
gen_expr(node->lhs);
cast(node->lhs->ty, node->ty);
return;
case ND_COND: {
int c = count();
gen_expr(node->cond);
println(" cmp $0, %%rax");
println(" je .L.else.%d", c);
gen_expr(node->then);
println(" jmp .L.end.%d", c);
println(".L.else.%d:", c);
gen_expr(node->els);
println(".L.end.%d:", c);
return;
}
case ND_NOT:
gen_expr(node->lhs);
println(" cmp $0, %%rax");
Expand Down
22 changes: 20 additions & 2 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ static Node *expr_stmt(Token **rest, Token *tok);
static Node *expr(Token **rest, Token *tok);
static Node *assign(Token **rest, Token *tok);
static Node *logor(Token **rest, Token *tok);
static Node *conditional(Token **rest, Token *tok);
static Node *logand(Token **rest, Token *tok);
static Node *bitor(Token **rest, Token *tok);
static Node *bitxor(Token **rest, Token *tok);
Expand Down Expand Up @@ -856,11 +857,11 @@ static Node *to_assign(Node *binary) {
return new_binary(ND_COMMA, expr1, expr2, tok);
}

// assign = logor (assign-op assign)?
// assign = conditional (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^="
// | "<<=" | ">>="
static Node *assign(Token **rest, Token *tok) {
Node *node = logor(&tok, tok);
Node *node = conditional(&tok, tok);

if (equal(tok, "="))
return new_binary(ND_ASSIGN, node, assign(rest, tok->next), tok);
Expand Down Expand Up @@ -899,6 +900,23 @@ static Node *assign(Token **rest, Token *tok) {
return node;
}

// conditional = logor ("?" expr ":" conditional)?
static Node *conditional(Token **rest, Token *tok) {
Node *cond = logor(&tok, tok);

if (!equal(tok, "?")) {
*rest = tok;
return cond;
}

Node *node = new_node(ND_COND, tok);
node->cond = cond;
node->then = expr(&tok, tok->next);
tok = skip(tok, ":");
node->els = conditional(rest, tok);
return node;
}

// logor = logand ("||" logand)*
static Node *logor(Token **rest, Token *tok) {
Node *node = logand(&tok, tok);
Expand Down
13 changes: 13 additions & 0 deletions test/arith.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ int main() {
ASSERT(-1, ({ int i=-1; i; }));
ASSERT(-1, ({ int i=-1; i>>=1; i; }));

ASSERT(2, 0?1:2);
ASSERT(1, 1?1:2);
ASSERT(-1, 0?-2:-1);
ASSERT(-2, 1?-2:-1);
ASSERT(4, sizeof(0?1:2));
ASSERT(8, sizeof(0?(long)1:(long)2));
ASSERT(-1, 0?(long)-2:-1);
ASSERT(-1, 0?-2:(long)-1);
ASSERT(-2, 1?(long)-2:-1);
ASSERT(-2, 1?-2:(long)-1);

1 ? -2 : (void)-1;

printf("OK\n");
return 0;
}
8 changes: 8 additions & 0 deletions type.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ void add_type(Node *node) {
case ND_VAR:
node->ty = node->var->ty;
return;
case ND_COND:
if (node->then->ty->kind == TY_VOID || node->els->ty->kind == TY_VOID) {
node->ty = ty_void;
} else {
usual_arith_conv(&node->then, &node->els);
node->ty = node->then->ty;
}
return;
case ND_COMMA:
node->ty = node->rhs->ty;
return;
Expand Down

0 comments on commit 1d0e942

Please sign in to comment.