Copyright 2018 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package text
parseNumberValue parses a number from the input and returns a Token object.
func ( *Decoder) () (Token, bool) {
	 := .in
	 := parseNumber()
	if .size == 0 {
		return Token{}, false
	}
	 := .kind
	if .neg {
		 |= isNegative
	}
	 := .size
	 := .size - 1
	if .kind == numFloat && (.in[] == 'f' || .in[] == 'F') {
		 = 
	}
	 := Token{
		kind:     Scalar,
		attrs:    numberValue,
		pos:      len(.orig) - len(.in),
		raw:      .in[:.size],
		str:      string(.in[:]),
		numAttrs: ,
	}
	.consume(.size)
	return , true
}

const (
	numDec uint8 = (1 << iota) / 2
	numHex
	numOct
	numFloat
)
number is the result of parsing out a valid number from parseNumber. It contains data for doing float or integer conversion via the strconv package in conjunction with the input bytes.
type number struct {
	kind uint8
	neg  bool
	size int
}
parseNumber constructs a number object from given input. It allows for the following patterns: integer: ^-?([1-9][0-9]*|0[xX][0-9a-fA-F]+|0[0-7]*) float: ^-?((0|[1-9][0-9]*)?([.][0-9]*)?([eE][+-]?[0-9]+)?[fF]?) It also returns the number of parsed bytes for the given number, 0 if it is not a number.
func ( []byte) number {
	 := numDec
	var  int
	var  bool

	 := 
	if len() == 0 {
		return number{}
	}
Optional -
	if [0] == '-' {
		 = true
		 = [1:]
		++
		if len() == 0 {
			return number{}
		}
	}
C++ allows for whitespace and comments in between the negative sign and the rest of the number. This logic currently does not but is consistent with v1.

	switch {
	case [0] == '0':
		if len() > 1 {
			switch {
Parse as hex number.
				 = numHex
				 := 2
				 = [2:]
				for len() > 0 && (('0' <= [0] && [0] <= '9') ||
					('a' <= [0] && [0] <= 'f') ||
					('A' <= [0] && [0] <= 'F')) {
					 = [1:]
					++
				}
				if  == 2 {
					return number{}
				}
				 += 

Parse as octal number.
				 = numOct
				 := 2
				 = [2:]
				for len() > 0 && '0' <= [0] && [0] <= '7' {
					 = [1:]
					++
				}
				 += 
			}

			if &(numHex|numOct) > 0 {
				if len() > 0 && !isDelim([0]) {
					return number{}
				}
				return number{kind: , neg: , size: }
			}
		}
		 = [1:]
		++

	case '1' <= [0] && [0] <= '9':
		 := 1
		 = [1:]
		for len() > 0 && '0' <= [0] && [0] <= '9' {
			 = [1:]
			++
		}
		 += 

Set kind to numFloat to signify the intent to parse as float. And that it needs to have other digits after '.'.
		 = numFloat

	default:
		return number{}
	}
. followed by 0 or more digits.
	if len() > 0 && [0] == '.' {
		 := 1
If decimal point was before any digits, it should be followed by other digits.
		if len() == 0 &&  == numFloat {
			return number{}
		}
		for len() > 0 && '0' <= [0] && [0] <= '9' {
			 = [1:]
			++
		}
		 += 
		 = numFloat
	}
e or E followed by an optional - or + and 1 or more digits.
	if len() >= 2 && ([0] == 'e' || [0] == 'E') {
		 = numFloat
		 = [1:]
		 := 1
		if [0] == '+' || [0] == '-' {
			 = [1:]
			++
			if len() == 0 {
				return number{}
			}
		}
		for len() > 0 && '0' <= [0] && [0] <= '9' {
			 = [1:]
			++
		}
		 += 
	}
Optional suffix f or F for floats.
	if len() > 0 && ([0] == 'f' || [0] == 'F') {
		 = numFloat
		 = [1:]
		++
	}
Check that next byte is a delimiter or it is at the end.
	if len() > 0 && !isDelim([0]) {
		return number{}
	}

	return number{kind: , neg: , size: }