module /** */ import { AsciiCodes } from "char-info/ascii" ; import { NumericHelpers } from "./numeric-helpers" ; import { ResultKind } from "../result" ; import { ParsingState } from "../state" ; import defaults from "lodash/defaults" ; import { ParjserBase } from "../parser" ; import { Parjser } from "../parjser" ; /**
 * A set of options for parsing floating point numbers.
 */ export interface FloatOptions { allowSign : boolean ; allowImplicitZero : boolean ; allowFloatingPoint : boolean ; allowExponent : boolean ; } const defaultFloatOptions = { allowExponent : true , allowSign : true , allowImplicitZero : true , allowFloatingPoint : true } ; const msgOneOrMoreDigits = "one or more digits" ; const msgExponentSign = "exponent sign (+ or -)" ; param options export function float ( options = defaultFloatOptions ) { options = defaults ( options , defaultFloatOptions ) ; return new class Float extends ParjserBase { type = "float" ; expecting = "expecting a floating-point number" ; _apply ( ps ) { let { allowSign , allowFloatingPoint , allowImplicitZero , allowExponent } = options ; let { position , input } = ps ; if ( position >= input . length ) { ps . kind = ResultKind . SoftFail ; return ; } let initPos = position ; let sign = 1 ; let hasSign = false , hasWhole = false , hasFraction = false ; if ( allowSign ) { sign = NumericHelpers . parseSign ( ps ) ; if ( sign === 0 ) { sign = 1 ; } else { hasSign = true ; } } let prevPos = ps . position ; NumericHelpers . parseDigitsInBase ( ps , 10 ) ; hasWhole = ps . position !== prevPos ; let nextChar = input . charCodeAt ( ps . position ) ; prevPos = ps . position ; if ( ! allowImplicitZero && ! hasWhole ) { ps . kind = hasSign ? ResultKind . HardFail : ResultKind . SoftFail ; ps . reason = msgOneOrMoreDigits ; return ; } floatingParse : { if ( allowFloatingPoint && nextChar === AsciiCodes . decimalPoint ) { ps . position ++ ; let prevFractionalPos = ps . position ; NumericHelpers . parseDigitsInBase ( ps , 10 ) ; hasFraction = prevFractionalPos !== ps . position ; if ( ! allowImplicitZero && ! hasFraction ) { break floatingParse ; } nextChar = input . charCodeAt ( ps . position ) ; prevPos = ps . position ; } if ( ! hasWhole && ! hasFraction ) { ps . kind = hasSign ? ResultKind . HardFail : ResultKind . SoftFail ; ps . reason = msgOneOrMoreDigits ; return ; } if ( allowExponent && ( nextChar === AsciiCodes . e || nextChar === AsciiCodes . E ) ) { ps . position ++ ; let expSign = NumericHelpers . parseSign ( ps ) ; if ( expSign === 0 ) { ps . kind = ResultKind . HardFail ; ps . reason = msgExponentSign ; return ; } let prevFractionalPos = ps . position ; NumericHelpers . parseDigitsInBase ( ps , 10 ) ; if ( ps . position === prevFractionalPos ) { ps . kind = ResultKind . HardFail ; ps . reason = msgOneOrMoreDigits ; return ; } } } ps . kind = ResultKind . Ok ; ps . value = parseFloat ( input . substring ( initPos , ps . position ) ) ; } } ( ) ; }