Skip to content

Commit e90c654

Browse files
committed
Update lexical-structure.md
1 parent 36e721c commit e90c654

File tree

1 file changed

+95
-22
lines changed

1 file changed

+95
-22
lines changed

standard/lexical-structure.md

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -489,34 +489,75 @@ The type of a *boolean_literal* is `bool`.
489489

490490
#### 7.4.5.3 Integer literals
491491

492-
Integer literals are used to write values of types `int`, `uint`, `long`, and `ulong`. Integer literals have two possible forms: decimal and hexadecimal.
492+
Integer literals are used to write values of types `int`, `uint`, `long`, and `ulong`. Integer literals have three possible forms: decimal, hexadecimal, and binary.
493493

494494
```ANTLR
495495
integer_literal
496496
: decimal_integer_literal
497497
| hexadecimal_integer_literal
498+
| binary_integer_literal
498499
;
499500
500501
decimal_integer_literal
501-
: decimal_digit+ integer_type_suffix?
502+
: decimal_digits integer_type_suffix?
502503
;
503504
505+
decimal_digits
506+
: decimal_digit
507+
| decimal_digit decimal_digit_or_underscore* decimal_digit
508+
;
509+
504510
decimal_digit
505511
: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
506512
;
513+
514+
decimal_digit_or_underscore
515+
: decimal_digit
516+
| '_'
517+
;
507518
508519
integer_type_suffix
509520
: 'U' | 'u' | 'L' | 'l' | 'UL' | 'Ul' | 'uL' | 'ul' | 'LU' | 'Lu' | 'lU' | 'lu'
510521
;
511522
512523
hexadecimal_integer_literal
513-
: '0x' hex_digit+ integer_type_suffix?
514-
| '0X' hex_digit+ integer_type_suffix?
524+
: '0x' hex_digits+ integer_type_suffix?
525+
| '0X' hex_digits+ integer_type_suffix?
526+
;
527+
528+
hex_digits
529+
: '_'* hex_digit
530+
| '_'* hex_digit hex_digit_or_underscore* hex_digit
515531
;
516532
517533
hex_digit
518534
: '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
519535
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';
536+
537+
hex_digit_or_underscore
538+
: hex_digit
539+
| '_'
540+
;
541+
542+
binary_integer_literal
543+
: '_'* '0b' binary_digits+ integer_type_suffix?
544+
| '_'* '0B' binary_digits+ integer_type_suffix?
545+
;
546+
547+
binary_digits
548+
: binary_digit
549+
| binary_digit binary_digit_or_underscore* binary_digit
550+
;
551+
552+
binary_digit
553+
: '0'
554+
| '1'
555+
;
556+
557+
binary_digit_or_underscore
558+
: binary_digit
559+
| '_'
560+
;
520561
```
521562

522563
The type of an integer literal is determined as follows:
@@ -528,32 +569,51 @@ The type of an integer literal is determined as follows:
528569

529570
If the value represented by an integer literal is outside the range of the `ulong` type, a compile-time error occurs.
530571

531-
> *Note*: As a matter of style, it is suggested that "`L`" be used instead of "`l`" when writing literals of type `long`, since it is easy to confuse the letter "`l`" with the digit "`1`". *end note*
572+
> *Note*: As a matter of style, it is suggested that "`L`" be used instead of "`l`" when writing literals of type `long`, since it is easy to confuse the letter "`l`" with the digit "`1`". *end note*
532573
533574
To permit the smallest possible `int` and `long` values to be written as integer literals, the following two rules exist:
534575

535-
- When an *integer_literal* representing the value `2147483648` (2³¹) and no *integer_type_suffix* appears as the token immediately following a unary minus operator token ([§12.8.3](expressions.md#1283-unary-minus-operator)), the result (of both tokens) is a constant of type int with the value `−2147483648` (−2³¹</sup>). In all other situations, such an *integer_literal* is of type `uint`.
536-
- When an *integer_literal* representing the value `9223372036854775808` (2⁶³) and no *integer_type_suffix* or the *integer_type_suffix* `L` or `l` appears as the token immediately following a unary minus operator token ([§12.8.3](expressions.md#1283-unary-minus-operator)), the result (of both tokens) is a constant of type `long` with the value `−9223372036854775808` (−2⁶³). In all other situations, such an *integer_literal* is of type `ulong`.
576+
- When an *integer_literal* representing the value `2147483648` (2³¹) and no *integer_type_suffix* appears as the token immediately following a unary minus operator token ([§12.8.3](expressions.md#1283-unary-minus-operator)), the result (of both tokens) is a constant of type `int` with the value `−2147483648` (−2³¹). In all other situations, such an *integer_literal* is of type `uint`.
577+
- When an *integer_literal* representing the value `9223372036854775808` (2⁶³) and no *integer_type_suffix* or the *integer_type_suffix* `L` or `l` appears as the token immediately following a unary minus operator token), the result (of both tokens) is a constant of type `long` with the value `−9223372036854775808` (−2⁶³). In all other situations, such an *integer_literal* is of type `ulong`.
578+
579+
> *Example*:
580+
> ```csharp
581+
> 123 // decimal, int
582+
> 10_543_765Lu // decimal, ulong
583+
> 1__234__567 // decimal, int
584+
>
585+
> 0xFf // hex, int
586+
> 0X1b_a0_44_fEL // hex, long
587+
> 0x1ade_3FE1_29AaUL // hex, ulong
588+
> 0xabc_ // invalid; no trailing _ allowed
589+
>
590+
> 0b101 // binary, int
591+
> 0B1001_1010u // binary, uint
592+
> 0b1111_1111_0000UL // binary, ulong
593+
> 0B__111 // OK; leading _ allowed
594+
> ```
595+
> *end example*
537596
538597
#### 7.4.5.4 Real literals
539598
540599
Real literals are used to write values of types `float`, `double`, and `decimal`.
541600
542601
```ANTLR
543602
real_literal
544-
: decimal_digit+ '.' decimal_digit+ exponent_part? real_type_suffix?
545-
| '.' decimal_digit+ exponent_part? real_type_suffix?
546-
| decimal_digit+ exponent_part real_type_suffix?
547-
| decimal_digit+ real_type_suffix
603+
: decimal_digits '.' decimal_digits exponent_part? real_type_suffix?
604+
| '.' decimal_digits exponent_part? real_type_suffix?
605+
| decimal_digits exponent_part real_type_suffix?
606+
| decimal_digits real_type_suffix
548607
;
549608
550609
exponent_part
551-
: 'e' sign? decimal_digit+
552-
| 'E' sign? decimal_digit+
610+
: 'e' sign? decimal_digits
611+
| 'E' sign? decimal_digits
553612
;
554613
555614
sign
556-
: '+' | '-'
615+
: '+'
616+
| '-'
557617
;
558618
559619
real_type_suffix
@@ -563,14 +623,14 @@ real_type_suffix
563623
564624
If no *real_type_suffix* is specified, the type of the *real_literal* is `double`. Otherwise, the *real_type_suffix* determines the type of the real literal, as follows:
565625

566-
- A real literal suffixed by `F` or `f` is of type `float`.
567-
> *Example*: The literals `1f, 1.5f, 1e10f`, and `123.456F` are all of type `float`. *end example*
568-
- A real literal suffixed by `D` or `d` is of type `double`.
569-
> *Example*: The literals `1d, 1.5d, 1e10d`, and `123.456D` are all of type `double`. *end example*
570-
- A real literal suffixed by `M` or `m` is of type `decimal`.
571-
> *Example*: The literals `1m, 1.5m, 1e10m`, and `123.456M` are all of type `decimal`. *end example*
572-
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 ([§9.3.8](types.md#938-the-decimal-type)). Any scale apparent in the literal is preserved unless the value is rounded.
573-
> *Note*: Hence, the literal `2.900m` will be parsed to form the `decimal` with sign `0`, coefficient `2900`, and scale `3`. *end note*
626+
- A real literal suffixed by `F` or `f` is of type `float`.
627+
> *Example*: The literals `1f, 1.5f, 1e10f`, and `123.456F` are all of type `float`. *end example*
628+
- A real literal suffixed by `D` or `d` is of type `double`.
629+
> *Example*: The literals `1d, 1.5d, 1e10d`, and `123.456D` are all of type `double`. *end example*
630+
- A real literal suffixed by `M` or `m` is of type `decimal`.
631+
> *Example*: The literals `1m, 1.5m, 1e10m`, and `123.456M` are all of type `decimal`. *end example*
632+
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 ([§9.3.8](types.md#938-the-decimal-type)). Any scale apparent in the literal is preserved unless the value is rounded.
633+
> *Note*: Hence, the literal `2.900m` will be parsed to form the `decimal` with sign `0`, coefficient `2900`, and scale `3`. *end note*
574634
575635
If the magnitude of the specified literal is too large to be represented in the indicated type, a compile-time error occurs.
576636

@@ -580,6 +640,19 @@ The value of a real literal of type `float` or `double` is determined by using t
580640

581641
> *Note*: In a real literal, decimal digits are always required after the decimal point. For example, `1.3F` is a real literal but `1.F` is not. *end note*
582642
643+
> *Example*:
644+
> ```csharp
645+
> 1.234_567 // double
646+
> .3e5f // float
647+
> 2_345E-2_0 // double
648+
> 15D // double
649+
> 19.73M // decimal
650+
> 1.F // invalid; ill-formed (parsed as "1." and "F")
651+
> 1.234_ // invalid; no trailing _ allowed in fraction
652+
> .3e5_F // invalid; no trailing _ allowed in exponent
653+
> ```
654+
> *end example*
655+
583656
#### 7.4.5.5 Character literals
584657
585658
A character literal represents a single character, and consists of a character in quotes, as in `'a'`.

0 commit comments

Comments
 (0)