Skip to content

Commit 1d0e942

Browse files
committed
Add ?: operator
1 parent 1fd27bf commit 1d0e942

File tree

5 files changed

+54
-2
lines changed

5 files changed

+54
-2
lines changed

chibicc.h

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ typedef enum {
101101
ND_LT, // <
102102
ND_LE, // <=
103103
ND_ASSIGN, // =
104+
ND_COND, // ?:
104105
ND_COMMA, // ,
105106
ND_MEMBER, // . (struct member access)
106107
ND_ADDR, // unary &

codegen.c

+12
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,18 @@ static void gen_expr(Node *node) {
209209
gen_expr(node->lhs);
210210
cast(node->lhs->ty, node->ty);
211211
return;
212+
case ND_COND: {
213+
int c = count();
214+
gen_expr(node->cond);
215+
println(" cmp $0, %%rax");
216+
println(" je .L.else.%d", c);
217+
gen_expr(node->then);
218+
println(" jmp .L.end.%d", c);
219+
println(".L.else.%d:", c);
220+
gen_expr(node->els);
221+
println(".L.end.%d:", c);
222+
return;
223+
}
212224
case ND_NOT:
213225
gen_expr(node->lhs);
214226
println(" cmp $0, %%rax");

parse.c

+20-2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ static Node *expr_stmt(Token **rest, Token *tok);
9797
static Node *expr(Token **rest, Token *tok);
9898
static Node *assign(Token **rest, Token *tok);
9999
static Node *logor(Token **rest, Token *tok);
100+
static Node *conditional(Token **rest, Token *tok);
100101
static Node *logand(Token **rest, Token *tok);
101102
static Node *bitor(Token **rest, Token *tok);
102103
static Node *bitxor(Token **rest, Token *tok);
@@ -856,11 +857,11 @@ static Node *to_assign(Node *binary) {
856857
return new_binary(ND_COMMA, expr1, expr2, tok);
857858
}
858859

859-
// assign = logor (assign-op assign)?
860+
// assign = conditional (assign-op assign)?
860861
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^="
861862
// | "<<=" | ">>="
862863
static Node *assign(Token **rest, Token *tok) {
863-
Node *node = logor(&tok, tok);
864+
Node *node = conditional(&tok, tok);
864865

865866
if (equal(tok, "="))
866867
return new_binary(ND_ASSIGN, node, assign(rest, tok->next), tok);
@@ -899,6 +900,23 @@ static Node *assign(Token **rest, Token *tok) {
899900
return node;
900901
}
901902

903+
// conditional = logor ("?" expr ":" conditional)?
904+
static Node *conditional(Token **rest, Token *tok) {
905+
Node *cond = logor(&tok, tok);
906+
907+
if (!equal(tok, "?")) {
908+
*rest = tok;
909+
return cond;
910+
}
911+
912+
Node *node = new_node(ND_COND, tok);
913+
node->cond = cond;
914+
node->then = expr(&tok, tok->next);
915+
tok = skip(tok, ":");
916+
node->els = conditional(rest, tok);
917+
return node;
918+
}
919+
902920
// logor = logand ("||" logand)*
903921
static Node *logor(Token **rest, Token *tok) {
904922
Node *node = logand(&tok, tok);

test/arith.c

+13
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,19 @@ int main() {
108108
ASSERT(-1, ({ int i=-1; i; }));
109109
ASSERT(-1, ({ int i=-1; i>>=1; i; }));
110110

111+
ASSERT(2, 0?1:2);
112+
ASSERT(1, 1?1:2);
113+
ASSERT(-1, 0?-2:-1);
114+
ASSERT(-2, 1?-2:-1);
115+
ASSERT(4, sizeof(0?1:2));
116+
ASSERT(8, sizeof(0?(long)1:(long)2));
117+
ASSERT(-1, 0?(long)-2:-1);
118+
ASSERT(-1, 0?-2:(long)-1);
119+
ASSERT(-2, 1?(long)-2:-1);
120+
ASSERT(-2, 1?-2:(long)-1);
121+
122+
1 ? -2 : (void)-1;
123+
111124
printf("OK\n");
112125
return 0;
113126
}

type.c

+8
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ void add_type(Node *node) {
145145
case ND_VAR:
146146
node->ty = node->var->ty;
147147
return;
148+
case ND_COND:
149+
if (node->then->ty->kind == TY_VOID || node->els->ty->kind == TY_VOID) {
150+
node->ty = ty_void;
151+
} else {
152+
usual_arith_conv(&node->then, &node->els);
153+
node->ty = node->then->ty;
154+
}
155+
return;
148156
case ND_COMMA:
149157
node->ty = node->rhs->ty;
150158
return;

0 commit comments

Comments
 (0)