Skip to content

Commit bfc92fb

Browse files
authored
Merge pull request #1243 from AviAvni/underscore-literals
RFC FS-1005 - Underscore literals @AviAvni Thank you for taking care of this
2 parents a58efbf + 57a2fe9 commit bfc92fb

File tree

3 files changed

+80
-12
lines changed

3 files changed

+80
-12
lines changed

src/fsharp/FSharp.Core/prim-types.fs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,10 +2504,15 @@ namespace Microsoft.FSharp.Core
25042504
let rec parse n acc = if n < l then parse (n+1) (acc *.. 2UL +.. (match s.Chars(n) with '0' -> 0UL | '1' -> 1UL | _ -> formatError())) else acc in
25052505
parse p 0UL
25062506

2507+
let inline removeUnderscores (s:string) =
2508+
match s with
2509+
| null -> null
2510+
| s -> s.Replace("_", "")
2511+
25072512
let ParseUInt32 (s:string) =
25082513
if System.Object.ReferenceEquals(s,null) then
25092514
raise( new System.ArgumentNullException("s") )
2510-
let s = s.Trim()
2515+
let s = removeUnderscores (s.Trim())
25112516
let l = s.Length
25122517
let mutable p = 0
25132518
let specifier = get0OXB s &p l
@@ -2524,7 +2529,7 @@ namespace Microsoft.FSharp.Core
25242529
let ParseInt32 (s:string) =
25252530
if System.Object.ReferenceEquals(s,null) then
25262531
raise( new System.ArgumentNullException("s") )
2527-
let s = s.Trim()
2532+
let s = removeUnderscores (s.Trim())
25282533
let l = s.Length
25292534
let mutable p = 0
25302535
let sign = getSign32 s &p l
@@ -2543,7 +2548,7 @@ namespace Microsoft.FSharp.Core
25432548
let ParseInt64 (s:string) =
25442549
if System.Object.ReferenceEquals(s,null) then
25452550
raise( new System.ArgumentNullException("s") )
2546-
let s = s.Trim()
2551+
let s = removeUnderscores (s.Trim())
25472552
let l = s.Length
25482553
let mutable p = 0
25492554
let sign = getSign64 s &p l
@@ -2562,7 +2567,7 @@ namespace Microsoft.FSharp.Core
25622567
let ParseUInt64 (s:string) : uint64 =
25632568
if System.Object.ReferenceEquals(s,null) then
25642569
raise( new System.ArgumentNullException("s") )
2565-
let s = s.Trim()
2570+
let s = removeUnderscores (s.Trim())
25662571
let l = s.Length
25672572
let mutable p = 0
25682573
let specifier = get0OXB s &p l
@@ -4144,8 +4149,8 @@ namespace Microsoft.FSharp.Core
41444149
let inline ParseUInt16 (s:string) = (# "conv.ovf.u2" (ParseUInt32 s) : uint16 #)
41454150
let inline ParseIntPtr (s:string) = (# "conv.ovf.i" (ParseInt64 s) : nativeint #)
41464151
let inline ParseUIntPtr (s:string) = (# "conv.ovf.u" (ParseInt64 s) : unativeint #)
4147-
let inline ParseDouble (s:string) = Double.Parse(s,NumberStyles.Float, CultureInfo.InvariantCulture)
4148-
let inline ParseSingle (s:string) = Single.Parse(s,NumberStyles.Float, CultureInfo.InvariantCulture)
4152+
let inline ParseDouble (s:string) = Double.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture)
4153+
let inline ParseSingle (s:string) = Single.Parse(removeUnderscores s,NumberStyles.Float, CultureInfo.InvariantCulture)
41494154

41504155

41514156
[<NoDynamicInvocation>]

src/fsharp/lex.fsl

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,13 @@ let parseOctalUInt64 (s:string) p l =
8282
let rec parse n acc = if n < l then parse (n+1) (acc * 8UL + (let c = s.[n] in if c >= '0' && c <= '7' then Convert.ToUInt64 c - Convert.ToUInt64 '0' else formatError())) else acc
8383
parse p 0UL
8484

85+
let removeUnderscores (s:string) =
86+
match s with
87+
| null -> null
88+
| s -> s.Replace("_", "")
89+
8590
let parseInt32 (s:string) =
91+
let s = removeUnderscores s
8692
let l = s.Length
8793
let mutable p = 0
8894
let sign = getSign32 s &p l
@@ -175,11 +181,12 @@ let anychar = [^'\n''\r']
175181
let anystring = anychar*
176182
let op_char = '!'|'$'|'%'|'&'|'*'|'+'|'-'|'.'|'/'|'<'|'='|'>'|'?'|'@'|'^'|'|'|'~'|':'
177183
let ignored_op_char = '.' | '$' | '?'
184+
let separator = '_'
178185
let xinteger =
179-
( '0' ('x'| 'X') hex +
180-
| '0' ('o'| 'O') (['0'-'7']) +
181-
| '0' ('b'| 'B') (['0'-'1']) + )
182-
let integer = digit+
186+
( '0' ('x'| 'X') hex ((hex | separator)* hex)?
187+
| '0' ('o'| 'O') (['0'-'7']) (((['0'-'7']) | separator)* (['0'-'7']))?
188+
| '0' ('b'| 'B') (['0'-'1']) (((['0'-'1']) | separator)* (['0'-'1']))?)
189+
let integer = digit ((digit | separator)* digit)?
183190
let int8 = integer 'y'
184191
let uint8 = (xinteger | integer) 'u' 'y'
185192
let int16 = integer 's'
@@ -196,8 +203,8 @@ let xint8 = xinteger 'y'
196203
let xint16 = xinteger 's'
197204
let xint = xinteger
198205
let xint32 = xinteger 'l'
199-
let floatp = digit+ '.' digit*
200-
let floate = digit+ ('.' digit* )? ('e'| 'E') ['+' '-']? digit+
206+
let floatp = digit ((digit | separator)* digit)? '.' (digit (digit | separator)*)?
207+
let floate = digit ((digit | separator)* digit)? ('.' (digit (digit | separator)*)? )? ('e'| 'E') ['+' '-']? digit (digit | separator)*
201208
let float = floatp | floate
202209
let bignum = integer ('I' | 'N' | 'Z' | 'Q' | 'R' | 'G')
203210
let ieee64 = float

tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/BasicConstants.fs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,60 @@ let boolConst2 = false
4040

4141
let unitConst = ()
4242

43+
let creditCardNumber = 1234_5678_9012_3456L
44+
if creditCardNumber <> 1234567890123456L then
45+
failwith "Wrong parsing"
46+
47+
let socialSecurityNumber = 999_99_9999L
48+
if socialSecurityNumber <> 999999999L then
49+
failwith "Wrong parsing"
50+
51+
let pi = 3.14_15F
52+
if pi <> 3.1415F then
53+
failwith "Wrong parsing"
54+
55+
let hexBytes = 0xFF_EC_DE_5E
56+
if hexBytes <> 0xFFECDE5E then
57+
failwith "Wrong parsing"
58+
59+
let hexWords = 0xCAFE_BABE
60+
if hexWords <> 0xCAFEBABE then
61+
failwith "Wrong parsing"
62+
63+
let maxLong = 0x7fff_ffff_ffff_ffffL
64+
if maxLong <> 0x7fffffffffffffffL then
65+
failwith "Wrong parsing"
66+
67+
let nybbles = 0b0010_0101
68+
if nybbles <> 0b00100101 then
69+
failwith "Wrong parsing"
70+
71+
let bytes = 0b11010010_01101001_10010100_10010010
72+
if bytes <> 0b11010010011010011001010010010010 then
73+
failwith "Wrong parsing"
74+
75+
let x2 = 5_2
76+
if x2 <> 52 then
77+
failwith "Wrong parsing"
78+
79+
let x4 = 5_______2
80+
if x4 <> 52 then
81+
failwith "Wrong parsing"
82+
83+
let x7 = 0x5_2
84+
if x7 <> 0x52 then
85+
failwith "Wrong parsing"
86+
87+
let x9 = 0_52
88+
if x9 <> 052 then
89+
failwith "Wrong parsing"
90+
91+
let x10 = 05_2
92+
if x10 <> 052 then
93+
failwith "Wrong parsing"
94+
95+
let x14 = 0o5_2
96+
if x14 <> 0o52 then
97+
failwith "Wrong parsing"
98+
4399
exit 0

0 commit comments

Comments
 (0)