package parser

import (
	

	
	
	
	
)

func ( *_parser) () *ast.Identifier {
	 := .parsedLiteral
	 := .idx
	.next()
	return &ast.Identifier{
		Name: ,
		Idx:  ,
	}
}

func ( *_parser) () ast.Expression {
	,  := .literal, .parsedLiteral
	 := .idx
	switch .token {
	case token.IDENTIFIER:
		.next()
		return &ast.Identifier{
			Name: ,
			Idx:  ,
		}
	case token.NULL:
		.next()
		return &ast.NullLiteral{
			Idx:     ,
			Literal: ,
		}
	case token.BOOLEAN:
		.next()
		 := false
		switch  {
		case "true":
			 = true
		case "false":
			 = false
		default:
			.error(, "Illegal boolean literal")
		}
		return &ast.BooleanLiteral{
			Idx:     ,
			Literal: ,
			Value:   ,
		}
	case token.STRING:
		.next()
		return &ast.StringLiteral{
			Idx:     ,
			Literal: ,
			Value:   ,
		}
	case token.NUMBER:
		.next()
		,  := parseNumberLiteral()
		if  != nil {
			.error(, .Error())
			 = 0
		}
		return &ast.NumberLiteral{
			Idx:     ,
			Literal: ,
			Value:   ,
		}
	case token.SLASH, token.QUOTIENT_ASSIGN:
		return .parseRegExpLiteral()
	case token.LEFT_BRACE:
		return .parseObjectLiteral()
	case token.LEFT_BRACKET:
		return .parseArrayLiteral()
	case token.LEFT_PARENTHESIS:
		return .parseParenthesisedExpression()
	case token.BACKTICK:
		return .parseTemplateLiteral(false)
	case token.THIS:
		.next()
		return &ast.ThisExpression{
			Idx: ,
		}
	case token.SUPER:
		return .parseSuperProperty()
	case token.ASYNC:
		if  := .parseMaybeAsyncFunction(false);  != nil {
			return 
		}
	case token.FUNCTION:
		return .parseFunction(false, false, )
	case token.CLASS:
		return .parseClass(false)
	}

	if .isBindingId(.token) {
		.next()
		return &ast.Identifier{
			Name: ,
			Idx:  ,
		}
	}

	.errorUnexpectedToken(.token)
	.nextStatement()
	return &ast.BadExpression{From: , To: .idx}
}

func ( *_parser) () ast.Expression {
	 := .idx
	.next()
	switch .token {
	case token.PERIOD:
		.next()
		if !token.IsId(.token) {
			.expect(token.IDENTIFIER)
			.nextStatement()
			return &ast.BadExpression{From: , To: .idx}
		}
		 := .idx
		 := .parsedLiteral
		.next()
		return &ast.DotExpression{
			Left: &ast.SuperExpression{
				Idx: ,
			},
			Identifier: ast.Identifier{
				Name: ,
				Idx:  ,
			},
		}
	case token.LEFT_BRACKET:
		return .parseBracketMember(&ast.SuperExpression{
			Idx: ,
		})
	case token.LEFT_PARENTHESIS:
		return .parseCallExpression(&ast.SuperExpression{
			Idx: ,
		})
	default:
		.error(, "'super' keyword unexpected here")
		.nextStatement()
		return &ast.BadExpression{From: , To: .idx}
	}
}

func ( *_parser) ( []ast.Expression) *ast.ParameterList {
	 := -1
	 := make([]*ast.Binding, 0, len())
	for ,  := range  {
		if ,  := .(*ast.SpreadElement);  {
			if  == -1 {
				 = 
				continue
			}
		}
		if  != -1 {
			.error([].Idx0(), "Rest parameter must be last formal parameter")
			return &ast.ParameterList{}
		}
		 = append(, .reinterpretAsBinding())
	}
	var  ast.Expression
	if  != -1 {
		 = .reinterpretAsBindingRestElement([])
	}
	return &ast.ParameterList{
		List: ,
		Rest: ,
	}
}

func ( *_parser) () ast.Expression {
	 := .idx
	.expect(token.LEFT_PARENTHESIS)
	var  []ast.Expression
	if .token != token.RIGHT_PARENTHESIS {
		for {
			if .token == token.ELLIPSIS {
				 := .idx
				.errorUnexpectedToken(token.ELLIPSIS)
				.next()
				 := .parseAssignmentExpression()
				 = append(, &ast.BadExpression{
					From: ,
					To:   .Idx1(),
				})
			} else {
				 = append(, .parseAssignmentExpression())
			}
			if .token != token.COMMA {
				break
			}
			.next()
			if .token == token.RIGHT_PARENTHESIS {
				.errorUnexpectedToken(token.RIGHT_PARENTHESIS)
				break
			}
		}
	}
	.expect(token.RIGHT_PARENTHESIS)
	if len() == 1 && len(.errors) == 0 {
		return [0]
	}
	if len() == 0 {
		.errorUnexpectedToken(token.RIGHT_PARENTHESIS)
		return &ast.BadExpression{
			From: ,
			To:   .idx,
		}
	}
	return &ast.SequenceExpression{
		Sequence: ,
	}
}

func ( *_parser) () *ast.RegExpLiteral {

	 := .chrOffset - 1 // Opening slash already gotten
	if .token == token.QUOTIENT_ASSIGN {
		 -= 1 // =
	}
	 := .idxOf()

	, ,  := .scanString(, false)
	 := .chrOffset

	if  == "" {
		 = [1 : len()-1]
	}

	 := ""
	if !isLineTerminator(.chr) && !isLineWhiteSpace(.chr) {
		.next()

		if .token == token.IDENTIFIER { // gim

			 = .literal
			.next()
			 = .chrOffset - 1
		}
	} else {
		.next()
	}

	 := .str[:]

	return &ast.RegExpLiteral{
		Idx:     ,
		Literal: ,
		Pattern: ,
		Flags:   ,
	}
}

func ( *_parser) ( token.Token) bool {
	if  == token.IDENTIFIER {
		return true
	}

	if  == token.AWAIT {
		return !.scope.allowAwait
	}
	if  == token.YIELD {
		return !.scope.allowYield
	}

	if token.IsUnreservedWord() {
		return true
	}
	return false
}

func ( *_parser) () {
	if .isBindingId(.token) {
		.token = token.IDENTIFIER
	}
}

func ( *_parser) () ( ast.BindingTarget) {
	.tokenToBindingId()
	switch .token {
	case token.IDENTIFIER:
		 = &ast.Identifier{
			Name: .parsedLiteral,
			Idx:  .idx,
		}
		.next()
	case token.LEFT_BRACKET:
		 = .parseArrayBindingPattern()
	case token.LEFT_BRACE:
		 = .parseObjectBindingPattern()
	default:
		 := .expect(token.IDENTIFIER)
		.nextStatement()
		 = &ast.BadExpression{From: , To: .idx}
	}

	return
}

func ( *_parser) ( *[]*ast.Binding) *ast.Binding {
	 := &ast.Binding{
		Target: .parseBindingTarget(),
	}

	if  != nil {
		* = append(*, )
	}

	if .token == token.ASSIGN {
		.next()
		.Initializer = .parseAssignmentExpression()
	}

	return 
}

func ( *_parser) () ( []*ast.Binding) {
	for {
		.parseVariableDeclaration(&)
		if .token != token.COMMA {
			break
		}
		.next()
	}
	return
}

func ( *_parser) ( file.Idx) []*ast.Binding {
	 := .parseVariableDeclarationList()

	.scope.declare(&ast.VariableDeclaration{
		Var:  ,
		List: ,
	})

	return 
}

func ( *_parser) () (string, unistring.String, ast.Expression, token.Token) {
	if .token == token.LEFT_BRACKET {
		.next()
		 := .parseAssignmentExpression()
		.expect(token.RIGHT_BRACKET)
		return "", "", , token.ILLEGAL
	}
	, , ,  := .idx, .token, .literal, .parsedLiteral
	var  ast.Expression
	.next()
	switch  {
	case token.IDENTIFIER, token.STRING, token.KEYWORD, token.ESCAPED_RESERVED_WORD:
		 = &ast.StringLiteral{
			Idx:     ,
			Literal: ,
			Value:   ,
		}
	case token.NUMBER:
		,  := parseNumberLiteral()
		if  != nil {
			.error(, .Error())
		} else {
			 = &ast.NumberLiteral{
				Idx:     ,
				Literal: ,
				Value:   ,
			}
		}
	case token.PRIVATE_IDENTIFIER:
		 = &ast.PrivateIdentifier{
			Identifier: ast.Identifier{
				Idx:  ,
				Name: ,
			},
		}
	default:
		// null, false, class, etc.
		if token.IsId() {
			 = &ast.StringLiteral{
				Idx:     ,
				Literal: ,
				Value:   unistring.String(),
			}
		} else {
			.errorUnexpectedToken()
		}
	}
	return , , , 
}

func ( *_parser) () ast.Property {
	if .token == token.ELLIPSIS {
		.next()
		return &ast.SpreadElement{
			Expression: .parseAssignmentExpression(),
		}
	}
	 := .idx
	 := false
	if .token == token.MULTIPLY {
		 = true
		.next()
	}
	, , ,  := .parseObjectPropertyKey()
	if  == nil {
		return nil
	}
	if token.IsId() ||  == token.STRING ||  == token.NUMBER ||  == token.ILLEGAL {
		if  {
			return &ast.PropertyKeyed{
				Key:      ,
				Kind:     ast.PropertyKindMethod,
				Value:    .parseMethodDefinition(, ast.PropertyKindMethod, true, false),
				Computed:  == token.ILLEGAL,
			}
		}
		switch {
		case .token == token.LEFT_PARENTHESIS:
			return &ast.PropertyKeyed{
				Key:      ,
				Kind:     ast.PropertyKindMethod,
				Value:    .parseMethodDefinition(, ast.PropertyKindMethod, false, false),
				Computed:  == token.ILLEGAL,
			}
		case .token == token.COMMA || .token == token.RIGHT_BRACE || .token == token.ASSIGN: // shorthand property
			if .isBindingId() {
				var  ast.Expression
				if .token == token.ASSIGN {
					// allow the initializer syntax here in case the object literal
					// needs to be reinterpreted as an assignment pattern, enforce later if it doesn't.
					.next()
					 = .parseAssignmentExpression()
				}
				return &ast.PropertyShort{
					Name: ast.Identifier{
						Name: ,
						Idx:  .Idx0(),
					},
					Initializer: ,
				}
			} else {
				.errorUnexpectedToken(.token)
			}
		case ( == "get" ||  == "set" ||  == token.ASYNC) && .token != token.COLON:
			, , ,  := .parseObjectPropertyKey()
			if  == nil {
				return nil
			}

			var  ast.PropertyKind
			var  bool
			if  == token.ASYNC {
				 = true
				 = ast.PropertyKindMethod
			} else if  == "get" {
				 = ast.PropertyKindGet
			} else {
				 = ast.PropertyKindSet
			}

			return &ast.PropertyKeyed{
				Key:      ,
				Kind:     ,
				Value:    .parseMethodDefinition(, , false, ),
				Computed:  == token.ILLEGAL,
			}
		}
	}

	.expect(token.COLON)
	return &ast.PropertyKeyed{
		Key:      ,
		Kind:     ast.PropertyKindValue,
		Value:    .parseAssignmentExpression(),
		Computed:  == token.ILLEGAL,
	}
}

func ( *_parser) ( file.Idx,  ast.PropertyKind, ,  bool) *ast.FunctionLiteral {
	 := .idx
	if  != .scope.allowYield {
		.scope.allowYield = 
		defer func() {
			.scope.allowYield = !
		}()
	}
	if  != .scope.allowAwait {
		.scope.allowAwait = 
		defer func() {
			.scope.allowAwait = !
		}()
	}
	 := .parseFunctionParameterList()
	switch  {
	case ast.PropertyKindGet:
		if len(.List) > 0 || .Rest != nil {
			.error(, "Getter must not have any formal parameters.")
		}
	case ast.PropertyKindSet:
		if len(.List) != 1 || .Rest != nil {
			.error(, "Setter must have exactly one formal parameter.")
		}
	}
	 := &ast.FunctionLiteral{
		Function:      ,
		ParameterList: ,
		Generator:     ,
		Async:         ,
	}
	.Body, .DeclarationList = .parseFunctionBlock(, , )
	.Source = .slice(, .Body.Idx1())
	return 
}

func ( *_parser) () *ast.ObjectLiteral {
	var  []ast.Property
	 := .expect(token.LEFT_BRACE)
	for .token != token.RIGHT_BRACE && .token != token.EOF {
		 := .parseObjectProperty()
		if  != nil {
			 = append(, )
		}
		if .token != token.RIGHT_BRACE {
			.expect(token.COMMA)
		} else {
			break
		}
	}
	 := .expect(token.RIGHT_BRACE)

	return &ast.ObjectLiteral{
		LeftBrace:  ,
		RightBrace: ,
		Value:      ,
	}
}

func ( *_parser) () *ast.ArrayLiteral {

	 := .expect(token.LEFT_BRACKET)
	var  []ast.Expression
	for .token != token.RIGHT_BRACKET && .token != token.EOF {
		if .token == token.COMMA {
			.next()
			 = append(, nil)
			continue
		}
		if .token == token.ELLIPSIS {
			.next()
			 = append(, &ast.SpreadElement{
				Expression: .parseAssignmentExpression(),
			})
		} else {
			 = append(, .parseAssignmentExpression())
		}
		if .token != token.RIGHT_BRACKET {
			.expect(token.COMMA)
		}
	}
	 := .expect(token.RIGHT_BRACKET)

	return &ast.ArrayLiteral{
		LeftBracket:  ,
		RightBracket: ,
		Value:        ,
	}
}

func ( *_parser) ( bool) *ast.TemplateLiteral {
	 := &ast.TemplateLiteral{
		OpenQuote: .idx,
	}
	for {
		 := .offset
		, , , ,  := .parseTemplateCharacters()
		if  != "" {
			.error(.offset, )
		}
		.Elements = append(.Elements, &ast.TemplateElement{
			Idx:     .idxOf(),
			Literal: ,
			Parsed:  ,
			Valid:    == "",
		})
		if ! &&  != "" {
			.error(.offset, )
		}
		 := .chrOffset - 1
		.next()
		if  {
			.CloseQuote = .idxOf()
			break
		}
		 := .parseExpression()
		.Expressions = append(.Expressions, )
		if .token != token.RIGHT_BRACE {
			.errorUnexpectedToken(.token)
		}
	}
	return 
}

func ( *_parser) ( ast.Expression) *ast.TemplateLiteral {
	 := .parseTemplateLiteral(true)
	.Tag = 
	return 
}

func ( *_parser) () ( []ast.Expression, ,  file.Idx) {
	 = .expect(token.LEFT_PARENTHESIS)
	for .token != token.RIGHT_PARENTHESIS {
		var  ast.Expression
		if .token == token.ELLIPSIS {
			.next()
			 = &ast.SpreadElement{
				Expression: .parseAssignmentExpression(),
			}
		} else {
			 = .parseAssignmentExpression()
		}
		 = append(, )
		if .token != token.COMMA {
			break
		}
		.next()
	}
	 = .expect(token.RIGHT_PARENTHESIS)
	return
}

func ( *_parser) ( ast.Expression) ast.Expression {
	, ,  := .parseArgumentList()
	return &ast.CallExpression{
		Callee:           ,
		LeftParenthesis:  ,
		ArgumentList:     ,
		RightParenthesis: ,
	}
}

func ( *_parser) ( ast.Expression) ast.Expression {
	 := .idx
	.next()

	 := .parsedLiteral
	 := .idx

	if .token == token.PRIVATE_IDENTIFIER {
		.next()
		return &ast.PrivateDotExpression{
			Left: ,
			Identifier: ast.PrivateIdentifier{
				Identifier: ast.Identifier{
					Idx:  ,
					Name: ,
				},
			},
		}
	}

	if !token.IsId(.token) {
		.expect(token.IDENTIFIER)
		.nextStatement()
		return &ast.BadExpression{From: , To: .idx}
	}

	.next()

	return &ast.DotExpression{
		Left: ,
		Identifier: ast.Identifier{
			Idx:  ,
			Name: ,
		},
	}
}

func ( *_parser) ( ast.Expression) ast.Expression {
	 := .expect(token.LEFT_BRACKET)
	 := .parseExpression()
	 := .expect(token.RIGHT_BRACKET)
	return &ast.BracketExpression{
		LeftBracket:  ,
		Left:         ,
		Member:       ,
		RightBracket: ,
	}
}

func ( *_parser) () ast.Expression {
	 := .expect(token.NEW)
	if .token == token.PERIOD {
		.next()
		if .literal == "target" {
			return &ast.MetaProperty{
				Meta: &ast.Identifier{
					Name: unistring.String(token.NEW.String()),
					Idx:  ,
				},
				Property: .parseIdentifier(),
			}
		}
		.errorUnexpectedToken(token.IDENTIFIER)
	}
	 := .parseLeftHandSideExpression()
	if ,  := .(*ast.BadExpression);  {
		.From = 
		return 
	}
	 := &ast.NewExpression{
		New:    ,
		Callee: ,
	}
	if .token == token.LEFT_PARENTHESIS {
		, ,  := .parseArgumentList()
		.ArgumentList = 
		.LeftParenthesis = 
		.RightParenthesis = 
	}
	return 
}

func ( *_parser) () ast.Expression {

	var  ast.Expression
	if .token == token.NEW {
		 = .parseNewExpression()
	} else {
		 = .parsePrimaryExpression()
	}
:
	for {
		switch .token {
		case token.PERIOD:
			 = .parseDotMember()
		case token.LEFT_BRACKET:
			 = .parseBracketMember()
		case token.BACKTICK:
			 = .parseTaggedTemplateLiteral()
		default:
			break 
		}
	}

	return 
}

func ( *_parser) () ast.Expression {

	 := .scope.allowIn
	.scope.allowIn = true
	defer func() {
		.scope.allowIn = 
	}()

	var  ast.Expression
	 := .idx
	if .token == token.NEW {
		 = .parseNewExpression()
	} else {
		 = .parsePrimaryExpression()
	}

	 := false
:
	for {
		switch .token {
		case token.PERIOD:
			 = .parseDotMember()
		case token.LEFT_BRACKET:
			 = .parseBracketMember()
		case token.LEFT_PARENTHESIS:
			 = .parseCallExpression()
		case token.BACKTICK:
			if  {
				.error(.idx, "Invalid template literal on optional chain")
				.nextStatement()
				return &ast.BadExpression{From: , To: .idx}
			}
			 = .parseTaggedTemplateLiteral()
		case token.QUESTION_DOT:
			 = true
			 = &ast.Optional{Expression: }

			switch .peek() {
			case token.LEFT_BRACKET, token.LEFT_PARENTHESIS, token.BACKTICK:
				.next()
			default:
				 = .parseDotMember()
			}
		default:
			break 
		}
	}

	if  {
		 = &ast.OptionalChain{Expression: }
	}
	return 
}

func ( *_parser) () ast.Expression {
	switch .token {
	case token.INCREMENT, token.DECREMENT:
		 := .token
		 := .idx
		.next()
		 := .parseUnaryExpression()
		switch .(type) {
		case *ast.Identifier, *ast.DotExpression, *ast.PrivateDotExpression, *ast.BracketExpression:
		default:
			.error(, "Invalid left-hand side in assignment")
			.nextStatement()
			return &ast.BadExpression{From: , To: .idx}
		}
		return &ast.UnaryExpression{
			Operator: ,
			Idx:      ,
			Operand:  ,
		}
	default:
		 := .parseLeftHandSideExpressionAllowCall()
		if .token == token.INCREMENT || .token == token.DECREMENT {
			// Make sure there is no line terminator here
			if .implicitSemicolon {
				return 
			}
			 := .token
			 := .idx
			.next()
			switch .(type) {
			case *ast.Identifier, *ast.DotExpression, *ast.PrivateDotExpression, *ast.BracketExpression:
			default:
				.error(, "Invalid left-hand side in assignment")
				.nextStatement()
				return &ast.BadExpression{From: , To: .idx}
			}
			return &ast.UnaryExpression{
				Operator: ,
				Idx:      ,
				Operand:  ,
				Postfix:  true,
			}
		}
		return 
	}
}

func ( *_parser) () ast.Expression {

	switch .token {
	case token.PLUS, token.MINUS, token.NOT, token.BITWISE_NOT:
		fallthrough
	case token.DELETE, token.VOID, token.TYPEOF:
		 := .token
		 := .idx
		.next()
		return &ast.UnaryExpression{
			Operator: ,
			Idx:      ,
			Operand:  .(),
		}
	case token.AWAIT:
		if .scope.allowAwait {
			 := .idx
			.next()
			if !.scope.inAsync {
				.errorUnexpectedToken(token.AWAIT)
				return &ast.BadExpression{
					From: ,
					To:   .idx,
				}
			}
			if .scope.inFuncParams {
				.error(, "Illegal await-expression in formal parameters of async function")
			}
			return &ast.AwaitExpression{
				Await:    ,
				Argument: .(),
			}
		}
	}

	return .parseUpdateExpression()
}

func ( *_parser) () ast.Expression {
	 := .token == token.LEFT_PARENTHESIS

	 := .parseUnaryExpression()

	if .token == token.EXPONENT {
		if ! {
			if ,  := .(*ast.UnaryExpression);  && .Operator != token.INCREMENT && .Operator != token.DECREMENT {
				.error(.idx, "Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence")
			}
		}
		for {
			.next()
			 = &ast.BinaryExpression{
				Operator: token.EXPONENT,
				Left:     ,
				Right:    .(),
			}
			if .token != token.EXPONENT {
				break
			}
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseExponentiationExpression()

	for .token == token.MULTIPLY || .token == token.SLASH ||
		.token == token.REMAINDER {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseExponentiationExpression(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseMultiplicativeExpression()

	for .token == token.PLUS || .token == token.MINUS {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseMultiplicativeExpression(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseAdditiveExpression()

	for .token == token.SHIFT_LEFT || .token == token.SHIFT_RIGHT ||
		.token == token.UNSIGNED_SHIFT_RIGHT {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseAdditiveExpression(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	if .scope.allowIn && .token == token.PRIVATE_IDENTIFIER {
		 := &ast.PrivateIdentifier{
			Identifier: ast.Identifier{
				Idx:  .idx,
				Name: .parsedLiteral,
			},
		}
		.next()
		if .token == token.IN {
			.next()
			return &ast.BinaryExpression{
				Operator: .token,
				Left:     ,
				Right:    .parseShiftExpression(),
			}
		}
		return 
	}
	 := .parseShiftExpression()

	 := .scope.allowIn
	.scope.allowIn = true
	defer func() {
		.scope.allowIn = 
	}()

	switch .token {
	case token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL:
		 := .token
		.next()
		return &ast.BinaryExpression{
			Operator:   ,
			Left:       ,
			Right:      .(),
			Comparison: true,
		}
	case token.INSTANCEOF:
		 := .token
		.next()
		return &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .(),
		}
	case token.IN:
		if ! {
			return 
		}
		 := .token
		.next()
		return &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseRelationalExpression()

	for .token == token.EQUAL || .token == token.NOT_EQUAL ||
		.token == token.STRICT_EQUAL || .token == token.STRICT_NOT_EQUAL {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator:   ,
			Left:       ,
			Right:      .parseRelationalExpression(),
			Comparison: true,
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseEqualityExpression()

	for .token == token.AND {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseEqualityExpression(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseBitwiseAndExpression()

	for .token == token.EXCLUSIVE_OR {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseBitwiseAndExpression(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseBitwiseExclusiveOrExpression()

	for .token == token.OR {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseBitwiseExclusiveOrExpression(),
		}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseBitwiseOrExpression()

	for .token == token.LOGICAL_AND {
		 := .token
		.next()
		 = &ast.BinaryExpression{
			Operator: ,
			Left:     ,
			Right:    .parseBitwiseOrExpression(),
		}
	}

	return 
}

func isLogicalAndExpr( ast.Expression) bool {
	if ,  := .(*ast.BinaryExpression);  && .Operator == token.LOGICAL_AND {
		return true
	}
	return false
}

func ( *_parser) () ast.Expression {
	var  file.Idx
	 := .token == token.LEFT_PARENTHESIS
	 := .parseLogicalAndExpression()

	if .token == token.LOGICAL_OR || ! && isLogicalAndExpr() {
		for {
			switch .token {
			case token.LOGICAL_OR:
				.next()
				 = &ast.BinaryExpression{
					Operator: token.LOGICAL_OR,
					Left:     ,
					Right:    .parseLogicalAndExpression(),
				}
			case token.COALESCE:
				 = .idx
				goto 
			default:
				return 
			}
		}
	} else {
		for {
			switch .token {
			case token.COALESCE:
				 = .idx
				.next()

				 := .token == token.LEFT_PARENTHESIS
				 := .parseLogicalAndExpression()
				if ! && isLogicalAndExpr() {
					goto 
				}

				 = &ast.BinaryExpression{
					Operator: token.COALESCE,
					Left:     ,
					Right:    ,
				}
			case token.LOGICAL_OR:
				 = .idx
				goto 
			default:
				return 
			}
		}
	}

:
	.error(, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses")
	return 
}

func ( *_parser) () ast.Expression {
	 := .parseLogicalOrExpression()

	if .token == token.QUESTION_MARK {
		.next()
		 := .scope.allowIn
		.scope.allowIn = true
		 := .parseAssignmentExpression()
		.scope.allowIn = 
		.expect(token.COLON)
		return &ast.ConditionalExpression{
			Test:       ,
			Consequent: ,
			Alternate:  .parseAssignmentExpression(),
		}
	}

	return 
}

func ( *_parser) ( file.Idx,  *ast.ParameterList,  bool) ast.Expression {
	.expect(token.ARROW)
	 := &ast.ArrowFunctionLiteral{
		Start:         ,
		ParameterList: ,
		Async:         ,
	}
	.Body, .DeclarationList = .parseArrowFunctionBody()
	.Source = .slice(, .Body.Idx1())
	return 
}

func ( *_parser) ( file.Idx,  bool) ast.Expression {
	if  != .scope.allowAwait {
		.scope.allowAwait = 
		defer func() {
			.scope.allowAwait = !
		}()
	}
	.tokenToBindingId()
	if .token != token.IDENTIFIER {
		.errorUnexpectedToken(.token)
		.next()
		return &ast.BadExpression{
			From: ,
			To:   .idx,
		}
	}

	 := .parseIdentifier()

	 := &ast.ParameterList{
		Opening: .Idx,
		Closing: .Idx1(),
		List: []*ast.Binding{{
			Target: ,
		}},
	}

	return .parseArrowFunction(, , )
}

func ( *_parser) () ast.Expression {
	 := .idx
	 := false
	 := false
	var  parserState
	switch .token {
	case token.LEFT_PARENTHESIS:
		.mark(&)
		 = true
	case token.ASYNC:
		 := .peek()
		if .isBindingId() {
			// async x => ...
			.next()
			return .parseSingleArgArrowFunction(, true)
		} else if  == token.LEFT_PARENTHESIS {
			.mark(&)
			 = true
		}
	case token.YIELD:
		if .scope.allowYield {
			return .parseYieldExpression()
		}
		fallthrough
	default:
		.tokenToBindingId()
	}
	 := .parseConditionalExpression()
	var  token.Token
	switch .token {
	case token.ASSIGN:
		 = .token
	case token.ADD_ASSIGN:
		 = token.PLUS
	case token.SUBTRACT_ASSIGN:
		 = token.MINUS
	case token.MULTIPLY_ASSIGN:
		 = token.MULTIPLY
	case token.EXPONENT_ASSIGN:
		 = token.EXPONENT
	case token.QUOTIENT_ASSIGN:
		 = token.SLASH
	case token.REMAINDER_ASSIGN:
		 = token.REMAINDER
	case token.AND_ASSIGN:
		 = token.AND
	case token.OR_ASSIGN:
		 = token.OR
	case token.EXCLUSIVE_OR_ASSIGN:
		 = token.EXCLUSIVE_OR
	case token.SHIFT_LEFT_ASSIGN:
		 = token.SHIFT_LEFT
	case token.SHIFT_RIGHT_ASSIGN:
		 = token.SHIFT_RIGHT
	case token.UNSIGNED_SHIFT_RIGHT_ASSIGN:
		 = token.UNSIGNED_SHIFT_RIGHT
	case token.ARROW:
		var  *ast.ParameterList
		if ,  := .(*ast.Identifier);  {
			 = &ast.ParameterList{
				Opening: .Idx,
				Closing: .Idx1() - 1,
				List: []*ast.Binding{{
					Target: ,
				}},
			}
		} else if  {
			if ,  := .(*ast.SequenceExpression);  && len(.errors) == 0 {
				 = .reinterpretSequenceAsArrowFuncParams(.Sequence)
			} else {
				.restore(&)
				 = .parseFunctionParameterList()
			}
		} else if  {
			// async (x, y) => ...
			if !.scope.allowAwait {
				.scope.allowAwait = true
				defer func() {
					.scope.allowAwait = false
				}()
			}
			if ,  := .(*ast.CallExpression);  {
				.restore(&)
				.next() // skip "async"
				 = .parseFunctionParameterList()
			}
		}
		if  == nil {
			.error(.Idx0(), "Malformed arrow function parameter list")
			return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
		}
		return .parseArrowFunction(, , )
	}

	if  != 0 {
		 := .idx
		.next()
		 := false
		switch l := .(type) {
		case *ast.Identifier, *ast.DotExpression, *ast.PrivateDotExpression, *ast.BracketExpression:
			 = true
		case *ast.ArrayLiteral:
			if ! &&  == token.ASSIGN {
				 = .reinterpretAsArrayAssignmentPattern()
				 = true
			}
		case *ast.ObjectLiteral:
			if ! &&  == token.ASSIGN {
				 = .reinterpretAsObjectAssignmentPattern()
				 = true
			}
		}
		if  {
			return &ast.AssignExpression{
				Left:     ,
				Operator: ,
				Right:    .(),
			}
		}
		.error(.Idx0(), "Invalid left-hand side in assignment")
		.nextStatement()
		return &ast.BadExpression{From: , To: .idx}
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .expect(token.YIELD)

	if .scope.inFuncParams {
		.error(, "Yield expression not allowed in formal parameter")
	}

	 := &ast.YieldExpression{
		Yield: ,
	}

	if !.implicitSemicolon && .token == token.MULTIPLY {
		.Delegate = true
		.next()
	}

	if !.implicitSemicolon && .token != token.SEMICOLON && .token != token.RIGHT_BRACE && .token != token.EOF {
		var  parserState
		.mark(&)
		 := .parseAssignmentExpression()
		if ,  := .(*ast.BadExpression);  {
			 = nil
			.restore(&)
		}
		.Argument = 
	}

	return 
}

func ( *_parser) () ast.Expression {
	 := .parseAssignmentExpression()

	if .token == token.COMMA {
		 := []ast.Expression{}
		for {
			if .token != token.COMMA {
				break
			}
			.next()
			 = append(, .parseAssignmentExpression())
		}
		return &ast.SequenceExpression{
			Sequence: ,
		}
	}

	return 
}

func ( *_parser) (,  file.Idx) {
	if  := strings.IndexByte(.str[int()-.base:int()-.base], ',');  >= 0 {
		.error(+file.Idx(), "Comma is not allowed here")
	}
}

func ( *_parser) ( *ast.ArrayLiteral) ast.Expression {
	 := .Value
	var  ast.Expression
	for ,  := range  {
		if ,  := .(*ast.SpreadElement);  {
			if  != len()-1 {
				.error(.Idx0(), "Rest element must be last element")
				return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
			}
			.checkComma(.Expression.Idx1(), .RightBracket)
			 = .reinterpretAsDestructAssignTarget(.Expression)
			 = [:len()-1]
		} else {
			[] = .reinterpretAsAssignmentElement()
		}
	}
	return &ast.ArrayPattern{
		LeftBracket:  .LeftBracket,
		RightBracket: .RightBracket,
		Elements:     ,
		Rest:         ,
	}
}

func ( *_parser) ( *ast.ArrayPattern) *ast.ArrayPattern {
	for ,  := range .Elements {
		.Elements[] = .reinterpretAsDestructBindingTarget()
	}
	if .Rest != nil {
		.Rest = .reinterpretAsDestructBindingTarget(.Rest)
	}
	return 
}

func ( *_parser) ( *ast.ArrayLiteral) ast.BindingTarget {
	 := .Value
	var  ast.Expression
	for ,  := range  {
		if ,  := .(*ast.SpreadElement);  {
			if  != len()-1 {
				.error(.Idx0(), "Rest element must be last element")
				return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
			}
			.checkComma(.Expression.Idx1(), .RightBracket)
			 = .reinterpretAsDestructBindingTarget(.Expression)
			 = [:len()-1]
		} else {
			[] = .reinterpretAsAssignmentElement()
		}
	}
	return &ast.ArrayPattern{
		LeftBracket:  .LeftBracket,
		RightBracket: .RightBracket,
		Elements:     ,
		Rest:         ,
	}
}

func ( *_parser) () ast.BindingTarget {
	return .reinterpretAsArrayBindingPattern(.parseArrayLiteral())
}

func ( *_parser) () ast.BindingTarget {
	return .reinterpretAsObjectBindingPattern(.parseObjectLiteral())
}

func ( *_parser) ( *ast.ObjectPattern) *ast.ObjectPattern {
	for ,  := range .Properties {
		if ,  := .(*ast.PropertyKeyed);  {
			.Value = .reinterpretAsBindingElement(.Value)
		}
	}
	if .Rest != nil {
		.Rest = .reinterpretAsBindingRestElement(.Rest)
	}
	return 
}

func ( *_parser) ( *ast.ObjectLiteral) ast.BindingTarget {
	var  ast.Expression
	 := .Value
	for ,  := range  {
		 := false
		switch prop := .(type) {
		case *ast.PropertyKeyed:
			if .Kind == ast.PropertyKindValue {
				.Value = .reinterpretAsBindingElement(.Value)
				 = true
			}
		case *ast.PropertyShort:
			 = true
		case *ast.SpreadElement:
			if  != len(.Value)-1 {
				.error(.Idx0(), "Rest element must be last element")
				return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
			}
			// TODO make sure there is no trailing comma
			 = .reinterpretAsBindingRestElement(.Expression)
			 = [:]
			 = true
		}
		if ! {
			.error(.Idx0(), "Invalid destructuring binding target")
			return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
		}
	}
	return &ast.ObjectPattern{
		LeftBrace:  .LeftBrace,
		RightBrace: .RightBrace,
		Properties: ,
		Rest:       ,
	}
}

func ( *_parser) ( *ast.ObjectLiteral) ast.Expression {
	var  ast.Expression
	 := .Value
	for ,  := range  {
		 := false
		switch prop := .(type) {
		case *ast.PropertyKeyed:
			if .Kind == ast.PropertyKindValue {
				.Value = .reinterpretAsAssignmentElement(.Value)
				 = true
			}
		case *ast.PropertyShort:
			 = true
		case *ast.SpreadElement:
			if  != len(.Value)-1 {
				.error(.Idx0(), "Rest element must be last element")
				return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
			}
			// TODO make sure there is no trailing comma
			 = .Expression
			 = [:]
			 = true
		}
		if ! {
			.error(.Idx0(), "Invalid destructuring assignment target")
			return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
		}
	}
	return &ast.ObjectPattern{
		LeftBrace:  .LeftBrace,
		RightBrace: .RightBrace,
		Properties: ,
		Rest:       ,
	}
}

func ( *_parser) ( ast.Expression) ast.Expression {
	switch expr := .(type) {
	case *ast.AssignExpression:
		if .Operator == token.ASSIGN {
			.Left = .reinterpretAsDestructAssignTarget(.Left)
			return 
		} else {
			.error(.Idx0(), "Invalid destructuring assignment target")
			return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
		}
	default:
		return .reinterpretAsDestructAssignTarget()
	}
}

func ( *_parser) ( ast.Expression) ast.Expression {
	switch expr := .(type) {
	case *ast.AssignExpression:
		if .Operator == token.ASSIGN {
			.Left = .reinterpretAsDestructBindingTarget(.Left)
			return 
		} else {
			.error(.Idx0(), "Invalid destructuring assignment target")
			return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
		}
	default:
		return .reinterpretAsDestructBindingTarget()
	}
}

func ( *_parser) ( ast.Expression) *ast.Binding {
	switch expr := .(type) {
	case *ast.AssignExpression:
		if .Operator == token.ASSIGN {
			return &ast.Binding{
				Target:      .reinterpretAsDestructBindingTarget(.Left),
				Initializer: .Right,
			}
		} else {
			.error(.Idx0(), "Invalid destructuring assignment target")
			return &ast.Binding{
				Target: &ast.BadExpression{From: .Idx0(), To: .Idx1()},
			}
		}
	default:
		return &ast.Binding{
			Target: .reinterpretAsDestructBindingTarget(),
		}
	}
}

func ( *_parser) ( ast.Expression) ast.Expression {
	switch item := .(type) {
	case nil:
		return nil
	case *ast.ArrayLiteral:
		return .reinterpretAsArrayAssignmentPattern()
	case *ast.ObjectLiteral:
		return .reinterpretAsObjectAssignmentPattern()
	case ast.Pattern, *ast.Identifier, *ast.DotExpression, *ast.PrivateDotExpression, *ast.BracketExpression:
		return 
	}
	.error(.Idx0(), "Invalid destructuring assignment target")
	return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
}

func ( *_parser) ( ast.Expression) ast.BindingTarget {
	switch item := .(type) {
	case nil:
		return nil
	case *ast.ArrayPattern:
		return .reinterpretArrayAssignPatternAsBinding()
	case *ast.ObjectPattern:
		return .reinterpretArrayObjectPatternAsBinding()
	case *ast.ArrayLiteral:
		return .reinterpretAsArrayBindingPattern()
	case *ast.ObjectLiteral:
		return .reinterpretAsObjectBindingPattern()
	case *ast.Identifier:
		if !.scope.allowAwait || .Name != "await" {
			return 
		}
	}
	.error(.Idx0(), "Invalid destructuring binding target")
	return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
}

func ( *_parser) ( ast.Expression) ast.Expression {
	if ,  := .(*ast.Identifier);  {
		return 
	}
	.error(.Idx0(), "Invalid binding rest")
	return &ast.BadExpression{From: .Idx0(), To: .Idx1()}
}