@@ -30,20 +30,39 @@ open FSharp.Compiler.ParseHelpers
3030open FSharp.Compiler.Parser
3131open FSharp.Compiler.SyntaxTree
3232
33+ module Ranges =
34+ /// Whether valid as signed int8 when a minus sign is prepended, compares true to 0x80
35+ let isInt8BadMax x = 1 <<< 7 = x
36+
37+ /// Whether valid as signed int16 when a minus sign is prepended, compares true to 0x8000
38+ let isInt16BadMax x = 1 <<< 15 = x
39+
40+ /// Whether valid as signed int32 when a minus sign is prepended, compares as string against "2147483648".
41+ let isInt32BadMax = let max = string(1UL <<< 31) in fun s -> max = s
42+
43+ /// Whether valid as signed int64 when a minus sign is prepended, compares as string against "9223372036854775808".
44+ let isInt64BadMax = let max = string(1UL <<< 63) in fun s -> max = s
45+
46+ /// Get string from lexbuf
3347let lexeme (lexbuf : UnicodeLexing.Lexbuf) = UnicodeLexing.Lexbuf.LexemeString lexbuf
3448
49+ /// Trim n chars from both side of a string
3550let trimBoth (s:string) n m = s.Substring(n, s.Length - (n+m))
3651
52+ /// Trim n chars from both sides of lexbuf, return string
3753let lexemeTrimBoth lexbuf n m = trimBoth (lexeme lexbuf) n m
3854
55+ /// Trim n chars from the right of lexbuf, return string
3956let lexemeTrimRight lexbuf n = lexemeTrimBoth lexbuf 0 n
4057
58+ /// Trim n chars from the left of lexbuf, return string
4159let lexemeTrimLeft lexbuf n = lexemeTrimBoth lexbuf n 0
4260
61+ /// Throw a lexing error with a message
4362let fail args (lexbuf:UnicodeLexing.Lexbuf) msg dflt =
4463 let m = lexbuf.LexemeRange
4564 args.errorLogger.ErrorR(Error(msg,m))
46- dflt
65+ dflt
4766
4867//--------------------------
4968// Integer parsing
@@ -313,88 +332,88 @@ rule token args skip = parse
313332
314333 | int8
315334 { let n = lexemeTrimRightToInt32 args lexbuf 1
316- if n > 0x80 || n < -0x80 then fail args lexbuf (FSComp.SR.lexOutsideEightBitSigned()) (INT8(0y,false))
317335 // Allow <max_int+1> to parse as min_int. Allowed only because we parse '-' as an operator.
318- else if n = 0x80 then INT8(sbyte(-0x80), true (* 'true' = 'bad'*) )
319- else INT8(sbyte n,false) }
336+ if Ranges.isInt8BadMax n then INT8(SByte.MinValue, true (* 'true' = 'bad'*) )
337+ else if n > int SByte.MaxValue || n < int SByte.MinValue then fail args lexbuf (FSComp.SR.lexOutsideEightBitSigned()) (INT8(0y, false))
338+ else INT8(sbyte n, false) }
320339
321340 | xint8
322341 { let n = lexemeTrimRightToInt32 args lexbuf 1
323- if n > 0xFF || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideEightBitSignedHex()) (INT8(0y,false))
324- else INT8(sbyte(byte(n)),false) }
342+ if n > int Byte.MaxValue || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideEightBitSignedHex()) (INT8(0y, false))
343+ else INT8(sbyte(byte(n)), false) }
325344
326345 | uint8
327346 { let n = lexemeTrimRightToInt32 args lexbuf 2
328- if n > 0xFF || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideEightBitUnsigned()) (UINT8(0uy))
329- else UINT8(byte n) }
347+ if n > int Byte.MaxValue || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideEightBitUnsigned()) (UINT8(0uy))
348+ else UINT8(byte n) }
330349
331350 | int16
332351 { let n = lexemeTrimRightToInt32 args lexbuf 1
333- if n > 0x8000 || n < -0x8000 then fail args lexbuf (FSComp.SR.lexOutsideSixteenBitSigned()) (INT16(0s,false))
334352 // Allow <max_int+1> to parse as min_int. Allowed only because we parse '-' as an operator.
335- else if n = 0x8000 then INT16(-0x8000s,true)
336- else INT16(int16 n,false) }
353+ if Ranges.isInt16BadMax n then INT16(Int16.MinValue, true (* 'true' = 'bad'*) )
354+ else if n > int Int16.MaxValue || n < int Int16.MinValue then fail args lexbuf (FSComp.SR.lexOutsideSixteenBitSigned()) (INT16(0s, false))
355+ else INT16(int16 n, false) }
337356
338357 | xint16
339358 { let n = lexemeTrimRightToInt32 args lexbuf 1
340- if n > 0xFFFF || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideSixteenBitSigned()) (INT16(0s,false))
341- else INT16(int16(uint16(n)),false) }
359+ if n > int UInt16.MaxValue || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideSixteenBitSigned()) (INT16(0s,false))
360+ else INT16(int16(uint16(n)), false) }
342361
343362 | uint16
344363 { let n = lexemeTrimRightToInt32 args lexbuf 2
345- if n > 0xFFFF || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideSixteenBitUnsigned()) (UINT16(0us))
364+ if n > int UInt16.MaxValue || n < 0 then fail args lexbuf (FSComp.SR.lexOutsideSixteenBitUnsigned()) (UINT16(0us))
346365 else UINT16(uint16 n) }
347366
348367 | int '.' '.'
349368 { let s = removeUnderscores (lexemeTrimRight lexbuf 2)
350369 // Allow <max_int+1> to parse as min_int. Allowed only because we parse '-' as an operator.
351- if s = "2147483648" then INT32_DOT_DOT(-2147483648, true) else
370+ if Ranges.isInt32BadMax s then INT32_DOT_DOT(Int32.MinValue, true (* 'true' = 'bad'*) ) else
352371 let n = try int32 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitSigned()) 0
353- INT32_DOT_DOT(n,false)
372+ INT32_DOT_DOT(n, false)
354373 }
355374
356375 | xint
357376 | int
358377 { let s = removeUnderscores (lexeme lexbuf)
359378 // Allow <max_int+1> to parse as min_int. Allowed only because we parse '-' as an operator.
360- if s = "2147483648" then INT32(-2147483648, true) else
379+ if Ranges.isInt32BadMax s then INT32(Int32.MinValue, true (* 'true' = 'bad'*) ) else
361380 let n =
362381 try int32 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitSigned()) 0
363- INT32(n,false)
382+ INT32(n, false)
364383 }
365384
366385 | xint32
367386 | int32
368387 { let s = removeUnderscores (lexemeTrimRight lexbuf 1)
369388 // Allow <max_int+1> to parse as min_int. Allowed only because we parse '-' as an operator.
370- if s = "2147483648" then INT32(-2147483648, true) else
371- let n =
389+ if Ranges.isInt32BadMax s then INT32(Int32.MinValue, true (* 'true' = 'bad'*) ) else
390+ let n =
372391 try int32 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitSigned()) 0
373- INT32(n,false)
392+ INT32(n, false)
374393 }
375394
376395 | uint32
377396 {
378397 let s = removeUnderscores (lexemeTrimRight lexbuf 1)
379398 let n =
380399 try int64 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitUnsigned()) 0L
381- if n > 0xFFFFFFFFL || n < 0L then fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitUnsigned()) (UINT32(0u)) else
400+ if n > int64 UInt32.MaxValue || n < 0L then fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitUnsigned()) (UINT32(0u)) else
382401 UINT32(uint32 (uint64 n)) }
383402
384403 | uint32l
385404 {
386405 let s = removeUnderscores (lexemeTrimRight lexbuf 2)
387406 let n =
388407 try int64 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitUnsigned()) 0L
389- if n > 0xFFFFFFFFL || n < 0L then fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitUnsigned()) (UINT32(0u)) else
408+ if n > int64 UInt32.MaxValue || n < 0L then fail args lexbuf (FSComp.SR.lexOutsideThirtyTwoBitUnsigned()) (UINT32(0u)) else
390409 UINT32(uint32 (uint64 n)) }
391410
392411 | int64
393412 { let s = removeUnderscores (lexemeTrimRight lexbuf 1)
394413 // Allow <max_int+1> to parse as min_int. Stupid but allowed because we parse '-' as an operator.
395- if s = "9223372036854775808" then INT64(-9223372036854775808L, true) else
414+ if Ranges.isInt64BadMax s then INT64(Int64.MinValue, true (* 'true' = 'bad'*) ) else
396415 let n =
397- try int64 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideSixtyFourBitSigned()) 0L
416+ try int64 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideSixtyFourBitSigned()) 0L
398417 INT64(n,false)
399418 }
400419
@@ -405,9 +424,13 @@ rule token args skip = parse
405424 UINT64(n) }
406425
407426 | nativeint
408- { try
409- NATIVEINT(int64 (removeUnderscores (lexemeTrimRight lexbuf 1)))
410- with _ -> fail args lexbuf (FSComp.SR.lexOutsideNativeSigned()) (NATIVEINT(0L)) }
427+ { let s = removeUnderscores (lexemeTrimRight lexbuf 1)
428+ // Allow <max_nativeint+1> to parse as min_nativeint. Stupid but allowed because we parse '-' as an operator.
429+ if Ranges.isInt64BadMax s then NATIVEINT(Int64.MinValue, true) else
430+ let n =
431+ try int64 s with _ -> fail args lexbuf (FSComp.SR.lexOutsideNativeSigned()) 0L
432+ NATIVEINT(n,false)
433+ }
411434
412435 | unativeint
413436 { try
0 commit comments