@@ -450,6 +450,114 @@ fn translation_rules() -> Vec<yeast::Rule> {
450450 callee: { func}
451451 argument: ( argument value: { closure} ) )
452452 ) ,
453+ // ---- Control flow ----
454+ rule!(
455+ ( if_statement condition: _* @cond body: @then_body else_branch: _? @else_stmts)
456+ =>
457+ ( if_expr
458+ condition: { ..cond} . reduce_left( first -> { first} , acc, elem -> ( binary_expr operator: ( infix_operator "&&" ) left: { acc} right: { elem} ) )
459+ then: { then_body}
460+ else: { ..else_stmts} )
461+ ) ,
462+ // Guard statement
463+ rule!(
464+ ( guard_statement condition: _* @cond body: ( block statement: _* @else_stmts) )
465+ =>
466+ ( guard_if_stmt
467+ condition: { ..cond} . reduce_left( first -> { first} , acc, elem -> ( binary_expr operator: ( infix_operator "&&" ) left: { acc} right: { elem} ) )
468+ else: ( block stmt: { ..else_stmts} ) )
469+ ) ,
470+ // Ternary expression → if_expr
471+ rule!(
472+ ( ternary_expression condition: @cond if_true: @then_val if_false: @else_val)
473+ =>
474+ ( if_expr condition: { cond} then: { then_val} else: { else_val} )
475+ ) ,
476+ // Switch statement
477+ rule!(
478+ ( switch_statement expr: @val entry: ( switch_entry) * @cases)
479+ =>
480+ ( switch_expr value: { val} case: { ..cases} )
481+ ) ,
482+ // Switch entry with patterns and body
483+ rule!(
484+ ( switch_entry pattern: ( switch_pattern) * @pats statement: _* @body)
485+ =>
486+ ( switch_case pattern: { ..pats} body: ( block stmt: { ..body} ) )
487+ ) ,
488+ // Switch entry: default case (no patterns)
489+ rule!(
490+ ( switch_entry default : ( default_keyword) statement: _* @body)
491+ =>
492+ ( switch_case body: ( block stmt: { ..body} ) )
493+ ) ,
494+ // Switch pattern — unwrap to inner pattern
495+ rule!( ( switch_pattern ( pattern) * @inner) => { ..inner} ) ,
496+ // if case let x = expr — the pattern is taken as-is (no Optional wrapping)
497+ rule!(
498+ ( if_let_binding "case" ( value_binding_pattern) bound_identifier: @name _ @val)
499+ =>
500+ ( pattern_guard_expr
501+ value: { val}
502+ pattern: ( name_pattern identifier: ( identifier #{ name} ) ) )
503+ ) ,
504+ rule!(
505+ ( if_let_binding
506+ pattern: ( pattern binding: ( value_binding_pattern) bound_identifier: @name)
507+ value: @val)
508+ =>
509+ ( pattern_guard_expr
510+ value: { val}
511+ pattern: ( constructor_pattern
512+ constructor: ( member_access_expr base: ( named_type_expr name: ( identifier "Optional" ) ) member: ( identifier "some" ) )
513+ element: ( pattern_element pattern: ( name_pattern identifier: ( identifier #{ name} ) ) ) ) )
514+ ) ,
515+ // Shorthand if let x (Swift 5.7+) — also semantically .some(x)
516+ rule!(
517+ ( if_let_binding
518+ pattern: ( pattern binding: ( value_binding_pattern) bound_identifier: @name) )
519+ =>
520+ ( pattern_guard_expr
521+ value: ( name_expr identifier: ( identifier #{ name} ) )
522+ pattern: ( constructor_pattern
523+ constructor: ( member_access_expr base: ( named_type_expr name: ( identifier "Optional" ) ) member: ( identifier "some" ) )
524+ element: ( pattern_element pattern: ( name_pattern identifier: ( identifier #{ name} ) ) ) ) )
525+ ) ,
526+ // If-condition — unwrap (pass through the inner expression/pattern)
527+ rule!( ( if_condition kind: @inner) => { inner} ) ,
528+ // ---- Loops ----
529+ // For-in loop with optional where-clause guard.
530+ rule!(
531+ ( for_statement
532+ item: @pat
533+ collection: @iter
534+ where : ( where_clause expr: @guard) ?
535+ body: ( block statement: _* @body) )
536+ =>
537+ ( for_each_stmt
538+ pattern: { pat}
539+ iterable: { iter}
540+ guard: { ..guard}
541+ body: ( block stmt: { ..body} ) )
542+ ) ,
543+ // While loop
544+ rule!(
545+ ( while_statement condition: _* @cond body: ( block statement: _* @body) )
546+ =>
547+ ( while_stmt condition: { ..cond} . reduce_left( first -> { first} , acc, elem -> ( binary_expr operator: ( infix_operator "&&" ) left: { acc} right: { elem} ) ) body: ( block stmt: { ..body} ) )
548+ ) ,
549+ // Repeat-while loop
550+ rule!(
551+ ( repeat_while_statement condition: _* @cond body: ( block statement: _* @body) )
552+ =>
553+ ( do_while_stmt condition: { ..cond} . reduce_left( first -> { first} , acc, elem -> ( binary_expr operator: ( infix_operator "&&" ) left: { acc} right: { elem} ) ) body: ( block stmt: { ..body} ) )
554+ ) ,
555+ // Labeled statement (e.g. `outer: for ...`). Strip the trailing ':' from the label token.
556+ rule!( ( labeled_statement label: ( statement_label) @lbl statement: @stmt) => { ..{
557+ let text = __yeast_ctx. ast. source_text( lbl. into( ) ) ;
558+ let name = __yeast_ctx. literal( "identifier" , & text[ ..text. len( ) - 1 ] ) ;
559+ vec![ __yeast_ctx. node( "labeled_stmt" , vec![ ( "label" , vec![ name] ) , ( "stmt" , vec![ stmt. into( ) ] ) ] ) ]
560+ } } ) ,
453561 // ---- Fallbacks ----
454562 rule!(
455563 ( _)
0 commit comments