We start by inlining member_access, post_increment_expression and post_decrement_expression. Then we do SLRR on primary_no_array_creation_expression:
primary_no_array_creation_expression
: (literal
| simple_name
| parenthesized_expression
| predefined_type DOT IDENTIFIER type_argument_list?
| qualified_alias_member DOT IDENTIFIER type_argument_list?
| invocation_expression
| this_access
| base_access
| array_creation_expression DOT IDENTIFIER type_argument_list?
| array_creation_expression OP_INC
| array_creation_expression OP_DEC
| array_creation_expression OP_PTR IDENTIFIER
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| anonymous_method_expression
| sizeof_expression
) (DOT IDENTIFIER type_argument_list?
| OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET
| OP_INC
| OP_DEC
| OP_PTR IDENTIFIER)*
;
Then we inline primary_no_array_creation_expression itself. Again we extract the trailing into a temporary subrule and in-factor its reference, before we do another SLRR.
invocation_expression
: (array_creation_expression OPEN_PARENS argument_list? CLOSE_PARENS
| literal invocation_expression_trailing
| simple_name invocation_expression_trailing
| parenthesized_expression invocation_expression_trailing
| predefined_type DOT IDENTIFIER type_argument_list? invocation_expression_trailing
| qualified_alias_member DOT IDENTIFIER type_argument_list? invocation_expression_trailing
| this_access invocation_expression_trailing
| base_access invocation_expression_trailing
| array_creation_expression DOT IDENTIFIER type_argument_list? invocation_expression_trailing
| array_creation_expression OP_INC invocation_expression_trailing
| array_creation_expression OP_DEC invocation_expression_trailing
| array_creation_expression OP_PTR IDENTIFIER invocation_expression_trailing
| object_creation_expression invocation_expression_trailing
| delegate_creation_expression invocation_expression_trailing
| anonymous_object_creation_expression invocation_expression_trailing
| typeof_expression invocation_expression_trailing
| checked_expression invocation_expression_trailing
| unchecked_expression invocation_expression_trailing
| default_value_expression invocation_expression_trailing
| anonymous_method_expression invocation_expression_trailing
| sizeof_expression invocation_expression_trailing
) invocation_expression_trailing*
;
invocation_expression_trailing
: (DOT IDENTIFIER type_argument_list?
| OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET
| OP_INC
| OP_DEC
| OP_PTR IDENTIFIER)* OPEN_PARENS argument_list? CLOSE_PARENS
;
The situation is analogous to member_expression above.
invocation_expression
: (array_creation_expression
| literal
| simple_name
| parenthesized_expression
| predefined_type DOT IDENTIFIER type_argument_list?
| qualified_alias_member DOT IDENTIFIER type_argument_list?
| this_access
| base_access
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| anonymous_method_expression
| sizeof_expression
) (DOT IDENTIFIER type_argument_list?
| OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET
| OP_INC
| OP_DEC
| OP_PTR IDENTIFIER
| OPEN_PARENS argument_list? CLOSE_PARENS)+
;
The second pass has to check that array_creation_expression may not be followed by OPEN_BRACKET. It has to be also checked that OPEN_PARENS argument_list? CLOSE_PARENS is the last matched sequence.