From b71f85a7c3ee9e36b6eab9f113436fa990f6e561 Mon Sep 17 00:00:00 2001 From: Mel Date: Sat, 5 Jul 2025 20:27:08 +0200 Subject: Try (?) & must (!) expressions Signed-off-by: Mel --- boot/parse.c | 33 +++++++++++++++++++++++++++++++++ boot/tests/parse/try_must.cskt | 0 boot/tree.c | 14 ++++++++++++++ boot/visit.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 boot/tests/parse/try_must.cskt diff --git a/boot/parse.c b/boot/parse.c index 7b40fb1..c08d247 100644 --- a/boot/parse.c +++ b/boot/parse.c @@ -895,6 +895,34 @@ parser_expression_postfix_subscript( return subject; } +struct Expression* +parser_expression_postfix_try( + struct Parser* p, struct Expression* subject, struct Parser_Error* error) +{ + while (parser_probe(p, TOKEN_QUESTION)) { + struct Token question_token = parser_next(p); + + struct Span span = span_merge(subject->span, question_token.span); + union Expression_Value value = { .try = { subject } }; + subject = expression_new(EXPRESSION_TRY, value, span, subject->location); + } + return subject; +} + +struct Expression* +parser_expression_postfix_must( + struct Parser* p, struct Expression* subject, struct Parser_Error* error) +{ + while (parser_probe(p, TOKEN_BANG)) { + struct Token bang_token = parser_next(p); + + struct Span span = span_merge(subject->span, bang_token.span); + union Expression_Value value = { .try = { subject } }; + subject = expression_new(EXPRESSION_MUST, value, span, subject->location); + } + return subject; +} + struct Expression* parser_expression_postfix(struct Parser* p, struct Parser_Error* error) { @@ -906,6 +934,11 @@ parser_expression_postfix(struct Parser* p, struct Parser_Error* error) return parser_expression_postfix_call_or_construct(p, expression, error); case TOKEN_SQUARE_OPEN: return parser_expression_postfix_subscript(p, expression, error); + + case TOKEN_QUESTION: + return parser_expression_postfix_try(p, expression, error); + case TOKEN_BANG: + return parser_expression_postfix_must(p, expression, error); default:; } diff --git a/boot/tests/parse/try_must.cskt b/boot/tests/parse/try_must.cskt new file mode 100644 index 0000000..e69de29 diff --git a/boot/tree.c b/boot/tree.c index dc22bfd..3c808f8 100644 --- a/boot/tree.c +++ b/boot/tree.c @@ -688,6 +688,8 @@ enum Expression_Kind EXPRESSION_SUBSCRIPT, EXPRESSION_MEMBER, EXPRESSION_INCREMENT_DECREMENT, + EXPRESSION_TRY, + EXPRESSION_MUST, EXPRESSION_FUNCTION, EXPRESSION_TYPE, @@ -766,6 +768,16 @@ struct Expression_Increment_Decrement enum Increment_Decrement_Operation operation; }; +struct Expression_Try +{ + struct Expression* expression; +}; + +struct Expression_Must +{ + struct Expression* expression; +}; + struct Expression_Function { struct Function_Header_Node header; @@ -791,6 +803,8 @@ union Expression_Value struct Expression_Subscript subscript; struct Expression_Member member; struct Expression_Increment_Decrement increment_decrement; + struct Expression_Try try; + struct Expression_Must must; struct Expression_Function function; struct Expression_Type type; }; diff --git a/boot/visit.c b/boot/visit.c index 3cc3e55..c1dd797 100644 --- a/boot/visit.c +++ b/boot/visit.c @@ -45,6 +45,8 @@ struct Visit_Table void (*visit_expression_subscript)(struct Visit* visitor, struct Expression* expr); void (*visit_expression_member)(struct Visit* visitor, struct Expression* expr); void (*visit_expression_increment_decrement)(struct Visit* visitor, struct Expression* expr); + void (*visit_expression_try)(struct Visit* visitor, struct Expression* expr); + void (*visit_expression_must)(struct Visit* visitor, struct Expression* expr); void (*visit_expression_function)(struct Visit* visitor, struct Expression* expr); void (*visit_type_node)(struct Visit* visitor, struct Type_Node* node); @@ -219,6 +221,12 @@ walk_expression(struct Visit* visit, struct Expression* expression) case EXPRESSION_INCREMENT_DECREMENT: VISIT(visit_expression_increment_decrement, expression); break; + case EXPRESSION_TRY: + VISIT(visit_expression_try, expression); + break; + case EXPRESSION_MUST: + VISIT(visit_expression_must, expression); + break; case EXPRESSION_FUNCTION: VISIT(visit_expression_function, expression); break; @@ -286,6 +294,10 @@ walk_expression_increment_decrement(struct Visit* visit, struct Expression* expr VISIT(visit_expression, expression->value.increment_decrement.subject); } +WALK_LEAF_FUNCTION(walk_expression_try, struct Expression*); + +WALK_LEAF_FUNCTION(walk_expression_must, struct Expression*); + void walk_expression_function(struct Visit* visit, struct Expression* expression) { @@ -814,6 +826,26 @@ printer_visit_expression_increment_decrement(struct Visit* visit, struct Express PRINT(")"); } +void +printer_visit_expression_try(struct Visit* visit, struct Expression* expr) +{ + TREE_PRINTER_PREAMBLE + + PRINT("(try "); + VISIT(visit_expression, expr->value.try.expression); + PRINT(")"); +} + +void +printer_visit_expression_must(struct Visit* visit, struct Expression* expr) +{ + TREE_PRINTER_PREAMBLE + + PRINT("(must "); + VISIT(visit_expression, expr->value.must.expression); + PRINT(")"); +} + void printer_visit_expression_function(struct Visit* visit, struct Expression* expr) { @@ -1064,6 +1096,8 @@ struct Visit_Table printer_visit_functions = { .visit_expression_subscript = printer_visit_expression_subscript, .visit_expression_member = printer_visit_expression_member, .visit_expression_increment_decrement = printer_visit_expression_increment_decrement, + .visit_expression_try = printer_visit_expression_try, + .visit_expression_must = printer_visit_expression_must, .visit_expression_function = printer_visit_expression_function, .visit_type_node = printer_visit_type_node, -- cgit 1.4.1