@@ -80,25 +80,22 @@ internal struct Parser {
8080 }
8181 try consume ( )
8282 let value : UnsignedType
83+ let makeError = { [ lexer] in
84+ WatParserError ( " invalid literal \( token. text ( from: lexer) ) " , location: token. location ( in: lexer) )
85+ }
8386 switch pattern {
8487 case . hexPattern( let pattern) :
85- guard let index = UnsignedType ( pattern, radix: 16 ) else {
86- throw WatParserError ( " invalid index \( pattern) " , location: token. location ( in: lexer) )
87- }
88+ guard let index = UnsignedType ( pattern, radix: 16 ) else { throw makeError ( ) }
8889 value = index
8990 case . decimalPattern( let pattern) :
90- guard let index = UnsignedType ( pattern) else {
91- throw WatParserError ( " invalid index \( pattern) " , location: token. location ( in: lexer) )
92- }
91+ guard let index = UnsignedType ( pattern) else { throw makeError ( ) }
9392 value = index
9493 }
9594 switch sign {
9695 case . plus, nil : return fromBitPattern ( value)
9796 case . minus:
9897 let casted = fromBitPattern ( ~ value &+ 1 )
99- guard casted <= 0 else {
100- throw WatParserError ( " invalid literal \( token. text ( from: lexer) ) " , location: token. location ( in: lexer) )
101- }
98+ guard casted <= 0 else { throw makeError ( ) }
10299 return casted
103100 }
104101 }
@@ -185,7 +182,7 @@ internal struct Parser {
185182 }
186183
187184 mutating func expectFloatingPoint< F: BinaryFloatingPoint & LosslessStringConvertible , BitPattern: FixedWidthInteger > (
188- _: F . Type , toBitPattern: ( F ) -> BitPattern ,
185+ _: F . Type , toBitPattern: ( F ) -> BitPattern , isNaN : ( BitPattern ) -> Bool ,
189186 buildBitPattern: (
190187 _ sign: FloatingPointSign ,
191188 _ exponentBitPattern: UInt ,
@@ -198,44 +195,43 @@ internal struct Parser {
198195 return 1 &<< UInt ( F . exponentBitCount) - 1
199196 }
200197
198+ let makeError = { [ lexer] in
199+ WatParserError ( " invalid float literal \( token. text ( from: lexer) ) " , location: token. location ( in: lexer) )
200+ }
201+ let parse = { ( pattern: String ) throws -> F in
202+ // Swift's Float{32,64} initializer returns +/- infinity for too large/too small values.
203+ // We know that the given pattern will not be expected to be parsed as infinity,
204+ // so we can check if the parsing succeeded by checking if the returned value is infinite.
205+ guard let value = F ( pattern) , !value. isInfinite else { throw makeError ( ) }
206+ return value
207+ }
201208 switch token. kind {
202209 case let . float( sign, pattern) :
203210 let float : F
204211 switch pattern {
205212 case . decimalPattern( let pattern) :
206- guard let value = F ( pattern) else {
207- throw WatParserError ( " invalid float \( pattern) " , location: token. location ( in: lexer) )
208- }
209- float = value
213+ float = try parse ( pattern)
210214 case . hexPattern( let pattern) :
211- guard let value = F ( " 0x " + pattern) else {
212- throw WatParserError ( " invalid float \( pattern) " , location: token. location ( in: lexer) )
213- }
214- float = value
215+ float = try parse ( " 0x " + pattern)
215216 case . inf:
216217 float = . infinity
217218 case . nan( hexPattern: nil ) :
218219 float = . nan
219220 case . nan( let hexPattern? ) :
220- guard let bitPattern = BitPattern ( hexPattern, radix: 16 ) else {
221- throw WatParserError ( " invalid float \( hexPattern) " , location: token. location ( in: lexer) )
222- }
223- return buildBitPattern ( sign ?? . plus, infinityExponent, UInt ( bitPattern) )
221+ guard let significandBitPattern = BitPattern ( hexPattern, radix: 16 ) else { throw makeError ( ) }
222+ let bitPattern = buildBitPattern ( sign ?? . plus, infinityExponent, UInt ( significandBitPattern) )
223+ // Ensure that the given bit pattern is a NaN.
224+ guard isNaN ( bitPattern) else { throw makeError ( ) }
225+ return bitPattern
224226 }
225227 return toBitPattern ( sign == . minus ? - float : float)
226228 case let . integer( sign, pattern) :
227229 let float : F
228230 switch pattern {
229231 case . hexPattern( let pattern) :
230- guard let value = F ( " 0x " + pattern) else {
231- throw WatParserError ( " invalid float \( pattern) " , location: token. location ( in: lexer) )
232- }
233- float = value
232+ float = try parse ( " 0x " + pattern)
234233 case . decimalPattern( let pattern) :
235- guard let value = F ( pattern) else {
236- throw WatParserError ( " invalid float \( pattern) " , location: token. location ( in: lexer) )
237- }
238- float = value
234+ float = try parse ( pattern)
239235 }
240236 return toBitPattern ( sign == . minus ? - float : float)
241237 default :
@@ -246,6 +242,7 @@ internal struct Parser {
246242 mutating func expectFloat32( ) throws -> IEEE754 . Float32 {
247243 let bitPattern = try expectFloatingPoint (
248244 Float32 . self, toBitPattern: \. bitPattern,
245+ isNaN: { Float32 ( bitPattern: $0) . isNaN } ,
249246 buildBitPattern: {
250247 UInt32 (
251248 ( $0 == . minus ? 1 : 0 ) << ( Float32 . exponentBitCount + Float32. significandBitCount)
@@ -259,6 +256,7 @@ internal struct Parser {
259256 mutating func expectFloat64( ) throws -> IEEE754 . Float64 {
260257 let bitPattern = try expectFloatingPoint (
261258 Float64 . self, toBitPattern: \. bitPattern,
259+ isNaN: { Float64 ( bitPattern: $0) . isNaN } ,
262260 buildBitPattern: {
263261 UInt64 (
264262 ( $0 == . minus ? 1 : 0 ) << ( Float64 . exponentBitCount + Float64. significandBitCount)
0 commit comments