package parser

import (
	
	
	
	
	
	
	
	

	

	
	
	
)

var (
	unicodeRangeIdNeg      = rangetable.Merge(unicode.Pattern_Syntax, unicode.Pattern_White_Space)
	unicodeRangeIdStartPos = rangetable.Merge(unicode.Letter, unicode.Nl, unicode.Other_ID_Start)
	unicodeRangeIdContPos  = rangetable.Merge(unicodeRangeIdStartPos, unicode.Mn, unicode.Mc, unicode.Nd, unicode.Pc, unicode.Other_ID_Continue)
)

func isDecimalDigit( rune) bool {
	return '0' <=  &&  <= '9'
}

func ( string) bool {
	if  == "" {
		return false
	}
	,  := utf8.DecodeRuneInString()
	if !isIdentifierStart() {
		return false
	}
	for ,  := range [:] {
		if !isIdentifierPart() {
			return false
		}
	}
	return true
}

func digitValue( rune) int {
	switch {
	case '0' <=  &&  <= '9':
		return int( - '0')
	case 'a' <=  &&  <= 'f':
		return int( - 'a' + 10)
	case 'A' <=  &&  <= 'F':
		return int( - 'A' + 10)
	}
	return 16 // Larger than any legal digit value
}

func isDigit( rune,  int) bool {
	return digitValue() < 
}

func isIdStartUnicode( rune) bool {
	return unicode.Is(unicodeRangeIdStartPos, ) && !unicode.Is(unicodeRangeIdNeg, )
}

func isIdPartUnicode( rune) bool {
	return unicode.Is(unicodeRangeIdContPos, ) && !unicode.Is(unicodeRangeIdNeg, ) ||  == '\u200C' ||  == '\u200D'
}

func isIdentifierStart( rune) bool {
	return  == '$' ||  == '_' ||  == '\\' ||
		'a' <=  &&  <= 'z' || 'A' <=  &&  <= 'Z' ||
		 >= utf8.RuneSelf && isIdStartUnicode()
}

func isIdentifierPart( rune) bool {
	return  == '$' ||  == '_' ||  == '\\' ||
		'a' <=  &&  <= 'z' || 'A' <=  &&  <= 'Z' ||
		'0' <=  &&  <= '9' ||
		 >= utf8.RuneSelf && isIdPartUnicode()
}

func ( *_parser) () (string, unistring.String, bool, string) {
	 := .chrOffset
	 := false
	 := false
	 := 0
	for isIdentifierPart(.chr) {
		 := .chr
		++
		if  == '\\' {
			 = true
			 := .chrOffset - 
			.read()
			if .chr != 'u' {
				return "", "", false, fmt.Sprintf("Invalid identifier escape character: %c (%s)", .chr, string(.chr))
			}
			var  rune
			if ._peek() == '{' {
				.read()
				 = -1
				for  <= utf8.MaxRune {
					.read()
					if .chr == '}' {
						break
					}
					,  := hex2decimal(byte(.chr))
					if ! {
						return "", "", false, "Invalid Unicode escape sequence"
					}
					if  == -1 {
						 = 
					} else {
						 = <<4 | 
					}
				}
				if  == -1 {
					return "", "", false, "Invalid Unicode escape sequence"
				}
			} else {
				for  := 0;  < 4; ++ {
					.read()
					,  := hex2decimal(byte(.chr))
					if ! {
						return "", "", false, fmt.Sprintf("Invalid identifier escape character: %c (%s)", .chr, string(.chr))
					}
					 = <<4 | 
				}
			}
			if  == '\\' {
				return "", "", false, fmt.Sprintf("Invalid identifier escape value: %c (%s)", , string())
			} else if  == 0 {
				if !isIdentifierStart() {
					return "", "", false, fmt.Sprintf("Invalid identifier escape value: %c (%s)", , string())
				}
			} else if  > 0 {
				if !isIdentifierPart() {
					return "", "", false, fmt.Sprintf("Invalid identifier escape value: %c (%s)", , string())
				}
			}
			 = 
		}
		if  >= utf8.RuneSelf {
			 = true
			if  > 0xFFFF {
				++
			}
		}
		.read()
	}

	 := .str[:.chrOffset]
	var  unistring.String
	if  ||  {
		var  string
		// TODO strict
		,  = parseStringLiteral(, , , false)
		if  != "" {
			return "", "", false, 
		}
	} else {
		 = unistring.String()
	}

	return , , , ""
}

// 7.2
func isLineWhiteSpace( rune) bool {
	switch  {
	case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff':
		return true
	case '\u000a', '\u000d', '\u2028', '\u2029':
		return false
	case '\u0085':
		return false
	}
	return unicode.IsSpace()
}

// 7.3
func isLineTerminator( rune) bool {
	switch  {
	case '\u000a', '\u000d', '\u2028', '\u2029':
		return true
	}
	return false
}

type parserState struct {
	idx                                file.Idx
	tok                                token.Token
	literal                            string
	parsedLiteral                      unistring.String
	implicitSemicolon, insertSemicolon bool
	chr                                rune
	chrOffset, offset                  int
	errorCount                         int
}

func ( *_parser) ( *parserState) *parserState {
	if  == nil {
		 = &parserState{}
	}
	.idx, .tok, .literal, .parsedLiteral, .implicitSemicolon, .insertSemicolon, .chr, .chrOffset, .offset =
		.idx, .token, .literal, .parsedLiteral, .implicitSemicolon, .insertSemicolon, .chr, .chrOffset, .offset

	.errorCount = len(.errors)
	return 
}

func ( *_parser) ( *parserState) {
	.idx, .token, .literal, .parsedLiteral, .implicitSemicolon, .insertSemicolon, .chr, .chrOffset, .offset =
		.idx, .tok, .literal, .parsedLiteral, .implicitSemicolon, .insertSemicolon, .chr, .chrOffset, .offset
	.errors = .errors[:.errorCount]
}

func ( *_parser) () token.Token {
	, , , ,  := .implicitSemicolon, .insertSemicolon, .chr, .chrOffset, .offset
	, , ,  := .scan()
	.implicitSemicolon, .insertSemicolon, .chr, .chrOffset, .offset = , , , , 
	return 
}

func ( *_parser) () ( token.Token,  string,  unistring.String,  file.Idx) {

	.implicitSemicolon = false

	for {
		.skipWhiteSpace()

		 = .idxOf(.chrOffset)
		 := false

		switch  := .chr; {
		case isIdentifierStart():
			var  string
			var  bool
			, , ,  = .scanIdentifier()
			if  != "" {
				 = token.ILLEGAL
				break
			}
			if len() > 1 {
				// Keywords are longer than 1 character, avoid lookup otherwise
				var  bool
				,  = token.IsKeyword(string())
				if  {
					.insertSemicolon = true
					if  == 0 || .isBindingId() {
						 = token.IDENTIFIER
					} else {
						 = token.ESCAPED_RESERVED_WORD
					}
					return
				}
				switch  {
				case 0: // Not a keyword
					// no-op
				case token.KEYWORD:
					if  {
						// TODO If strict and in strict mode, then this is not a break
						break
					}
					return

				case
					token.BOOLEAN,
					token.NULL,
					token.THIS,
					token.BREAK,
					token.THROW, // A newline after a throw is not allowed, but we need to detect it
					token.YIELD,
					token.RETURN,
					token.CONTINUE,
					token.DEBUGGER:
					.insertSemicolon = true
					return

				case token.ASYNC:
					// async only has special meaning if not followed by a LineTerminator
					if .skipWhiteSpaceCheckLineTerminator() {
						.insertSemicolon = true
						 = token.IDENTIFIER
					}
					return
				default:
					return

				}
			}
			.insertSemicolon = true
			 = token.IDENTIFIER
			return
		case '0' <=  &&  <= '9':
			.insertSemicolon = true
			,  = .scanNumericLiteral(false)
			return
		default:
			.read()
			switch  {
			case -1:
				if .insertSemicolon {
					.insertSemicolon = false
					.implicitSemicolon = true
				}
				 = token.EOF
			case '\r', '\n', '\u2028', '\u2029':
				.insertSemicolon = false
				.implicitSemicolon = true
				continue
			case ':':
				 = token.COLON
			case '.':
				if digitValue(.chr) < 10 {
					 = true
					,  = .scanNumericLiteral(true)
				} else {
					if .chr == '.' {
						.read()
						if .chr == '.' {
							.read()
							 = token.ELLIPSIS
						} else {
							 = token.ILLEGAL
						}
					} else {
						 = token.PERIOD
					}
				}
			case ',':
				 = token.COMMA
			case ';':
				 = token.SEMICOLON
			case '(':
				 = token.LEFT_PARENTHESIS
			case ')':
				 = token.RIGHT_PARENTHESIS
				 = true
			case '[':
				 = token.LEFT_BRACKET
			case ']':
				 = token.RIGHT_BRACKET
				 = true
			case '{':
				 = token.LEFT_BRACE
			case '}':
				 = token.RIGHT_BRACE
				 = true
			case '+':
				 = .switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT)
				if  == token.INCREMENT {
					 = true
				}
			case '-':
				 = .switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT)
				if  == token.DECREMENT {
					 = true
				}
			case '*':
				if .chr == '*' {
					.read()
					 = .switch2(token.EXPONENT, token.EXPONENT_ASSIGN)
				} else {
					 = .switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN)
				}
			case '/':
				if .chr == '/' {
					.skipSingleLineComment()
					continue
				} else if .chr == '*' {
					if .skipMultiLineComment() {
						.insertSemicolon = false
						.implicitSemicolon = true
					}
					continue
				} else {
					// Could be division, could be RegExp literal
					 = .switch2(token.SLASH, token.QUOTIENT_ASSIGN)
					 = true
				}
			case '%':
				 = .switch2(token.REMAINDER, token.REMAINDER_ASSIGN)
			case '^':
				 = .switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN)
			case '<':
				 = .switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN)
			case '>':
				 = .switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN)
			case '=':
				if .chr == '>' {
					.read()
					if .implicitSemicolon {
						 = token.ILLEGAL
					} else {
						 = token.ARROW
					}
				} else {
					 = .switch2(token.ASSIGN, token.EQUAL)
					if  == token.EQUAL && .chr == '=' {
						.read()
						 = token.STRICT_EQUAL
					}
				}
			case '!':
				 = .switch2(token.NOT, token.NOT_EQUAL)
				if  == token.NOT_EQUAL && .chr == '=' {
					.read()
					 = token.STRICT_NOT_EQUAL
				}
			case '&':
				 = .switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND)
			case '|':
				 = .switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR)
			case '~':
				 = token.BITWISE_NOT
			case '?':
				if .chr == '.' && !isDecimalDigit(._peek()) {
					.read()
					 = token.QUESTION_DOT
				} else if .chr == '?' {
					.read()
					 = token.COALESCE
				} else {
					 = token.QUESTION_MARK
				}
			case '"', '\'':
				 = true
				 = token.STRING
				var  string
				, ,  = .scanString(.chrOffset-1, true)
				if  != "" {
					 = token.ILLEGAL
				}
			case '`':
				 = token.BACKTICK
			case '#':
				if .chrOffset == 1 && .chr == '!' {
					.skipSingleLineComment()
					continue
				}

				var  string
				, , _,  = .scanIdentifier()
				if  != "" ||  == "" {
					 = token.ILLEGAL
					break
				}
				.insertSemicolon = true
				 = token.PRIVATE_IDENTIFIER
				return
			default:
				.errorUnexpected(, )
				 = token.ILLEGAL
			}
		}
		.insertSemicolon = 
		return
	}
}

func ( *_parser) (,  token.Token) token.Token {
	if .chr == '=' {
		.read()
		return 
	}
	return 
}

func ( *_parser) (,  token.Token,  rune,  token.Token) token.Token {
	if .chr == '=' {
		.read()
		return 
	}
	if .chr ==  {
		.read()
		return 
	}
	return 
}

func ( *_parser) (,  token.Token,  rune, ,  token.Token) token.Token {
	if .chr == '=' {
		.read()
		return 
	}
	if .chr ==  {
		.read()
		if .chr == '=' {
			.read()
			return 
		}
		return 
	}
	return 
}

func ( *_parser) (,  token.Token,  rune, ,  token.Token,  rune, ,  token.Token) token.Token {
	if .chr == '=' {
		.read()
		return 
	}
	if .chr ==  {
		.read()
		if .chr == '=' {
			.read()
			return 
		}
		if .chr ==  {
			.read()
			if .chr == '=' {
				.read()
				return 
			}
			return 
		}
		return 
	}
	return 
}

func ( *_parser) () rune {
	if .offset < .length {
		return rune(.str[.offset])
	}
	return -1
}

func ( *_parser) () {
	if .offset < .length {
		.chrOffset = .offset
		,  := rune(.str[.offset]), 1
		if  >= utf8.RuneSelf { // !ASCII
			,  = utf8.DecodeRuneInString(.str[.offset:])
			if  == utf8.RuneError &&  == 1 {
				.error(.chrOffset, "Invalid UTF-8 character")
			}
		}
		.offset += 
		.chr = 
	} else {
		.chrOffset = .length
		.chr = -1 // EOF
	}
}

func ( *_parser) () {
	for .chr != -1 {
		.read()
		if isLineTerminator(.chr) {
			return
		}
	}
}

func ( *_parser) () ( bool) {
	.read()
	for .chr >= 0 {
		 := .chr
		if  == '\r' ||  == '\n' ||  == '\u2028' ||  == '\u2029' {
			 = true
			break
		}
		.read()
		if  == '*' && .chr == '/' {
			.read()
			return
		}
	}
	for .chr >= 0 {
		 := .chr
		.read()
		if  == '*' && .chr == '/' {
			.read()
			return
		}
	}

	.errorUnexpected(0, .chr)
	return
}

func ( *_parser) () bool {
	for {
		switch .chr {
		case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff':
			.read()
			continue
		case '\r':
			if ._peek() == '\n' {
				.read()
			}
			fallthrough
		case '\u2028', '\u2029', '\n':
			return true
		}
		if .chr >= utf8.RuneSelf {
			if unicode.IsSpace(.chr) {
				.read()
				continue
			}
		}
		break
	}
	return false
}

func ( *_parser) () {
	for {
		switch .chr {
		case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff':
			.read()
			continue
		case '\r':
			if ._peek() == '\n' {
				.read()
			}
			fallthrough
		case '\u2028', '\u2029', '\n':
			if .insertSemicolon {
				return
			}
			.read()
			continue
		}
		if .chr >= utf8.RuneSelf {
			if unicode.IsSpace(.chr) {
				.read()
				continue
			}
		}
		break
	}
}

func ( *_parser) ( int,  bool) {
	for digitValue(.chr) <  || ( && .chr == '_') {
		 := .chr == '_'
		.read()
		if  && !isDigit(.chr, ) {
			.error(.chrOffset, "Only one underscore is allowed as numeric separator")
		}
	}
}

func ( *_parser) ( rune) (int, bool) {

	var ,  uint32
	 := .chr
	switch  {
	case '0', '1', '2', '3', '4', '5', '6', '7':
		//    Octal:
		,  = 3, 8
	case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'':
		.read()
		return 1, false
	case '\r':
		.read()
		if .chr == '\n' {
			.read()
			return 2, false
		}
		return 1, false
	case '\n':
		.read()
		return 1, false
	case '\u2028', '\u2029':
		.read()
		return 1, true
	case 'x':
		.read()
		,  = 2, 16
	case 'u':
		.read()
		if .chr == '{' {
			.read()
			,  = 0, 16
		} else {
			,  = 4, 16
		}
	default:
		.read() // Always make progress
	}

	if  > 0 {
		var  uint32
		if  > 0 {
			for ;  > 0 && .chr !=  && .chr >= 0; -- {
				 := uint32(digitValue(.chr))
				if  >=  {
					break
				}
				 = * + 
				.read()
			}
		} else {
			for .chr !=  && .chr >= 0 &&  < utf8.MaxRune {
				if .chr == '}' {
					.read()
					break
				}
				 := uint32(digitValue(.chr))
				if  >=  {
					break
				}
				 = * + 
				.read()
			}
		}
		 = rune()
	}
	if  >= utf8.RuneSelf {
		if  > 0xFFFF {
			return 2, true
		}
		return 1, true
	}
	return 1, false
}

func ( *_parser) ( int,  bool) ( string,  unistring.String,  string) {
	// " ' /
	 := rune(.str[])
	 := 0
	 := false
	for .chr !=  {
		 := .chr
		if  == '\n' ||  == '\r' ||  < 0 {
			goto 
		}
		if  == '/' && (.chr == '\u2028' || .chr == '\u2029') {
			goto 
		}
		.read()
		if  == '\\' {
			if .chr == '\n' || .chr == '\r' || .chr == '\u2028' || .chr == '\u2029' || .chr < 0 {
				if  == '/' {
					goto 
				}
				.scanNewline()
			} else {
				,  := .scanEscape()
				 += 
				if  {
					 = true
				}
			}
			continue
		} else if  == '[' &&  == '/' {
			// Allow a slash (/) in a bracket character class ([...])
			// TODO Fix this, this is hacky...
			 = -1
		} else if  == ']' &&  == -1 {
			 = '/'
		}
		if  >= utf8.RuneSelf {
			 = true
			if  > 0xFFFF {
				++
			}
		}
		++
	}

	// " ' /
	.read()
	 = .str[:.chrOffset]
	if  {
		// TODO strict
		,  = parseStringLiteral([1:len()-1], , , false)
	}
	return

:
	.scanNewline()
	 := "String not terminated"
	if  == '/' {
		 = "Invalid regular expression: missing /"
		.error(.idxOf(), )
	}
	return "", "", 
}

func ( *_parser) () {
	if .chr == '\u2028' || .chr == '\u2029' {
		.read()
		return
	}
	if .chr == '\r' {
		.read()
		if .chr != '\n' {
			return
		}
	}
	.read()
}

func ( *_parser) () ( string,  unistring.String,  bool, ,  string) {
	 := .chrOffset
	var  int
	 := 0
	 := false
	 := false
	for {
		 := .chr
		if  < 0 {
			goto 
		}
		.read()
		if  == '`' {
			 = true
			 = .chrOffset - 1
			break
		}
		if  == '\\' {
			if .chr == '\n' || .chr == '\r' || .chr == '\u2028' || .chr == '\u2029' || .chr < 0 {
				if .chr == '\r' {
					 = true
				}
				.scanNewline()
			} else {
				if .chr == '8' || .chr == '9' {
					if  == "" {
						 = "\\8 and \\9 are not allowed in template strings."
					}
				}
				,  := .scanEscape('`')
				 += 
				if  {
					 = true
				}
			}
			continue
		}
		if  == '$' && .chr == '{' {
			.read()
			 = .chrOffset - 2
			break
		}
		if  >= utf8.RuneSelf {
			 = true
			if  > 0xFFFF {
				++
			}
		} else if  == '\r' {
			 = true
			if .chr == '\n' {
				--
			}
		}
		++
	}
	 = .str[:]
	if  {
		 = normaliseCRLF()
	}
	if  == "" {
		,  = parseStringLiteral(, , , true)
	}
	.insertSemicolon = true
	return
:
	 = err_UnexpectedEndOfInput
	 = true
	return
}

func normaliseCRLF( string) string {
	var  strings.Builder
	.Grow(len())
	for  := 0;  < len(); ++ {
		if [] == '\r' {
			.WriteByte('\n')
			if  < len()-1 && [+1] == '\n' {
				++
			}
		} else {
			.WriteByte([])
		}
	}
	return .String()
}

func hex2decimal( byte) ( rune,  bool) {
	{
		 := rune()
		switch {
		case '0' <=  &&  <= '9':
			return  - '0', true
		case 'a' <=  &&  <= 'f':
			return  - 'a' + 10, true
		case 'A' <=  &&  <= 'F':
			return  - 'A' + 10, true
		}
		return
	}
}

func parseNumberLiteral( string) ( interface{},  error) {
	// TODO Is Uint okay? What about -MAX_UINT
	,  = strconv.ParseInt(, 0, 64)
	if  == nil {
		return
	}

	 :=  // Save this first error, just in case

	,  = strconv.ParseFloat(, 64)
	if  == nil {
		return
	} else if .(*strconv.NumError).Err == strconv.ErrRange {
		// Infinity, etc.
		return , nil
	}

	 = 

	if .(*strconv.NumError).Err == strconv.ErrRange {
		if len() > 2 &&
			[0] == '0' && ([1] == 'X' || [1] == 'x') &&
			[len()-1] != 'n' {
			// Could just be a very large number (e.g. 0x8000000000000000)
			var  float64
			 = [2:]
			for ,  := range  {
				 := digitValue()
				if  >= 16 {
					goto 
				}
				 = *16 + float64()
			}
			return , nil
		}
	}

	if len() > 1 && [len()-1] == 'n' {
		if [0] == '0' {
			if len() > 2 && isDecimalDigit(rune([1])) {
				goto 
			}
		}
		// Parse as big.Int
		 := new(big.Int)
		,  := .SetString([:len()-1], 0)
		if ! {
			goto 
		}
		return , nil
	}

:
	return nil, errors.New("Illegal numeric literal")
}

func parseStringLiteral( string,  int, ,  bool) (unistring.String, string) {
	var  strings.Builder
	var  []uint16
	if  {
		 = make([]uint16, 1, +1)
		[0] = unistring.BOM
	} else {
		.Grow()
	}
	 := 
	for len() > 0 {
		switch  := [0]; {
		// We do not explicitly handle the case of the quote
		// value, which can be: " ' /
		// This assumes we're already passed a partially well-formed literal
		case  >= utf8.RuneSelf:
			,  := utf8.DecodeRuneInString()
			if  <= 0xFFFF {
				 = append(, uint16())
			} else {
				,  := utf16.EncodeRune()
				 = append(, uint16(), uint16())
			}
			 = [:]
			continue
		case  != '\\':
			if  {
				 = append(, uint16())
			} else {
				.WriteByte()
			}
			 = [1:]
			continue
		}

		if len() <= 1 {
			panic("len(str) <= 1")
		}
		 := [1]
		var  rune
		if  >= utf8.RuneSelf {
			 = [1:]
			var  int
			,  = utf8.DecodeRuneInString()
			 = [:] // \ + <character>
			if  == '\u2028' ||  == '\u2029' {
				continue
			}
		} else {
			 = [2:] // \<character>
			switch  {
			case 'b':
				 = '\b'
			case 'f':
				 = '\f'
			case 'n':
				 = '\n'
			case 'r':
				 = '\r'
			case 't':
				 = '\t'
			case 'v':
				 = '\v'
			case 'x', 'u':
				 := 0
				switch  {
				case 'x':
					 = 2
				case 'u':
					if  == "" || [0] != '{' {
						 = 4
					}
				}
				if  > 0 {
					if len() <  {
						return "", fmt.Sprintf("invalid escape: \\%s: len(%q) != %d", string(), , )
					}
					for  := 0;  < ; ++ {
						,  := hex2decimal([])
						if ! {
							return "", fmt.Sprintf("invalid escape: \\%s: %q", string(), [:])
						}
						 = <<4 | 
					}
				} else {
					 = [1:]
					var  rune
					 = -1
					for ;  < len(); ++ {
						if [] == '}' {
							if  == 0 {
								return "", fmt.Sprintf("invalid escape: \\%s", string())
							}
							++
							 = 
							break
						}
						,  := hex2decimal([])
						if ! {
							return "", fmt.Sprintf("invalid escape: \\%s: %q", string(), [:+1])
						}
						 = <<4 | 
						if  > utf8.MaxRune {
							return "", fmt.Sprintf("undefined Unicode code-point: %q", [:+1])
						}
					}
					if  == -1 {
						return "", fmt.Sprintf("unterminated \\u{: %q", )
					}
				}
				 = [:]
				if  == 'x' {
					break
				}
				if  > utf8.MaxRune {
					panic("value > utf8.MaxRune")
				}
			case '0':
				if len() == 0 || '0' > [0] || [0] > '7' {
					 = 0
					break
				}
				fallthrough
			case '1', '2', '3', '4', '5', '6', '7':
				if  {
					return "", "Octal escape sequences are not allowed in this context"
				}
				 = rune() - '0'
				 := 0
				for ;  < 2; ++ {
					if len() < +1 {
						break
					}
					 := []
					if '0' >  ||  > '7' {
						break
					}
					 := rune([]) - '0'
					 = ( << 3) | 
				}
				 = [:]
			case '\\':
				 = '\\'
			case '\'', '"':
				 = rune()
			case '\r':
				if len() > 0 {
					if [0] == '\n' {
						 = [1:]
					}
				}
				fallthrough
			case '\n':
				continue
			default:
				 = rune()
			}
		}
		if  {
			if  <= 0xFFFF {
				 = append(, uint16())
			} else {
				,  := utf16.EncodeRune()
				 = append(, uint16(), uint16())
			}
		} else {
			if  >= utf8.RuneSelf {
				return "", "Unexpected unicode character"
			}
			.WriteByte(byte())
		}
	}

	if  {
		if len() != +1 {
			panic(fmt.Errorf("unexpected unicode length while parsing '%s'", ))
		}
		return unistring.FromUtf16(), ""
	}
	if .Len() !=  {
		panic(fmt.Errorf("unexpected length while parsing '%s'", ))
	}
	return unistring.String(.String()), ""
}

func ( *_parser) ( bool) (token.Token, string) {

	 := .chrOffset
	 := token.NUMBER

	if  {
		--
		.scanMantissa(10, true)
	} else {
		if .chr == '0' {
			.read()
			 := 0
			switch .chr {
			case 'x', 'X':
				 = 16
			case 'o', 'O':
				 = 8
			case 'b', 'B':
				 = 2
			case '.', 'e', 'E':
				// no-op
			default:
				// legacy octal
				.scanMantissa(8, false)
				goto 
			}
			if  > 0 {
				.read()
				if !isDigit(.chr, ) {
					return token.ILLEGAL, .str[:.chrOffset]
				}
				.scanMantissa(, true)
				goto 
			}
		} else {
			.scanMantissa(10, true)
		}
		if .chr == '.' {
			.read()
			.scanMantissa(10, true)
		}
	}

	if .chr == 'e' || .chr == 'E' {
		.read()
		if .chr == '-' || .chr == '+' {
			.read()
		}
		if isDecimalDigit(.chr) {
			.read()
			.scanMantissa(10, true)
		} else {
			return token.ILLEGAL, .str[:.chrOffset]
		}
	}
:
	if .chr == 'n' || .chr == 'N' {
		.read()
		return , .str[:.chrOffset]
	}
	if isIdentifierStart(.chr) || isDecimalDigit(.chr) {
		return token.ILLEGAL, .str[:.chrOffset]
	}

	return , .str[:.chrOffset]
}