Skip to content

Commit

Permalink
feat: add ternary operator(?)
Browse files Browse the repository at this point in the history
  • Loading branch information
diohabara committed Jul 26, 2023
1 parent 1adbe08 commit 4c3f2de
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 3 deletions.
1 change: 1 addition & 0 deletions ccc.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ typedef enum {
ND_SHR, // >>
ND_A_SHL, // <<=
ND_A_SHR, // >>=
ND_TERNARY, // ? :
} NodeKind;
// AST node type
typedef struct Node Node;
Expand Down
12 changes: 12 additions & 0 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,18 @@ void gen(Node *node) {
store(node->ty);
inc(node);
return;
case ND_TERNARY:
int seq = labelseq++;
gen(node->cond);
printf(" pop rax\n");
printf(" cmp rax, 0\n");
printf(" je .Lelse%d\n", seq);
gen(node->then);
printf(" jmp .Lend%d\n", seq);
printf(".Lelse%d:\n", seq);
gen(node->els);
printf(".Lend%d:\n", seq);
return;
case ND_A_ADD:
case ND_A_SUB:
case ND_A_MUL:
Expand Down
20 changes: 18 additions & 2 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ bool is_typename();
Node *stmt();
Node *expr();
Node *assign();
Node *conditional();
Node *bitand();
Node * bitor ();
Node *bitxor();
Expand Down Expand Up @@ -820,10 +821,10 @@ Node *expr() {
}
return node;
}
// assign = logor (assign-op assign)?
// assign = conditional (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>="
Node *assign() {
Node *node = logor();
Node *node = conditional();
Token *tok;
if (tok = consume("=")) {
node = new_binary(ND_ASSIGN, node, assign(), tok);
Expand Down Expand Up @@ -852,6 +853,21 @@ Node *assign() {
return node;
}

// conditional = logor ("?" expr ":" condtional)?
Node *conditional() {
Node *node = logor();
Token *tok = consume("?");
while (!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)*
Node *logor() {
Node *node = logand();
Expand Down
3 changes: 3 additions & 0 deletions tests
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,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;
}
2 changes: 1 addition & 1 deletion tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ Token *tokenize() {
continue;
}
// Single-letter punctuator
if (strchr("+-*/()<>;={},&[].,!~|^:", *p)) {
if (strchr("+-*/()<>;={},&[].,!~|^:?", *p)) {
cur = new_token(TK_RESERVED, cur, p++, 1);
continue;
}
Expand Down
3 changes: 3 additions & 0 deletions type.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ void visit(Node* node) {
case ND_BITNOT:
node->ty = node->lhs->ty;
return;
case ND_TERNARY:
node->ty = node->then->ty;
return;
case ND_COMMA:
node->ty = node->lhs->ty;
return;
Expand Down

0 comments on commit 4c3f2de

Please sign in to comment.