Skip to content

Commit 143bdc0

Browse files
Nigel-Ecmajskeet
authored andcommitted
Addresses issue #1283.
Updates §6.2.5 as per issue and also changes the descriptive style to the proscriptive requirement of the Standard
1 parent bebc600 commit 143bdc0

File tree

2 files changed

+55
-43
lines changed

2 files changed

+55
-43
lines changed

standard/expressions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4161,7 +4161,7 @@ equality_expression
41614161
;
41624162
```
41634163

4164-
> *Note*: Lookup for the right operand of the `is` operator must first test as a *type*, then as an *expression* which may span multiple tokens. In the case where the operand is an *expreesion*, the pattern expression must have precedence at least as high as *shift_expression*. *end note*
4164+
> *Note*: Lookup for the right operand of the `is` operator must first test as a *type*, then as an *expression* which may span multiple tokens. In the case where the operand is an *expression*, the pattern expression must have precedence at least as high as *shift_expression*. *end note*
41654165
41664166
The `is` operator is described in [§12.12.12](expressions.md#121212-the-is-operator) and the `as` operator is described in [§12.12.13](expressions.md#121213-the-as-operator).
41674167

standard/lexical-structure.md

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,18 @@ Every compilation unit in a C# program shall conform to the *compilation_unit*
5252

5353
### 6.2.5 Grammar ambiguities
5454

55-
The productions for *simple_name* ([§12.8.4](expressions.md#1284-simple-names)) and *member_access* ([§12.8.7](expressions.md#1287-member-access)) can give rise to ambiguities in the grammar for expressions.
55+
The productions for:
56+
57+
- *simple_name* ([§12.8.4](expressions.md#1284-simple-names)),
58+
- *member_access* ([§12.8.7](expressions.md#1287-member-access)),
59+
- *null_conditional_member_access* ([§12.8.8](expressions.md#1288-null-conditional-member-access)),
60+
- *dependent_access* ([§12.8.8](expressions.md#1288-dependent-access)),
61+
- *base_access* ([§12.8.15](expressions.md#12815-base-access)) and
62+
- *pointer_member_access* ([§23.6.3](unsafe-code.md#2363-pointer-member-access));
63+
64+
(the “disambiguated productions”) can give rise to ambiguities in the grammar for expressions.
65+
66+
These productions occur in contexts where a value can occur in an expression, and have one or more alternatives that end with the grammar “`identifier type_argument_list?`”. It is the optional *type_argument_list* which results in the possible ambiguity.
5667

5768
> *Example*: The statement:
5869
>
@@ -65,16 +76,17 @@ The productions for *simple_name* ([§12.8.4](expressions.md#1284-simple-names))
6576
>
6677
> *end example*
6778
68-
If a sequence of tokens can be parsed (in context) as a *simple_name* ([§12.8.4](expressions.md#1284-simple-names)), *member_access* ([§12.8.7](expressions.md#1287-member-access)), or *pointer_member_access* ([§23.6.3](unsafe-code.md#2363-pointer-member-access)) ending with a *type_argument_list* ([§8.4.2](types.md#842-type-arguments)), the token immediately following the closing `>token is examined, to see if it is
79+
If a sequence of tokens can be parsed, in context, as one of the disambiguated productions
80+
including an optional *type_argument_list* ([§8.4.2](types.md#842-type-arguments)), then
81+
the token immediately following the closing `>token shall be examined and if it is:
6982
70-
- One of `( ) ] } : ; , . ? == != | ^ && || & [`; or
71-
- One of the relational operators `< <= >= is as`; or
72-
- A contextual query keyword appearing inside a query expression; or
73-
- In certain contexts, *identifier* is treated as a disambiguating token. Those contexts are where the sequence of tokens being disambiguated is immediately preceded by one of the keywords `is`, `case` or `out`, or arises while parsing the first element of a tuple literal (in which case the tokens are preceded by `(` or `:` and the identifier is followed by a `,`) or a subsequent element of a tuple literal.
83+
- one of `( ) ] } : ; , . ? == != | ^ && || & [`; or
84+
- one of the relational operators `< <= >= is as`; or
85+
- a contextual query keyword appearing inside a query expression.
7486
75-
If the following token is among this list, or an identifier in such a context, then the *type_argument_list* is retained as part of the *simple_name*, *member_access* or *pointer_member-access* and any other possible parse of the sequence of tokens is discarded. Otherwise, the *type_argument_list* is not considered to be part of the *simple_name*, *member_access* or *pointer_member_access*, even if there is no other possible parse of the sequence of tokens.
87+
then the *type_argument_list* shall be retained as part of the disambiguated production and any other possible parse of the sequence of tokens discarded. Otherwise, the tokens parsed as a *type_argument_list* shall not be considered to be part of the disambiguated production, even if there is no other possible parse of those tokens.
7688
77-
> *Note*: These rules are not applied when parsing a *type_argument_list* in a *namespace_or_type_name* ([§7.8](basic-concepts.md#78-namespace-and-type-names)). *end note*
89+
> *Note*: These disambiguation rules shall not be applied when parsing other productions even if they similarly end in “`identifier type_argument_list?`”; such productions shall be parsed as normal. Examples include: *namespace_or_type_name* ([§7.8](basic-concepts.md#78-namespace-and-type-names)); *named_entity* ([§12.8.23](expressions.md#12823-named-entity)); *null_conditional_projection_initializer* ([§12.8.8](expressions.md1288-null_conditional-projection-initializer)); and *qualified_alias_member* ([§14.8.1](namespaces.md#1481-qualified-alias-member)). *end note*
7890
<!-- markdownlint-disable MD028 -->
7991
8092
<!-- markdownlint-enable MD028 -->
@@ -124,7 +136,7 @@ If the following token is among this list, or an identifier in such a context, t
124136
>
125137
> *end example*
126138
127-
When recognising a *relational_expression* ([§12.12.1](expressions.md#12121-general)) if both the “*relational_expression* `is` *type*” and “*relational_expression* `is` *constant_pattern*” alternatives are applicable, and *type* resolves to an accessible type, then the “*relational_expression* `is` *type*” alternative shall be chosen.
139+
When recognising a *relational_expression* ([§12.12.1](expressions.md#12121-general)) if both the “*relational_expression* `is` *type*” and “*relational_expression* `is` *pattern*” alternatives are applicable, and *type* resolves to an accessible type, then the “*relational_expression* `is` *type*” alternative shall be chosen.
128140
129141
## 6.3 Lexical analysis
130142
@@ -189,7 +201,7 @@ Line terminators divide the characters of a C# compilation unit into lines.
189201
```ANTLR
190202
New_Line
191203
: New_Line_Character
192-
| '\u000D\u000A' // carriage return, line feed
204+
| '\u000D\u000A' // carriage return, line feed
193205
;
194206
```
195207
@@ -262,19 +274,19 @@ fragment Input_Character
262274
// anything but New_Line_Character
263275
: ~('\u000D' | '\u000A' | '\u0085' | '\u2028' | '\u2029')
264276
;
265-
277+
266278
fragment New_Line_Character
267279
: '\u000D' // carriage return
268280
| '\u000A' // line feed
269281
| '\u0085' // next line
270282
| '\u2028' // line separator
271283
| '\u2029' // paragraph separator
272284
;
273-
285+
274286
fragment Delimited_Comment
275287
: '/*' Delimited_Comment_Section* ASTERISK+ '/'
276288
;
277-
289+
278290
fragment Delimited_Comment_Section
279291
: SLASH
280292
| ASTERISK* Not_Slash_Or_Asterisk
@@ -428,7 +440,7 @@ fragment Available_Identifier
428440
fragment Escaped_Identifier
429441
// Includes keywords and contextual keywords prefixed by '@'.
430442
// See note below.
431-
: '@' Basic_Identifier
443+
: '@' Basic_Identifier
432444
;
433445
434446
fragment Basic_Identifier
@@ -664,36 +676,36 @@ fragment Decimal_Integer_Literal
664676
fragment Decorated_Decimal_Digit
665677
: '_'* Decimal_Digit
666678
;
667-
679+
668680
fragment Decimal_Digit
669681
: '0'..'9'
670682
;
671-
683+
672684
fragment Integer_Type_Suffix
673685
: 'U' | 'u' | 'L' | 'l' |
674686
'UL' | 'Ul' | 'uL' | 'ul' | 'LU' | 'Lu' | 'lU' | 'lu'
675687
;
676-
688+
677689
fragment Hexadecimal_Integer_Literal
678690
: ('0x' | '0X') Decorated_Hex_Digit+ Integer_Type_Suffix?
679691
;
680692
681693
fragment Decorated_Hex_Digit
682694
: '_'* Hex_Digit
683695
;
684-
696+
685697
fragment Hex_Digit
686698
: '0'..'9' | 'A'..'F' | 'a'..'f'
687699
;
688-
700+
689701
fragment Binary_Integer_Literal
690702
: ('0b' | '0B') Decorated_Binary_Digit+ Integer_Type_Suffix?
691703
;
692704
693705
fragment Decorated_Binary_Digit
694706
: '_'* Binary_Digit
695707
;
696-
708+
697709
fragment Binary_Digit
698710
: '0' | '1'
699711
;
@@ -723,14 +735,14 @@ To permit the smallest possible `int` and `long` values to be written as integer
723735
> 1_2__3___4____5 // decimal, int
724736
> _123 // not a numeric literal; identifier due to leading _
725737
> 123_ // invalid; no trailing _allowed
726-
>
738+
>
727739
> 0xFf // hex, int
728740
> 0X1b_a0_44_fEL // hex, long
729741
> 0x1ade_3FE1_29AaUL // hex, ulong
730742
> 0x_abc // hex, int
731743
> _0x123 // not a numeric literal; identifier due to leading _
732744
> 0xabc_ // invalid; no trailing _ allowed
733-
>
745+
>
734746
> 0b101 // binary, int
735747
> 0B1001_1010u // binary, uint
736748
> 0b1111_1111_0000UL // binary, ulong
@@ -774,7 +786,7 @@ If no *Real_Type_Suffix* is specified, the type of the *Real_Literal* is `double
774786
- A real literal suffixed by `D` or `d` is of type `double`.
775787
> *Example*: The literals `1d`, `1.5d`, `1e10d`, and `123.456D` are all of type `double`. *end example*
776788
- A real literal suffixed by `M` or `m` is of type `decimal`.
777-
> *Example*: The literals `1m`, `1.5m`, `1e10m`, and `123.456M` are all of type `decimal`. *end example*
789+
> *Example*: The literals `1m`, `1.5m`, `1e10m`, and `123.456M` are all of type `decimal`. *end example*
778790
This literal is converted to a `decimal` value by taking the exact value, and, if necessary, rounding to the nearest representable value using banker’s rounding ([§8.3.8](types.md#838-the-decimal-type)). Any scale apparent in the literal is preserved unless the value is rounded.
779791
> *Note*: Hence, the literal `2.900m` will be parsed to form the `decimal` with sign `0`, coefficient `2900`, and scale `3`. *end note*
780792
@@ -812,24 +824,24 @@ A character literal represents a single character, and consists of a character i
812824
Character_Literal
813825
: '\'' Character '\''
814826
;
815-
827+
816828
fragment Character
817829
: Single_Character
818830
| Simple_Escape_Sequence
819831
| Hexadecimal_Escape_Sequence
820832
| Unicode_Escape_Sequence
821833
;
822-
834+
823835
fragment Single_Character
824836
// anything but ', \, and New_Line_Character
825837
: ~['\\\u000D\u000A\u0085\u2028\u2029]
826838
;
827-
839+
828840
fragment Simple_Escape_Sequence
829841
: '\\\'' | '\\"' | '\\\\' | '\\0' | '\\a' | '\\b' |
830842
'\\f' | '\\n' | '\\r' | '\\t' | '\\v'
831843
;
832-
844+
833845
fragment Hexadecimal_Escape_Sequence
834846
: '\\x' Hex_Digit Hex_Digit? Hex_Digit? Hex_Digit?
835847
;
@@ -890,11 +902,11 @@ String_Literal
890902
: Regular_String_Literal
891903
| Verbatim_String_Literal
892904
;
893-
905+
894906
fragment Regular_String_Literal
895907
: '"' Regular_String_Literal_Character* '"'
896908
;
897-
909+
898910
fragment Regular_String_Literal_Character
899911
: Single_Regular_String_Literal_Character
900912
| Simple_Escape_Sequence
@@ -910,16 +922,16 @@ fragment Single_Regular_String_Literal_Character
910922
fragment Verbatim_String_Literal
911923
: '@"' Verbatim_String_Literal_Character* '"'
912924
;
913-
925+
914926
fragment Verbatim_String_Literal_Character
915927
: Single_Verbatim_String_Literal_Character
916928
| Quote_Escape_Sequence
917929
;
918-
930+
919931
fragment Single_Verbatim_String_Literal_Character
920932
: ~["] // anything but quotation mark (U+0022)
921933
;
922-
934+
923935
fragment Quote_Escape_Sequence
924936
: '""'
925937
;
@@ -1102,7 +1114,7 @@ Pre-processing directives are not part of the syntactic grammar of C#. However,
11021114
> #endif
11031115
> #if B
11041116
> void H() {}
1105-
> #else
1117+
> #else
11061118
> void I() {}
11071119
> #endif
11081120
> }
@@ -1155,11 +1167,11 @@ Pre-processing expressions can occur in `#if` and `#elif` directives. The operat
11551167
fragment PP_Expression
11561168
: PP_Whitespace? PP_Or_Expression PP_Whitespace?
11571169
;
1158-
1170+
11591171
fragment PP_Or_Expression
11601172
: PP_And_Expression (PP_Whitespace? '||' PP_Whitespace? PP_And_Expression)*
11611173
;
1162-
1174+
11631175
fragment PP_And_Expression
11641176
: PP_Equality_Expression (PP_Whitespace? '&&' PP_Whitespace?
11651177
PP_Equality_Expression)*
@@ -1169,12 +1181,12 @@ fragment PP_Equality_Expression
11691181
: PP_Unary_Expression (PP_Whitespace? ('==' | '!=') PP_Whitespace?
11701182
PP_Unary_Expression)*
11711183
;
1172-
1184+
11731185
fragment PP_Unary_Expression
11741186
: PP_Primary_Expression
11751187
| '!' PP_Whitespace? PP_Unary_Expression
11761188
;
1177-
1189+
11781190
fragment PP_Primary_Expression
11791191
: TRUE
11801192
| FALSE
@@ -1282,15 +1294,15 @@ fragment PP_Conditional
12821294
fragment PP_If_Section
12831295
: 'if' PP_Whitespace PP_Expression
12841296
;
1285-
1297+
12861298
fragment PP_Elif_Section
12871299
: 'elif' PP_Whitespace PP_Expression
12881300
;
1289-
1301+
12901302
fragment PP_Else_Section
12911303
: 'else'
12921304
;
1293-
1305+
12941306
fragment PP_Endif
12951307
: 'endif'
12961308
;
@@ -1488,11 +1500,11 @@ fragment PP_Line_Indicator
14881500
| DEFAULT
14891501
| 'hidden'
14901502
;
1491-
1503+
14921504
fragment PP_Compilation_Unit_Name
14931505
: '"' PP_Compilation_Unit_Name_Character* '"'
14941506
;
1495-
1507+
14961508
fragment PP_Compilation_Unit_Name_Character
14971509
// Any Input_Character except "
14981510
: ~('\u000D' | '\u000A' | '\u0085' | '\u2028' | '\u2029' | '"')

0 commit comments

Comments
 (0)