Add ?: operator

This commit is contained in:
Rui Ueyama 2019-08-17 10:27:35 +09:00
parent 55d24d049b
commit 0f367201b1
5 changed files with 38 additions and 2 deletions

View File

@ -100,6 +100,7 @@ typedef enum {
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // =
ND_TERNARY, // ?:
ND_PRE_INC, // pre ++
ND_PRE_DEC, // pre --
ND_POST_INC, // post ++

View File

@ -226,6 +226,19 @@ static void gen(Node *node) {
gen(node->rhs);
store(node->ty);
return;
case ND_TERNARY: {
int seq = labelseq++;
gen(node->cond);
printf(" pop rax\n");
printf(" cmp rax, 0\n");
printf(" je .L.else.%d\n", seq);
gen(node->then);
printf(" jmp .L.end.%d\n", seq);
printf(".L.else.%d:\n", seq);
gen(node->els);
printf(".L.end.%d:\n", seq);
return;
}
case ND_PRE_INC:
gen_lval(node->lhs);
printf(" push [rsp]\n");

20
parse.c
View File

@ -186,6 +186,7 @@ static Node *stmt(void);
static Node *stmt2(void);
static Node *expr(void);
static Node *assign(void);
static Node *conditional(void);
static Node *logor(void);
static Node *logand(void);
static Node *bitand(void);
@ -883,10 +884,10 @@ static Node *expr(void) {
return node;
}
// assign = logor (assign-op assign)?
// assign = conditional (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "<<=" | ">>="
static Node *assign(void) {
Node *node = logor();
Node *node = conditional();
Token *tok;
if (tok = consume("="))
@ -923,6 +924,21 @@ static Node *assign(void) {
return node;
}
// conditional = logor ("?" expr ":" conditional)?
static Node *conditional(void) {
Node *node = logor();
Token *tok = consume("?");
if (!tok)
return node;
Node *ternary = new_node(ND_TERNARY, tok);
ternary->cond = node;
ternary->then = expr();
expect(":");
ternary->els = conditional();
return ternary;
}
// logor = logand ("||" logand)*
static Node *logor(void) {
Node *node = logand();

3
tests
View File

@ -468,6 +468,9 @@ int main() {
assert(-1, ({ int i=-1; i; }), "int i=-1; i;");
assert(-1, ({ int i=-1; i>>=1; i; }), "int i=1; i>>1;");
assert(2, 0?1:2, "0?1:2");
assert(1, 1?1:2, "0?1:2");
printf("OK\n");
return 0;
}

3
type.c
View File

@ -113,6 +113,9 @@ void add_type(Node *node) {
case ND_VAR:
node->ty = node->var->ty;
return;
case ND_TERNARY:
node->ty = node->then->ty;
return;
case ND_COMMA:
node->ty = node->rhs->ty;
return;