Add &, |, ^, &=, |= and ^=

This commit is contained in:
Rui Ueyama 2020-08-27 21:57:11 +09:00
parent 4af75d51f7
commit fcc9daa39d
6 changed files with 82 additions and 4 deletions

View File

@ -90,6 +90,9 @@ typedef enum {
ND_MUL, // *
ND_DIV, // /
ND_MOD, // %
ND_BITAND, // &
ND_BITOR, // |
ND_BITXOR, // ^
ND_EQ, // ==
ND_NE, // !=
ND_LT, // <

View File

@ -268,6 +268,15 @@ static void gen_expr(Node *node) {
if (node->kind == ND_MOD)
println(" mov %%rdx, %%rax");
return;
case ND_BITAND:
println(" and %%rdi, %%rax");
return;
case ND_BITOR:
println(" or %%rdi, %%rax");
return;
case ND_BITXOR:
println(" xor %%rdi, %%rax");
return;
case ND_EQ:
case ND_NE:
case ND_LT:

51
parse.c
View File

@ -83,6 +83,9 @@ static Node *stmt(Token **rest, Token *tok);
static Node *expr_stmt(Token **rest, Token *tok);
static Node *expr(Token **rest, Token *tok);
static Node *assign(Token **rest, Token *tok);
static Node *bitor(Token **rest, Token *tok);
static Node *bitxor(Token **rest, Token *tok);
static Node *bitand(Token **rest, Token *tok);
static Node *equality(Token **rest, Token *tok);
static Node *relational(Token **rest, Token *tok);
static Node *add(Token **rest, Token *tok);
@ -702,10 +705,10 @@ static Node *to_assign(Node *binary) {
return new_binary(ND_COMMA, expr1, expr2, tok);
}
// assign = equality (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%="
// assign = bitor (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^="
static Node *assign(Token **rest, Token *tok) {
Node *node = equality(&tok, tok);
Node *node = bitor(&tok, tok);
if (equal(tok, "="))
return new_binary(ND_ASSIGN, node, assign(rest, tok->next), tok);
@ -725,6 +728,48 @@ static Node *assign(Token **rest, Token *tok) {
if (equal(tok, "%="))
return to_assign(new_binary(ND_MOD, node, assign(rest, tok->next), tok));
if (equal(tok, "&="))
return to_assign(new_binary(ND_BITAND, node, assign(rest, tok->next), tok));
if (equal(tok, "|="))
return to_assign(new_binary(ND_BITOR, node, assign(rest, tok->next), tok));
if (equal(tok, "^="))
return to_assign(new_binary(ND_BITXOR, node, assign(rest, tok->next), tok));
*rest = tok;
return node;
}
// bitor = bitxor ("|" bitxor)*
static Node *bitor(Token **rest, Token *tok) {
Node *node = bitxor(&tok, tok);
while (equal(tok, "|")) {
Token *start = tok;
node = new_binary(ND_BITOR, node, bitxor(&tok, tok->next), start);
}
*rest = tok;
return node;
}
// bitxor = bitand ("^" bitand)*
static Node *bitxor(Token **rest, Token *tok) {
Node *node = bitand(&tok, tok);
while (equal(tok, "^")) {
Token *start = tok;
node = new_binary(ND_BITXOR, node, bitand(&tok, tok->next), start);
}
*rest = tok;
return node;
}
// bitand = equality ("&" equality)*
static Node *bitand(Token **rest, Token *tok) {
Node *node = equality(&tok, tok);
while (equal(tok, "&")) {
Token *start = tok;
node = new_binary(ND_BITAND, node, equality(&tok, tok->next), start);
}
*rest = tok;
return node;
}

View File

@ -79,6 +79,22 @@ int main() {
ASSERT(2, ({ int i=10; i%=4; i; }));
ASSERT(2, ({ long i=10; i%=4; i; }));
ASSERT(0, 0&1);
ASSERT(1, 3&1);
ASSERT(3, 7&3);
ASSERT(10, -1&10);
ASSERT(1, 0|1);
ASSERT(0b10011, 0b10000|0b00011);
ASSERT(0, 0^0);
ASSERT(0, 0b1111^0b1111);
ASSERT(0b110100, 0b111000^0b001100);
ASSERT(2, ({ int i=6; i&=3; i; }));
ASSERT(7, ({ int i=6; i|=3; i; }));
ASSERT(10, ({ int i=15; i^=5; i; }));
printf("OK\n");
return 0;
}

View File

@ -337,7 +337,9 @@ static Token *tokenize(char *filename, char *p) {
startswith(p, "->") || startswith(p, "+=") ||
startswith(p, "-=") || startswith(p, "*=") ||
startswith(p, "/=") || startswith(p, "++") ||
startswith(p, "--") || startswith(p, "%=")) {
startswith(p, "--") || startswith(p, "%=") ||
startswith(p, "&=") || startswith(p, "|=") ||
startswith(p, "^=")) {
cur = new_token(TK_RESERVED, cur, p, 2);
p += 2;
continue;

3
type.c
View File

@ -99,6 +99,9 @@ void add_type(Node *node) {
case ND_MUL:
case ND_DIV:
case ND_MOD:
case ND_BITAND:
case ND_BITOR:
case ND_BITXOR:
usual_arith_conv(&node->lhs, &node->rhs);
node->ty = node->lhs->ty;
return;