Skip to content

Commit d8a8c3a

Browse files
committed
Publish Terminals.genericReal and add optionally allow a leading sign.
1 parent 6fb3fe5 commit d8a8c3a

File tree

1 file changed

+40
-21
lines changed

1 file changed

+40
-21
lines changed

Diff for: src/Farkle/Builder/Terminals.fs

+40-21
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,31 @@ open System.Text
2727
// A string prefixed by four spaces will be replaced in the future with
2828
// a ReadOnlySpan of characters.
2929

30+
[<CompiledName("UnsignedIntRegex")>]
3031
/// A `Regex` that recognizes a series of decimal digits.
3132
/// Leading zeros are accepted.
3233
// Seriously though, why not? Looking at you, JSON!
33-
let unsignedRegex = Number |> chars |> atLeast 1
34+
let unsignedIntRegex = Number |> chars |> atLeast 1
3435

35-
[<CompiledName("FSharpOnlyGenericUnsigned"); RequiresExplicitTypeArguments>]
36+
[<CompiledName("FSharpOnlyGenericUnsigned"); RequiresExplicitTypeArguments; NoDynamicInvocation>]
3637
/// Creates a designtimeFarkle that parses an unsigned decimal integer
3738
/// into the desired number type. No bounds checking is performed.
3839
/// Using this function from a language other than F# will throw an exception.
3940
let inline genericUnsigned< ^TInt when ^TInt: (static member Parse: string * NumberStyles * IFormatProvider -> ^TInt)> name =
4041
terminal name
4142
(T (fun _ x ->
4243
(^TInt: (static member Parse: string * NumberStyles * IFormatProvider -> ^TInt)
43-
(x.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo))))
44-
unsignedRegex
44+
(x.ToString(), NumberStyles.None, NumberFormatInfo.InvariantInfo))))
45+
unsignedIntRegex
4546

47+
[<CompiledName("SignedIntRegex")>]
4648
/// A `Regex` that recognizes a series of decimal digits
4749
/// that might be prefixed with a minus sign "-".
4850
/// Leading zeros are accepted.
49-
let signedRegex = (optional <| char '-') <&> unsignedRegex
51+
let signedIntRegex = (optional <| char '-') <&> unsignedIntRegex
5052

51-
[<CompiledName("FSharpOnlyGenericSigned"); RequiresExplicitTypeArguments>]
52-
/// Creates a designtimeFarkle that parses a signed decimal integer
53+
[<CompiledName("FSharpOnlyGenericSigned"); RequiresExplicitTypeArguments; NoDynamicInvocation>]
54+
/// Creates a designtime Farkle that parses a signed decimal integer
5355
/// into the desired number type. No bounds checking is performed.
5456
/// The type parameter must support the unary negation operator.
5557
/// Using this function from a language other than F# will throw an exception.
@@ -58,7 +60,7 @@ let inline genericSigned< ^TInt when ^TInt: (static member Parse: string * Nu
5860
(T (fun _ x ->
5961
(^TInt: (static member Parse: string * NumberStyles * IFormatProvider -> ^TInt)
6062
(x.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo))))
61-
signedRegex
63+
signedIntRegex
6264

6365
/// Creates a designtime Farkle that parses and returns a
6466
/// signed 32-bit signed integer. No bounds checking is performed.
@@ -80,12 +82,17 @@ let uint32 name = genericUnsigned<uint32> name
8082
/// signed 64-bit unsigned integer. No bounds checking is performed.
8183
let uint64 name = genericUnsigned<uint64> name
8284

83-
let private realRegex =
85+
[<CompiledName("UnsignedRealRegex")>]
86+
/// A `Regex` that recognizes an unsigned real number.
87+
/// The number is expected to be written in scientific
88+
/// notation, with the decimal point symbol being the dot.
89+
/// Numbers before or after the dot are optional, but they
90+
/// must exist in at least one of the two places.
91+
let unsignedRealRegex =
8492
let numberStar = chars Number |> star
8593
let atLeastOneNumber = chars Number <&> numberStar
8694
let dotOptional = char '.' |> optional
8795
concat [
88-
optional <| char '-'
8996
choice [
9097
// There has to be at least one digit
9198
// either before or after the dot.
@@ -98,37 +105,49 @@ let private realRegex =
98105
|> optional
99106
]
100107

101-
[<RequiresExplicitTypeArguments>]
102-
// We have exhausted all the cases, so let's make it private.
103-
let inline private genericReal< ^TReal when ^TReal: (static member Parse: string * NumberStyles * IFormatProvider -> ^TReal)> name =
108+
[<CompiledName("SignedRealRegex")>]
109+
/// Like `unsignedRealRegex`, but with an optional
110+
/// sign in the beginning being allowed.
111+
let signedRealRegex = (optional <| char '-') <&> unsignedRealRegex
112+
113+
[<CompiledName("FSharpOnlyGenericReal"); RequiresExplicitTypeArguments; NoDynamicInvocation>]
114+
/// Creates a designtime Farkle that parses a real number
115+
/// into the desired number type. No bounds checking is performed.
116+
/// Using this function from a language other than F# will throw an exception.
117+
let inline genericReal< ^TReal when ^TReal: (static member Parse: string * NumberStyles * IFormatProvider -> ^TReal)> allowSign name =
118+
let regex =
119+
if allowSign then
120+
signedRealRegex
121+
else
122+
unsignedRealRegex
104123
terminal name
105124
(T (fun _ x ->
106125
(^TReal: (static member Parse: string * NumberStyles * IFormatProvider -> ^TReal)
107-
(x.ToString(), NumberStyles.AllowExponent ||| NumberStyles.Float, NumberFormatInfo.InvariantInfo))))
108-
realRegex
126+
(x.ToString(), NumberStyles.Float, NumberFormatInfo.InvariantInfo))))
127+
regex
109128

110129
[<CompiledName("Single")>]
111130
/// Creates a designtime Farkle that parses and returns
112-
/// a single-precision floating-point number. The number
131+
/// a signed single-precision floating-point number. The number
113132
/// is expected to be written in scientific notation, with
114133
/// the decimal point symbol being the dot. Special values
115134
/// such as NaN or infinity are not recognized.
116-
let float32 name = genericReal<float32> name
135+
let float32 name = genericReal<float32> true name
117136

118137
[<CompiledName("Double")>]
119138
/// Creates a designtime Farkle that parses and returns
120-
/// a single-precision floating-point number. The number
139+
/// a signed double-precision floating-point number. The number
121140
/// is expected to be written in scientific notation, with
122141
/// the decimal point symbol being the dot. Special values
123142
/// such as NaN or infinity are not recognized.
124-
let float name = genericReal<float> name
143+
let float name = genericReal<float> true name
125144

126145
[<CompiledName("Decimal")>]
127146
/// Creates a designtime Farkle that parses and returns
128-
/// a single-precision floating-point number. The number
147+
/// a signed decimal floating-point number. The number
129148
/// is expected to be written in scientific notation, with
130149
/// the decimal point symbol being the dot.
131-
let decimal name = genericReal<decimal> name
150+
let decimal name = genericReal<decimal> true name
132151

133152
let private stringTransformer = T (fun _ span ->
134153
let span = span.Slice(1, span.Length - 2)

0 commit comments

Comments
 (0)