aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-05-03 14:56:33 +0900
committernsfisis <nsfisis@gmail.com>2025-05-03 14:56:33 +0900
commitccfab25b9cb3341fe150bb7aae16e3f46cc6ea99 (patch)
treee31fe090628938bff111e0d905b92a119c1b47e2
parente07db70ea48583cac2ab8517586b6a25316cb8ca (diff)
downloadP4Dcc-ccfab25b9cb3341fe150bb7aae16e3f46cc6ea99.tar.gz
P4Dcc-ccfab25b9cb3341fe150bb7aae16e3f46cc6ea99.tar.zst
P4Dcc-ccfab25b9cb3341fe150bb7aae16e3f46cc6ea99.zip
unary minus
-rw-r--r--main.c27
-rw-r--r--tests/005.sh7
2 files changed, 30 insertions, 4 deletions
diff --git a/main.c b/main.c
index 76a7739..3397608 100644
--- a/main.c
+++ b/main.c
@@ -238,10 +238,17 @@ AST* ast_new_list(int kind) {
return ast;
}
+AST* ast_new_unary_expr(int op, AST* operand) {
+ AST* e = ast_new(AST_UNARY_EXPR);
+ e->op = op;
+ e->lhs = operand;
+ return e;
+}
+
AST* ast_new_binary_expr(int op, AST* lhs, AST* rhs) {
AST* e = ast_new(AST_BINARY_EXPR);
- e->lhs = lhs;
e->op = op;
+ e->lhs = lhs;
e->rhs = rhs;
return e;
}
@@ -283,7 +290,7 @@ TOKEN* expect(PARSER*p, int expected) {
AST* parse_expr(PARSER* p);
-AST* parse_primitive_expr(PARSER* p) {
+AST* parse_primary_expr(PARSER* p) {
TOKEN* t = next_token(p);
if (t->kind == TK_L_INT) {
AST* e = ast_new(AST_INT_LIT_EXPR);
@@ -301,13 +308,25 @@ AST* parse_primitive_expr(PARSER* p) {
}
}
+AST* parse_prefix_expr(PARSER* p) {
+ int op = peek_token(p)->kind;
+ if (op == TK_MINUS) {
+ next_token(p);
+ AST* operand = parse_prefix_expr(p);
+ AST* lhs = ast_new(AST_INT_LIT_EXPR);
+ lhs->int_value = 0;
+ return ast_new_binary_expr(op, lhs, operand);
+ }
+ return parse_primary_expr(p);
+}
+
AST* parse_multiplicative_expr(PARSER* p) {
- AST* lhs = parse_primitive_expr(p);
+ AST* lhs = parse_prefix_expr(p);
while (1) {
int op = peek_token(p)->kind;
if (op == TK_STAR || op == TK_SLASH || op == TK_PERCENT) {
next_token(p);
- AST* rhs = parse_primitive_expr(p);
+ AST* rhs = parse_prefix_expr(p);
lhs = ast_new_binary_expr(op, lhs, rhs);
} else {
break;
diff --git a/tests/005.sh b/tests/005.sh
new file mode 100644
index 0000000..1b4611a
--- /dev/null
+++ b/tests/005.sh
@@ -0,0 +1,7 @@
+set -e
+
+bash ../../test_exit_code.sh 30 <<'EOF'
+int main() {
+ return (-10 + 20 * -3) + 100;
+}
+EOF