aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--codegen.c2
-rw-r--r--parse.c20
-rw-r--r--preprocess.c14
-rw-r--r--tests/067.sh15
-rw-r--r--tokenize.c5
5 files changed, 50 insertions, 6 deletions
diff --git a/codegen.c b/codegen.c
index 4bb15e2..234b4e5 100644
--- a/codegen.c
+++ b/codegen.c
@@ -152,6 +152,8 @@ void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
printf(" cqo\n");
printf(" idiv rdi\n");
printf(" mov rax, rdx\n");
+ } else if (ast->node_op == TokenKind_or) {
+ printf(" or rax, rdi\n");
} else if (ast->node_op == TokenKind_eq) {
printf(" cmp rax, rdi\n");
printf(" sete al\n");
diff --git a/parse.c b/parse.c
index 469ed49..057d5c2 100644
--- a/parse.c
+++ b/parse.c
@@ -474,13 +474,29 @@ AstNode* parse_equality_expr(Parser* p) {
return lhs;
}
-AstNode* parse_logical_and_expr(Parser* p) {
+AstNode* parse_bitwise_or_expr(Parser* p) {
AstNode* lhs = parse_equality_expr(p);
while (1) {
TokenKind op = peek_token(p)->kind;
- if (op == TokenKind_andand) {
+ if (op == TokenKind_or) {
next_token(p);
AstNode* rhs = parse_equality_expr(p);
+ lhs = ast_new_binary_expr(op, lhs, rhs);
+ lhs->ty = type_new(TypeKind_int);
+ } else {
+ break;
+ }
+ }
+ return lhs;
+}
+
+AstNode* parse_logical_and_expr(Parser* p) {
+ AstNode* lhs = parse_bitwise_or_expr(p);
+ while (1) {
+ TokenKind op = peek_token(p)->kind;
+ if (op == TokenKind_andand) {
+ next_token(p);
+ AstNode* rhs = parse_bitwise_or_expr(p);
AstNode* e = ast_new(AstNodeKind_logical_expr);
e->node_op = op;
e->node_lhs = lhs;
diff --git a/preprocess.c b/preprocess.c
index 4ffe12e..7fa98f3 100644
--- a/preprocess.c
+++ b/preprocess.c
@@ -146,10 +146,16 @@ void pp_tokenize_all(Preprocessor* pp) {
tok->raw.data = pp->src + pp->pos - tok->raw.len;
}
} else if (c == '|') {
- ++pp->pos;
- tok->kind = PpTokenKind_punctuator;
- tok->raw.len = 2;
- tok->raw.data = pp->src + pp->pos - tok->raw.len;
+ if (pp->src[pp->pos] == '|') {
+ ++pp->pos;
+ tok->kind = PpTokenKind_punctuator;
+ tok->raw.len = 2;
+ tok->raw.data = pp->src + pp->pos - tok->raw.len;
+ } else {
+ tok->kind = PpTokenKind_punctuator;
+ tok->raw.len = 1;
+ tok->raw.data = pp->src + pp->pos - tok->raw.len;
+ }
} else if (c == '&') {
if (pp->src[pp->pos] == '&') {
++pp->pos;
diff --git a/tests/067.sh b/tests/067.sh
new file mode 100644
index 0000000..0abac88
--- /dev/null
+++ b/tests/067.sh
@@ -0,0 +1,15 @@
+set -e
+
+cat <<'EOF' > expected
+123
+460
+EOF
+
+bash ../../test_diff.sh <<'EOF'
+int printf();
+
+int main() {
+ printf("%d\n", 0 | 123);
+ printf("%d\n", 12 | 456);
+}
+EOF
diff --git a/tokenize.c b/tokenize.c
index b6b5233..4d4ed8d 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -44,6 +44,7 @@ enum TokenKind {
TokenKind_minusminus,
TokenKind_ne,
TokenKind_not,
+ TokenKind_or,
TokenKind_oror,
TokenKind_paren_l,
TokenKind_paren_r,
@@ -154,6 +155,8 @@ const char* token_kind_stringify(TokenKind k) {
return "!=";
else if (k == TokenKind_not)
return "!";
+ else if (k == TokenKind_or)
+ return "|";
else if (k == TokenKind_oror)
return "||";
else if (k == TokenKind_paren_l)
@@ -316,6 +319,8 @@ void tokenize_all(Lexer* l) {
tok->kind = TokenKind_plus;
} else if (string_equals_cstr(&pp_tok->raw, "||")) {
tok->kind = TokenKind_oror;
+ } else if (string_equals_cstr(&pp_tok->raw, "|")) {
+ tok->kind = TokenKind_or;
} else if (string_equals_cstr(&pp_tok->raw, "&&")) {
tok->kind = TokenKind_andand;
} else if (string_equals_cstr(&pp_tok->raw, "&")) {