aboutsummaryrefslogtreecommitdiffhomepage
path: root/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/parse.c b/parse.c
index 61f701e..8f06a83 100644
--- a/parse.c
+++ b/parse.c
@@ -697,6 +697,12 @@ AstNode* parse_conditional_expr(Parser* p) {
}
}
+// constant-expression:
+// conditional-expression
+AstNode* parse_constant_expression(Parser* p) {
+ return parse_conditional_expr(p);
+}
+
AstNode* parse_assignment_expr(Parser* p) {
AstNode* lhs = parse_conditional_expr(p);
while (1) {
@@ -1364,3 +1370,35 @@ Program* parse(TokenArray* tokens) {
prog->str_literals = p->str_literals;
return prog;
}
+
+int eval(AstNode* e) {
+ if (e->kind == AstNodeKind_int_expr) {
+ return e->node_int_value;
+ } else if (e->kind == AstNodeKind_unary_expr) {
+ int v = eval(e->node_operand);
+ if (e->node_op == TokenKind_not) {
+ return !v;
+ } else {
+ unimplemented();
+ }
+ } else if (e->kind == AstNodeKind_binary_expr || e->kind == AstNodeKind_logical_expr) {
+ int v1 = eval(e->node_lhs);
+ int v2 = eval(e->node_rhs);
+ if (e->node_op == TokenKind_andand) {
+ return v1 && v2;
+ } else if (e->node_op == TokenKind_oror) {
+ return v1 || v2;
+ } else {
+ unimplemented();
+ }
+ } else {
+ unimplemented();
+ }
+}
+
+BOOL pp_eval_constant_expression(TokenArray* pp_tokens) {
+ TokenArray* tokens = tokenize(pp_tokens);
+ Parser* p = parser_new(tokens);
+ AstNode* e = parse_constant_expression(p);
+ return eval(e) != 0;
+}