Add ?: operator

This commit is contained in:
Rui Ueyama 2019-08-17 10:27:35 +09:00
parent 1bb4c6d4b8
commit 0924ab0aa5
5 changed files with 54 additions and 2 deletions

View File

@ -100,6 +100,7 @@ typedef enum {
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // =
ND_COND, // ?:
ND_COMMA, // ,
ND_MEMBER, // . (struct member access)
ND_ADDR, // unary &

View File

@ -205,6 +205,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");

22
parse.c
View File

@ -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);
@ -849,11 +850,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);
@ -892,6 +893,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);

View File

@ -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
type.c
View File

@ -139,6 +139,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;