@@ -9,19 +9,44 @@ use yeast::{manual_rule, rule, tree, ConcreteDesugarer, DesugaringConfig, PhaseK
99#[ derive( Clone , Default ) ]
1010struct SwiftContext {
1111 /// Identifier node for the property name. Set by the outer
12- /// `property_binding` (computed accessors / willSet-didSet) rule
13- /// before translating accessor children; read by
14- /// `computed_getter`/`computed_setter`/`computed_modify`/
15- /// `willset_clause`/`didset_clause`.
12+ /// `property_binding` (computed accessors / willSet-didSet) and
13+ /// `protocol_property_declaration` rules before translating accessor
14+ /// children; read by the accessor inner rules
15+ /// (`computed_getter`/`computed_setter`/`computed_modify`/
16+ /// `willset_clause`/`didset_clause`/`getter_specifier`/
17+ /// `setter_specifier`).
1618 property_name : Option < yeast:: Id > ,
1719 /// Translated type node for the property type. Set by the outer
18- /// `property_binding` rule (computed accessors variant) when
19- /// present; read by `computed_*` rules.
20+ /// `property_binding` rule (computed accessors variant) and
21+ /// `protocol_property_declaration` when present; read by the
22+ /// accessor inner rules.
2023 property_type : Option < yeast:: Id > ,
2124 /// Default-value expression for the next translated `parameter`. Set
2225 /// by the outer `function_parameter` rule; read by the `parameter`
2326 /// rules.
2427 default_value : Option < yeast:: Id > ,
28+ /// Translated outer modifiers (e.g. visibility, attributes) to
29+ /// attach to each child of a flattening outer rule. Set by
30+ /// `protocol_property_declaration` (and, later,
31+ /// `property_declaration`/`enum_entry`).
32+ outer_modifiers : Vec < yeast:: Id > ,
33+ /// True when the current child of a flattening outer rule is not
34+ /// the first one — its inner rule should emit a
35+ /// `chained_declaration` modifier so the original grouping can be
36+ /// recovered downstream.
37+ is_chained : bool ,
38+ }
39+
40+ /// Build a freshly-created `chained_declaration` modifier node if
41+ /// `ctx.is_chained`, else `None`. Used by inner declaration rules to
42+ /// emit the chained tag for non-first children of a flattening outer
43+ /// rule. Returns `Option<Id>` so it splices via `{..…}` to 0 or 1 ids.
44+ fn chained_modifier ( ctx : & mut yeast:: build:: BuildCtx < ' _ , SwiftContext > ) -> Option < yeast:: Id > {
45+ if ctx. is_chained {
46+ Some ( ctx. literal ( "modifier" , "chained_declaration" ) )
47+ } else {
48+ None
49+ }
2550}
2651
2752fn translation_rules ( ) -> Vec < Rule < SwiftContext > > {
@@ -904,41 +929,61 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
904929 name: ( identifier #{ name} )
905930 bound: { ..bound} )
906931 ) ,
907- // Protocol property declaration: translate each accessor requirement to an
908- // accessor_declaration without a body, carrying the property name and type.
909- // Subsequent accessors get chained_declaration (same flattening as computed properties).
910- rule!(
932+ // Protocol property declaration: translate each accessor
933+ // requirement to an `accessor_declaration` carrying the property
934+ // name, type, and outer modifiers. Manual rule: we publish the
935+ // property's name/type/modifiers into `ctx` and translate each
936+ // accessor with `ctx.is_chained` toggled per iteration so the
937+ // inner `getter_specifier`/`setter_specifier` rules emit
938+ // complete nodes from the start (including the
939+ // `chained_declaration` tag for non-first accessors).
940+ manual_rule!(
911941 ( protocol_property_declaration
912- name: @ pattern
942+ name: ( pattern bound_identifier : @name )
913943 requirements: ( protocol_property_requirements accessor: _+ @accessors)
914944 type : _? @ty
915945 ( modifiers) * @mods)
916- =>
917- { ..{
918- let name_text = ctx. ast. source_text( pattern. into( ) ) ;
919- let mod_ids: Vec <usize > = mods. iter( ) . map( |& m| m. into( ) ) . collect( ) ;
920- let ty_ids: Vec <usize > = ty. iter( ) . map( |& t| t. into( ) ) . collect( ) ;
921- let acc_ids: Vec <usize > = accessors. iter( ) . map( |& a| a. into( ) ) . collect( ) ;
922- for ( i, & acc_id) in acc_ids. iter( ) . enumerate( ) {
923- if i > 0 {
924- let chained = ctx. literal( "modifier" , "chained_declaration" ) ;
925- ctx. prepend_field( acc_id, "modifier" , chained) ;
926- }
927- for & mod_id in mod_ids. iter( ) . rev( ) {
928- ctx. prepend_field( acc_id, "modifier" , mod_id) ;
929- }
930- for & ty_id in ty_ids. iter( ) . rev( ) {
931- ctx. prepend_field( acc_id, "type" , ty_id) ;
932- }
933- let ident = ctx. literal( "identifier" , & name_text) ;
934- ctx. prepend_field( acc_id, "name" , ident) ;
946+ {
947+ ctx. property_name = Some ( tree!( ( identifier #{ name} ) ) ) ;
948+ ctx. property_type = ctx. translate_opt( ty) ?;
949+ let mut modifiers = Vec :: new( ) ;
950+ for m in mods {
951+ modifiers. extend( ctx. translate( m) ?) ;
935952 }
936- acc_ids
937- } }
953+ ctx. outer_modifiers = modifiers;
954+
955+ let mut result = Vec :: new( ) ;
956+ for ( i, acc) in accessors. into_iter( ) . enumerate( ) {
957+ ctx. is_chained = i > 0 ;
958+ result. extend( ctx. translate( acc) ?) ;
959+ }
960+ Ok ( result)
961+ }
938962 ) ,
939963 // getter_specifier / setter_specifier → bodyless accessor_declaration
940- rule!( ( getter_specifier) => ( accessor_declaration accessor_kind: ( accessor_kind "get" ) ) ) ,
941- rule!( ( setter_specifier) => ( accessor_declaration accessor_kind: ( accessor_kind "set" ) ) ) ,
964+ // getter_specifier / setter_specifier → bodyless
965+ // accessor_declaration. Reads property name/type/modifiers from
966+ // `ctx` set by the outer `protocol_property_declaration` rule.
967+ rule!(
968+ ( getter_specifier)
969+ =>
970+ ( accessor_declaration
971+ name: { ctx. property_name. ok_or( "getter_specifier outside protocol_property_declaration context" ) ?}
972+ type : { ..ctx. property_type}
973+ accessor_kind: ( accessor_kind "get" )
974+ modifier: { ..ctx. outer_modifiers. clone( ) }
975+ modifier: { ..chained_modifier( & mut ctx) } )
976+ ) ,
977+ rule!(
978+ ( setter_specifier)
979+ =>
980+ ( accessor_declaration
981+ name: { ctx. property_name. ok_or( "setter_specifier outside protocol_property_declaration context" ) ?}
982+ type : { ..ctx. property_type}
983+ accessor_kind: ( accessor_kind "set" )
984+ modifier: { ..ctx. outer_modifiers. clone( ) }
985+ modifier: { ..chained_modifier( & mut ctx) } )
986+ ) ,
942987 // protocol_property_requirements wrapper — should be consumed by above; fallback
943988 rule!( ( protocol_property_requirements accessor: _* @accs) => { ..accs} ) ,
944989 // Computed getter → accessor_declaration (body optional).
0 commit comments