This time we remove the left-recursion of the rule type, right at the beginning:
type
: (type_name
| simple_type
| enum_type
| class_type
| interface_type
| array_type
| delegate_type
| type_parameter
| pointer_type
) INTERR*
;
Now we inline type and simplify further. I inline unmanaged_type as next and in-factor "INTERR* STAR" to each subrule, so that I can remove the left-recursion in pointer_type. Because of the assymmetric "VOID STAR" subrule I inline pointer_type instead doing some optimization, except turning the trailing into "(INTERR | STAR)*". Then we arrive at
non_array_type
: (type_name
| simple_type
| enum_type
| class_type
| interface_type
| array_type
| delegate_type
| type_parameter
| (type_name INTERR* STAR
| simple_type INTERR* STAR
| enum_type INTERR* STAR
| class_type INTERR* STAR
| interface_type INTERR* STAR
| array_type INTERR* STAR
| delegate_type INTERR* STAR
| type_parameter INTERR* STAR
| VOID STAR
) (INTERR | STAR)*
) INTERR*
;
Taking the near duplicates into account, "INTERR* STAR (INTERR | STAR)" is transformable into "INTERR* STAR? (INTERR | STAR)" and this is "(INTERR | STAR)*". We then obtain
non_array_type
: (type_name (INTERR | STAR)*
| simple_type (INTERR | STAR)*
| enum_type (INTERR | STAR)*
| class_type (INTERR | STAR)*
| interface_type (INTERR | STAR)*
| array_type (INTERR | STAR)*
| delegate_type (INTERR | STAR)*
| type_parameter (INTERR | STAR)*
| VOID STAR (INTERR | STAR)*
) INTERR*
;
The last INTERR* can be safely deleted. Then after some rule-inling, SLRR and simplification we arrive at
array_type
: type_name (STAR | INTERR)* rank_specifier+
| simple_type (STAR | INTERR)* rank_specifier+
| enum_type (STAR | INTERR)* rank_specifier+
| class_type (STAR | INTERR)* rank_specifier+
| interface_type (STAR | INTERR)* rank_specifier+
| array_type (STAR | INTERR)* rank_specifier+
| delegate_type (STAR | INTERR)* rank_specifier+
| type_parameter (STAR | INTERR)* rank_specifier+
| VOID STAR (STAR | INTERR)* rank_specifier+
;
Now repeat SLRR and simplify the result to
array_type
: (type_name
| simple_type
| enum_type
| class_type
| interface_type
| delegate_type
| type_parameter
| VOID STAR
) ((STAR | INTERR)* rank_specifier)+
;
"((STAR | INTERR)* rank_specifier)" is similar to "(+STAR +| INTERR | rank_specifier+)+", if there is at least one rank_specifier. This can be checked with:
array_type
: (type_name
| simple_type
| enum_type
| class_type
| interface_type
| delegate_type
| type_parameter
| VOID STAR
) (STAR | INTERR | r+=rank_specifier)+ {$r.Count >= 1}?
;
Sections
My siblings (including me):