Firstly, we can do SLRR and simplification with primary_no_array_creation_expression:
primary_no_array_creation_expression
: (literal
| simple_name
| parenthesized_expression
| member_access
| invocation_expression
| this_access
| base_access
| post_increment_expression
| post_decrement_expression
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| anonymous_method_expression
| sizeof_expression
| primary_expression OP_PTR IDENTIFIER
) (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
;
The rest of the rule inlining is simple. It leads to
primary_expression
: array_creation_expression
| (literal
| simple_name
| parenthesized_expression
| primary_expression DOT IDENTIFIER type_argument_list?
| predefined_type DOT IDENTIFIER type_argument_list?
| qualified_alias_member DOT IDENTIFIER type_argument_list?
| primary_expression OPEN_PARENS argument_list? CLOSE_PARENS
| this_access
| base_access
| primary_expression OP_INC
| primary_expression OP_DEC
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| anonymous_method_expression
| sizeof_expression
| primary_expression OP_PTR IDENTIFIER
) (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
;
This point seems to be problematic. primary_expression is actually SLR. But due to the parentheses ANTLR considers them MLR. In-factoring is the only and somewhat ugly solution to allow SLRR:
primary_expression
: (array_creation_expression
| literal (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| simple_name (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| parenthesized_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| predefined_type DOT IDENTIFIER type_argument_list? (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| qualified_alias_member DOT IDENTIFIER type_argument_list? (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| this_access (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| base_access (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| object_creation_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| delegate_creation_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| anonymous_object_creation_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| typeof_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| checked_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| unchecked_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| default_value_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| anonymous_method_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
| sizeof_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*
) ( (DOT IDENTIFIER type_argument_list?
| OPEN_PARENS argument_list? CLOSE_PARENS
| OP_INC
| OP_DEC
| OP_PTR IDENTIFIER
)
(OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*)*
;
The only simplification which preserves the equivalence without checking for validity would be the out-factoring of "(OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*", but as I use a second pass for my compiler a further simplification can be done.
The first move is to pretend the line "array_creation_expression (OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET)*" and out-factor the inner trailing. Thus the outer trailing can be turn into:
primary_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_PARENS argument_list? CLOSE_PARENS
| OP_INC
| OP_DEC
| OP_PTR IDENTIFIER
| OPEN_BRACKET (expression_list | expression) CLOSE_BRACKET
)*
;
For now we can leave this rule like this and move on.