package jmespath

import (
	
	
	
	
)

type astNodeType int
ASTNode represents the abstract syntax tree of a JMESPath expression.
type ASTNode struct {
	nodeType astNodeType
	value    interface{}
	children []ASTNode
}

func ( ASTNode) () string {
	return .PrettyPrint(0)
}
PrettyPrint will pretty print the parsed AST. The AST is an implementation detail and this pretty print function is provided as a convenience method to help with debugging. You should not rely on its output as the internal structure of the AST may change at any time.
func ( ASTNode) ( int) string {
	 := strings.Repeat(" ", )
	 := fmt.Sprintf("%s%s {\n", , .nodeType)
	 :=  + 2
	if .value != nil {
Account for things like comparator nodes that are enums with a String() method.
			 += fmt.Sprintf("%svalue: %s\n", strings.Repeat(" ", ), .String())
		} else {
			 += fmt.Sprintf("%svalue: %#v\n", strings.Repeat(" ", ), .value)
		}
	}
	 := len(.children)
	if  > 0 {
		 += fmt.Sprintf("%schildren: {\n", strings.Repeat(" ", ))
		 :=  + 2
		for ,  := range .children {
			 += .()
		}
	}
	 += fmt.Sprintf("%s}\n", )
	return 
}

var bindingPowers = map[tokType]int{
	tEOF:                0,
	tUnquotedIdentifier: 0,
	tQuotedIdentifier:   0,
	tRbracket:           0,
	tRparen:             0,
	tComma:              0,
	tRbrace:             0,
	tNumber:             0,
	tCurrent:            0,
	tExpref:             0,
	tColon:              0,
	tPipe:               1,
	tOr:                 2,
	tAnd:                3,
	tEQ:                 5,
	tLT:                 5,
	tLTE:                5,
	tGT:                 5,
	tGTE:                5,
	tNE:                 5,
	tFlatten:            9,
	tStar:               20,
	tFilter:             21,
	tDot:                40,
	tNot:                45,
	tLbrace:             50,
	tLbracket:           55,
	tLparen:             60,
}
Parser holds state about the current expression being parsed.
NewParser creates a new JMESPath parser.
func () *Parser {
	 := Parser{}
	return &
}
Parse will compile a JMESPath expression.
func ( *Parser) ( string) (ASTNode, error) {
	 := NewLexer()
	.expression = 
	.index = 0
	,  := .tokenize()
	if  != nil {
		return ASTNode{}, 
	}
	.tokens = 
	,  := .parseExpression(0)
	if  != nil {
		return ASTNode{}, 
	}
	if .current() != tEOF {
		return ASTNode{}, .syntaxError(fmt.Sprintf(
			"Unexpected token at the end of the expression: %s", .current()))
	}
	return , nil
}

func ( *Parser) ( int) (ASTNode, error) {
	var  error
	 := .lookaheadToken(0)
	.advance()
	,  := .nud()
	if  != nil {
		return ASTNode{}, 
	}
	 := .current()
	for  < bindingPowers[] {
		.advance()
		,  = .led(, )
		if  != nil {
			return ASTNode{}, 
		}
		 = .current()
	}
	return , nil
}

func ( *Parser) () (ASTNode, error) {
	if .lookahead(0) == tColon || .lookahead(1) == tColon {
		return .parseSliceExpression()
	}
	 := .lookaheadToken(0).value
	,  := strconv.Atoi()
	if  != nil {
		return ASTNode{}, 
	}
	 := ASTNode{nodeType: ASTIndex, value: }
	.advance()
	if  := .match(tRbracket);  != nil {
		return ASTNode{}, 
	}
	return , nil
}

func ( *Parser) () (ASTNode, error) {
	 := []*int{nil, nil, nil}
	 := 0
	 := .current()
	for  != tRbracket &&  < 3 {
		if  == tColon {
			++
			.advance()
		} else if  == tNumber {
			,  := strconv.Atoi(.lookaheadToken(0).value)
			if  != nil {
				return ASTNode{}, 
			}
			[] = &
			.advance()
		} else {
			return ASTNode{}, .syntaxError(
				"Expected tColon or tNumber" + ", received: " + .current().String())
		}
		 = .current()
	}
	if  := .match(tRbracket);  != nil {
		return ASTNode{}, 
	}
	return ASTNode{
		nodeType: ASTSlice,
		value:    ,
	}, nil
}

func ( *Parser) ( tokType) error {
	if .current() ==  {
		.advance()
		return nil
	}
	return .syntaxError("Expected " + .String() + ", received: " + .current().String())
}

func ( *Parser) ( tokType,  ASTNode) (ASTNode, error) {
	switch  {
	case tDot:
		if .current() != tStar {
			,  := .parseDotRHS(bindingPowers[tDot])
			return ASTNode{
				nodeType: ASTSubexpression,
				children: []ASTNode{, },
			}, 
		}
		.advance()
		,  := .parseProjectionRHS(bindingPowers[tDot])
		return ASTNode{
			nodeType: ASTValueProjection,
			children: []ASTNode{, },
		}, 
	case tPipe:
		,  := .parseExpression(bindingPowers[tPipe])
		return ASTNode{nodeType: ASTPipe, children: []ASTNode{, }}, 
	case tOr:
		,  := .parseExpression(bindingPowers[tOr])
		return ASTNode{nodeType: ASTOrExpression, children: []ASTNode{, }}, 
	case tAnd:
		,  := .parseExpression(bindingPowers[tAnd])
		return ASTNode{nodeType: ASTAndExpression, children: []ASTNode{, }}, 
	case tLparen:
		 := .value
		var  []ASTNode
		for .current() != tRparen {
			,  := .parseExpression(0)
			if  != nil {
				return ASTNode{}, 
			}
			if .current() == tComma {
				if  := .match(tComma);  != nil {
					return ASTNode{}, 
				}
			}
			 = append(, )
		}
		if  := .match(tRparen);  != nil {
			return ASTNode{}, 
		}
		return ASTNode{
			nodeType: ASTFunctionExpression,
			value:    ,
			children: ,
		}, nil
	case tFilter:
		return .parseFilter()
	case tFlatten:
		 := ASTNode{nodeType: ASTFlatten, children: []ASTNode{}}
		,  := .parseProjectionRHS(bindingPowers[tFlatten])
		return ASTNode{
			nodeType: ASTProjection,
			children: []ASTNode{, },
		}, 
	case tEQ, tNE, tGT, tGTE, tLT, tLTE:
		,  := .parseExpression(bindingPowers[])
		if  != nil {
			return ASTNode{}, 
		}
		return ASTNode{
			nodeType: ASTComparator,
			value:    ,
			children: []ASTNode{, },
		}, nil
	case tLbracket:
		 := .current()
		var  ASTNode
		var  error
		if  == tNumber ||  == tColon {
			,  = .parseIndexExpression()
			if  != nil {
				return ASTNode{}, 
			}
			return .projectIfSlice(, )
Otherwise this is a projection.
		if  := .match(tStar);  != nil {
			return ASTNode{}, 
		}
		if  := .match(tRbracket);  != nil {
			return ASTNode{}, 
		}
		,  = .parseProjectionRHS(bindingPowers[tStar])
		if  != nil {
			return ASTNode{}, 
		}
		return ASTNode{
			nodeType: ASTProjection,
			children: []ASTNode{, },
		}, nil
	}
	return ASTNode{}, .syntaxError("Unexpected token: " + .String())
}

func ( *Parser) ( token) (ASTNode, error) {
	switch .tokenType {
	case tJSONLiteral:
		var  interface{}
		 := json.Unmarshal([]byte(.value), &)
		if  != nil {
			return ASTNode{}, 
		}
		return ASTNode{nodeType: ASTLiteral, value: }, nil
	case tStringLiteral:
		return ASTNode{nodeType: ASTLiteral, value: .value}, nil
	case tUnquotedIdentifier:
		return ASTNode{
			nodeType: ASTField,
			value:    .value,
		}, nil
	case tQuotedIdentifier:
		 := ASTNode{nodeType: ASTField, value: .value}
		if .current() == tLparen {
			return ASTNode{}, .syntaxErrorToken("Can't have quoted identifier as function name.", )
		}
		return , nil
	case tStar:
		 := ASTNode{nodeType: ASTIdentity}
		var  ASTNode
		var  error
		if .current() == tRbracket {
			 = ASTNode{nodeType: ASTIdentity}
		} else {
			,  = .parseProjectionRHS(bindingPowers[tStar])
		}
		return ASTNode{nodeType: ASTValueProjection, children: []ASTNode{, }}, 
	case tFilter:
		return .parseFilter(ASTNode{nodeType: ASTIdentity})
	case tLbrace:
		return .parseMultiSelectHash()
	case tFlatten:
		 := ASTNode{
			nodeType: ASTFlatten,
			children: []ASTNode{{nodeType: ASTIdentity}},
		}
		,  := .parseProjectionRHS(bindingPowers[tFlatten])
		if  != nil {
			return ASTNode{}, 
		}
		return ASTNode{nodeType: ASTProjection, children: []ASTNode{, }}, nil
	case tLbracket:
var right ASTNode
		if  == tNumber ||  == tColon {
			,  := .parseIndexExpression()
			if  != nil {
				return ASTNode{}, nil
			}
			return .projectIfSlice(ASTNode{nodeType: ASTIdentity}, )
		} else if  == tStar && .lookahead(1) == tRbracket {
			.advance()
			.advance()
			,  := .parseProjectionRHS(bindingPowers[tStar])
			if  != nil {
				return ASTNode{}, 
			}
			return ASTNode{
				nodeType: ASTProjection,
				children: []ASTNode{{nodeType: ASTIdentity}, },
			}, nil
		} else {
			return .parseMultiSelectList()
		}
	case tCurrent:
		return ASTNode{nodeType: ASTCurrentNode}, nil
	case tExpref:
		,  := .parseExpression(bindingPowers[tExpref])
		if  != nil {
			return ASTNode{}, 
		}
		return ASTNode{nodeType: ASTExpRef, children: []ASTNode{}}, nil
	case tNot:
		,  := .parseExpression(bindingPowers[tNot])
		if  != nil {
			return ASTNode{}, 
		}
		return ASTNode{nodeType: ASTNotExpression, children: []ASTNode{}}, nil
	case tLparen:
		,  := .parseExpression(0)
		if  != nil {
			return ASTNode{}, 
		}
		if  := .match(tRparen);  != nil {
			return ASTNode{}, 
		}
		return , nil
	case tEOF:
		return ASTNode{}, .syntaxErrorToken("Incomplete expression", )
	}

	return ASTNode{}, .syntaxErrorToken("Invalid token: "+.tokenType.String(), )
}

func ( *Parser) () (ASTNode, error) {
	var  []ASTNode
	for {
		,  := .parseExpression(0)
		if  != nil {
			return ASTNode{}, 
		}
		 = append(, )
		if .current() == tRbracket {
			break
		}
		 = .match(tComma)
		if  != nil {
			return ASTNode{}, 
		}
	}
	 := .match(tRbracket)
	if  != nil {
		return ASTNode{}, 
	}
	return ASTNode{
		nodeType: ASTMultiSelectList,
		children: ,
	}, nil
}

func ( *Parser) () (ASTNode, error) {
	var  []ASTNode
	for {
		 := .lookaheadToken(0)
		if  := .match(tUnquotedIdentifier);  != nil {
			if  := .match(tQuotedIdentifier);  != nil {
				return ASTNode{}, .syntaxError("Expected tQuotedIdentifier or tUnquotedIdentifier")
			}
		}
		 := .value
		 := .match(tColon)
		if  != nil {
			return ASTNode{}, 
		}
		,  := .parseExpression(0)
		if  != nil {
			return ASTNode{}, 
		}
		 := ASTNode{
			nodeType: ASTKeyValPair,
			value:    ,
			children: []ASTNode{},
		}
		 = append(, )
		if .current() == tComma {
			 := .match(tComma)
			if  != nil {
				return ASTNode{}, nil
			}
		} else if .current() == tRbrace {
			 := .match(tRbrace)
			if  != nil {
				return ASTNode{}, nil
			}
			break
		}
	}
	return ASTNode{
		nodeType: ASTMultiSelectHash,
		children: ,
	}, nil
}

func ( *Parser) ( ASTNode,  ASTNode) (ASTNode, error) {
	 := ASTNode{
		nodeType: ASTIndexExpression,
		children: []ASTNode{, },
	}
	if .nodeType == ASTSlice {
		,  := .parseProjectionRHS(bindingPowers[tStar])
		return ASTNode{
			nodeType: ASTProjection,
			children: []ASTNode{, },
		}, 
	}
	return , nil
}
func ( *Parser) ( ASTNode) (ASTNode, error) {
	var ,  ASTNode
	var  error
	,  = .parseExpression(0)
	if  != nil {
		return ASTNode{}, 
	}
	if  := .match(tRbracket);  != nil {
		return ASTNode{}, 
	}
	if .current() == tFlatten {
		 = ASTNode{nodeType: ASTIdentity}
	} else {
		,  = .parseProjectionRHS(bindingPowers[tFilter])
		if  != nil {
			return ASTNode{}, 
		}
	}

	return ASTNode{
		nodeType: ASTFilterProjection,
		children: []ASTNode{, , },
	}, nil
}

func ( *Parser) ( int) (ASTNode, error) {
	 := .current()
	if tokensOneOf([]tokType{tQuotedIdentifier, tUnquotedIdentifier, tStar}, ) {
		return .parseExpression()
	} else if  == tLbracket {
		if  := .match(tLbracket);  != nil {
			return ASTNode{}, 
		}
		return .parseMultiSelectList()
	} else if  == tLbrace {
		if  := .match(tLbrace);  != nil {
			return ASTNode{}, 
		}
		return .parseMultiSelectHash()
	}
	return ASTNode{}, .syntaxError("Expected identifier, lbracket, or lbrace")
}

func ( *Parser) ( int) (ASTNode, error) {
	 := .current()
	if bindingPowers[] < 10 {
		return ASTNode{nodeType: ASTIdentity}, nil
	} else if  == tLbracket {
		return .parseExpression()
	} else if  == tFilter {
		return .parseExpression()
	} else if  == tDot {
		 := .match(tDot)
		if  != nil {
			return ASTNode{}, 
		}
		return .parseDotRHS()
	} else {
		return ASTNode{}, .syntaxError("Error")
	}
}

func ( *Parser) ( int) tokType {
	return .lookaheadToken().tokenType
}

func ( *Parser) () tokType {
	return .lookahead(0)
}

func ( *Parser) ( int) token {
	return .tokens[.index+]
}

func ( *Parser) () {
	.index++
}

func ( []tokType,  tokType) bool {
	for ,  := range  {
		if  ==  {
			return true
		}
	}
	return false
}

func ( *Parser) ( string) SyntaxError {
	return SyntaxError{
		msg:        ,
		Expression: .expression,
		Offset:     .lookaheadToken(0).position,
	}
}
Create a SyntaxError based on the provided token. This differs from syntaxError() which creates a SyntaxError based on the current lookahead token.