pub(super) fn read_number(
        &mut self,
        starts_with_dot: bool,
    ) -> LexResult<Either<f64, BigIntValue>> {
        debug_assert!(self.cur().is_some());
        if starts_with_dot {
            debug_assert_eq!(
                self.cur(),
                Some('.'),
                "read_number(starts_with_dot = true) expects current char to be '.'"
            );
        }
        let start = self.cur_pos();

        let starts_with_zero = self.cur().unwrap() == '0';
        let mut raw_val = String::new();

        let val = if starts_with_dot {
            // first char is '.'
            0f64
        } else {
            // Use read_number_no_dot to support long numbers.
            let (val, s, not_octal) = self.read_number_no_dot_as_str(10)?;
            if self.input.cur() == Some('n') {
                self.input.bump();
                return Ok(Either::Right(s));
            }
            write!(raw_val, "{}", s).unwrap();
            if starts_with_zero {
                // TODO: I guess it would be okay if I don't use -ffast-math
                // (or something like that), but needs review.

                if val == 0.0f64 {
                    // If only one zero is used, it's decimal.
                    // And if multiple zero is used, it's octal.
                    //
                    // e.g. `0` is decimal (so it can be part of float)
                    //
                    // e.g. `000` is octal
                    if start.0 != self.last_pos().0 - 1 {
                        // `-1` is utf 8 length of `0`

                        return self.make_legacy_octal(start, 0f64).map(Either::Left);
                    }
                } else {
                    // strict mode hates non-zero decimals starting with zero.
                    // e.g. 08.1 is strict mode violation but 0.1 is valid float.

                    if val.fract() == 0.0 {
                        let val_str = s.to_string();

                        // if it contains '8' or '9', it's decimal.
                        if not_octal {
                            // Continue parsing
                            self.emit_strict_mode_error(start, SyntaxError::LegacyDecimal);
                        } else {
                            // It's Legacy octal, and we should reinterpret value.
                            let val =
                                lexical::parse_radix::<f64, _>(&val_str, 8).unwrap_or_else(|err| {
                                    panic!("failed to parse {} using `lexical`: {:?}", val_str, err)
                                });

                            return self.make_legacy_octal(start, val).map(Either::Left);
                        }
                    }
                }
            }

            val
        };

        // At this point, number cannot be an octal literal.

        let mut val: f64 = val;

        //  `0.a`, `08.a`, `102.a` are invalid.
        //
        // `.1.a`, `.1e-4.a` are valid,
        if self.cur() == Some('.') {
            raw_val.push('.');
            self.bump();
            if starts_with_dot {
                debug_assert!(self.cur().is_some());
                debug_assert!(self.cur().unwrap().is_digit(10));
            }

            let mut raw = Raw(Some(String::new()));
            // Read numbers after dot
            let dec_val = self.read_int(10, 0, &mut raw)?;
            val = {
                if let Some(..) = dec_val {
                    raw_val.push_str(&raw.0.as_ref().unwrap());
                }

                raw_val
                    .parse()
                    .expect("failed to parse float using rust's impl")
            };
        }

        // Handle 'e' and 'E'
        //
        // .5e1 = 5
        // 1e2 = 100
        // 1e+2 = 100
        // 1e-2 = 0.01
        if self.eat(b'e') || self.eat(b'E') {
            let next = match self.cur() {
                Some(next) => next,
                None => {
                    let pos = self.cur_pos();
                    self.error(pos, SyntaxError::NumLitTerminatedWithExp)?
                }
            };

            raw_val.push('e');

            let positive = if next == '+' || next == '-' {
                self.bump(); // remove '+', '-'
                next == '+'
            } else {
                true
            };

            let exp = self.read_number_no_dot(10)?;

            val = if exp == f64::INFINITY {
                if positive && val != 0.0 {
                    f64::INFINITY
                } else {
                    0.0
                }
            } else {
                let flag = if positive { '+' } else { '-' };

                raw_val.push(flag);
                write!(raw_val, "{}", exp).unwrap();

                // TODO:
                raw_val.parse().expect("failed to parse float literal")
            }
        }

        self.ensure_not_ident()?;

        Ok(Either::Left(val))
    }
/// Reads an integer, octal integer, or floating-point number
Reads an integer, octal integer, or floating-point number
Reads an integer octal integer or floating - point number
pub(super) fn read_number(
        &mut self,
        starts_with_dot: bool,
    ) -> LexResult<Either<f64, BigIntValue>> {
        debug_assert!(self.cur().is_some());
        if starts_with_dot {
            debug_assert_eq!(
                self.cur(),
                Some('.'),
                "read_number(starts_with_dot = true) expects current char to be '.'"
            );
        }
        let start = self.cur_pos();
        let starts_with_zero = self.cur().unwrap() == '0';
        let mut raw_val = String::new();
        let val = if starts_with_dot {
            // first char is '.'
            0f64
        } else {
            // Use read_number_no_dot to support long numbers.
            let (val, s, not_octal) = self.read_number_no_dot_as_str(10)?;
            if self.input.cur() == Some('n') {
                self.input.bump();
                return Ok(Either::Right(s));
            }
            write!(raw_val, "{}", s).unwrap();
            if starts_with_zero {
                // TODO: I guess it would be okay if I don't use -ffast-math
                // (or something like that), but needs review.
                if val == 0.0f64 {
                    // If only one zero is used, it's decimal.
                    // And if multiple zero is used, it's octal.
                    //
                    // e.g. `0` is decimal (so it can be part of float)
                    //
                    // e.g. `000` is octal
                    if start.0 != self.last_pos().0 - 1 {
                        // `-1` is utf 8 length of `0`
                        return self.make_legacy_octal(start, 0f64).map(Either::Left);
                    }
                } else {
                    // strict mode hates non-zero decimals starting with zero.
                    // e.g. 08.1 is strict mode violation but 0.1 is valid float.
                    if val.fract() == 0.0 {
                        let val_str = s.to_string();
                        // if it contains '8' or '9', it's decimal.
                        if not_octal {
                            // Continue parsing
                            self.emit_strict_mode_error(start, SyntaxError::LegacyDecimal);
                        } else {
                            // It's Legacy octal, and we should reinterpret value.
                            let val =
                                lexical::parse_radix::<f64, _>(&val_str, 8).unwrap_or_else(|err| {
                                    panic!("failed to parse {} using `lexical`: {:?}", val_str, err)
                                });
                            return self.make_legacy_octal(start, val).map(Either::Left);
                        }
                    }
                }
            }
            val
        };
        // At this point, number cannot be an octal literal.
        let mut val: f64 = val;
        //  `0.a`, `08.a`, `102.a` are invalid.
        //
        // `.1.a`, `.1e-4.a` are valid,
        if self.cur() == Some('.') {
            raw_val.push('.');
            self.bump();
            if starts_with_dot {
                debug_assert!(self.cur().is_some());
                debug_assert!(self.cur().unwrap().is_digit(10));
            }
            let mut raw = Raw(Some(String::new()));
            // Read numbers after dot
            let dec_val = self.read_int(10, 0, &mut raw)?;
            val = {
                if let Some(..) = dec_val {
                    raw_val.push_str(&raw.0.as_ref().unwrap());
                }
                raw_val
                    .parse()
                    .expect("failed to parse float using rust's impl")
            };
        }
        // Handle 'e' and 'E'
        //
        // .5e1 = 5
        // 1e2 = 100
        // 1e+2 = 100
        // 1e-2 = 0.01
        if self.eat(b'e') || self.eat(b'E') {
            let next = match self.cur() {
                Some(next) => next,
                None => {
                    let pos = self.cur_pos();
                    self.error(pos, SyntaxError::NumLitTerminatedWithExp)?
                }
            };
            raw_val.push('e');
            let positive = if next == '+' || next == '-' {
                self.bump(); // remove '+', '-'
                next == '+'
            } else {
                true
            };
            let exp = self.read_number_no_dot(10)?;
            val = if exp == f64::INFINITY {
                if positive && val != 0.0 {
                    f64::INFINITY
                } else {
                    0.0
                }
            } else {
                let flag = if positive { '+' } else { '-' };
                raw_val.push(flag);
                write!(raw_val, "{}", exp).unwrap();
                // TODO:
                raw_val.parse().expect("failed to parse float literal")
            }
        }
        self.ensure_not_ident()?;
        Ok(Either::Left(val))
    }
pub ( super ) fn read_number ( & mut self , starts_with_dot : bool , ) -> LexResult < Either < f64 , BigIntValue > > { debug_assert ! ( self cur ( ) is_some ( ) ) ; if starts_with_dot { debug_assert_eq ! ( self cur ( ) Some ( '.' ) " " ) ; } let start = self . cur_pos ( ) ; let starts_with_zero = self . cur ( ) . unwrap ( ) == '0' ; let mut raw_val = String :: new ( ) ; let val = if starts_with_dot { // first char is '.' 0f64 } else { // Use read_number_no_dot to support long numbers. let ( val , s , not_octal ) = self . read_number_no_dot_as_str ( 10 ) ? ; if self . input . cur ( ) == Some ( 'n' ) { self . input . bump ( ) ; return Ok ( Either :: Right ( s ) ) ; } write ! ( raw_val " " s ) . unwrap ( ) ; if starts_with_zero { // TODO: I guess it would be okay if I don't use -ffast-math // (or something like that), but needs review. if val == 0.0f64 { // If only one zero is used, it's decimal. // And if multiple zero is used, it's octal. // // e.g. `0` is decimal (so it can be part of float) // // e.g. `000` is octal if start . 0 != self . last_pos ( ) . 0 - 1 { // `-1` is utf 8 length of `0` return self . make_legacy_octal ( start , 0f64 ) . map ( Either :: Left ) ; } } else { // strict mode hates non-zero decimals starting with zero. // e.g. 08.1 is strict mode violation but 0.1 is valid float. if val . fract ( ) == 0.0 { let val_str = s . to_string ( ) ; // if it contains '8' or '9', it's decimal. if not_octal { // Continue parsing self . emit_strict_mode_error ( start , SyntaxError :: LegacyDecimal ) ; } else { // It's Legacy octal, and we should reinterpret value. let val = lexical :: parse_radix :: < f64 , _ > ( & val_str , 8 ) . unwrap_or_else ( | err | { panic ! ( " " val_str err ) } ) ; return self . make_legacy_octal ( start , val ) . map ( Either :: Left ) ; } } } } val } ; // At this point, number cannot be an octal literal. let mut val : f64 = val ; //  `0.a`, `08.a`, `102.a` are invalid. // // `.1.a`, `.1e-4.a` are valid, if self . cur ( ) == Some ( '.' ) { raw_val . push ( '.' ) ; self . bump ( ) ; if starts_with_dot { debug_assert ! ( self cur ( ) is_some ( ) ) ; debug_assert ! ( self cur ( ) unwrap ( ) is_digit ( 10 ) ) ; } let mut raw = Raw ( Some ( String :: new ( ) ) ) ; // Read numbers after dot let dec_val = self . read_int ( 10 , 0 , & mut raw ) ? ; val = { if let Some ( .. ) = dec_val { raw_val . push_str ( & raw . 0 . as_ref ( ) . unwrap ( ) ) ; } raw_val . parse ( ) . expect ( " " ) } ; } // Handle 'e' and 'E' // // .5e1 = 5 // 1e2 = 100 // 1e+2 = 100 // 1e-2 = 0.01 if self . eat ( b'e' ) || self . eat ( b'E' ) { let next = match self . cur ( ) { Some ( next ) => next , None => { let pos = self . cur_pos ( ) ; self . error ( pos , SyntaxError :: NumLitTerminatedWithExp ) ? } } ; raw_val . push ( 'e' ) ; let positive = if next == '+' || next == '-' { self . bump ( ) ; // remove '+', '-' next == '+' } else { true } ; let exp = self . read_number_no_dot ( 10 ) ? ; val = if exp == f64 :: INFINITY { if positive && val != 0.0 { f64 :: INFINITY } else { 0.0 } } else { let flag = if positive { '+' } else { '-' } ; raw_val . push ( flag ) ; write ! ( raw_val " " exp ) . unwrap ( ) ; // TODO: raw_val . parse ( ) . expect ( " " ) } } self . ensure_not_ident ( ) ? ; Ok ( Either :: Left ( val ) ) }
Reads an integer, octal integer, or floating-point number
Reads an integer octal integer or floating - point number
&mut self
starts_with_dot
bool