func (p *parser) parseRelativeLocationPath(n node) node {
	opnd := n
Loop:
	for {
		opnd = p.parseStep(opnd)
		switch p.r.typ {
		case itemSlashSlash:
			p.next()
			opnd = newAxisNode("descendant-or-self", "", "", "", opnd)
		case itemSlash:
			p.next()
		default:
			break Loop
		}
	}
	return opnd
}
RelativeLocationPath	 ::= Step | RelativeLocationPath '/' Step | AbbreviatedRelativeLocationPath
package xpath
import (
	"bytes"
	"errors"
	"fmt"
	"strconv"
	"unicode"
)
type itemType int
const (
	itemComma      itemType = iota  
	itemSlash                       
	itemAt                          
	itemDot                         
	itemLParens                     
	itemRParens                     
	itemLBracket                    
	itemRBracket                    
	itemStar                        
	itemPlus                        
	itemMinus                       
	itemEq                          
	itemLt                          
	itemGt                          
	itemBang                        
	itemDollar                      
	itemApos                        
	itemQuote                       
	itemUnion                       
	itemNe                          
	itemLe                          
	itemGe                          
	itemAnd                         
	itemOr                          
	itemDotDot                      
	itemSlashSlash                  
	itemName                        
	itemString                      
	itemNumber                      
	itemAxe                         
	itemEOF                         
)
type node interface {
	Type() nodeType
}
type nodeType int
func (t nodeType) Type() nodeType {
	return t
}
const (
	nodeRoot nodeType = iota
	nodeAxis
	nodeFilter
	nodeFunction
	nodeOperator
	nodeVariable
	nodeConstantOperand
	nodeGroup
)
type parser struct {
	r *scanner
	d int
}
func newOperatorNode(op string, left, right node) node {
	return &operatorNode{nodeType: nodeOperator, Op: op, Left: left, Right: right}
}
func newOperandNode(v interface{}) node {
	return &operandNode{nodeType: nodeConstantOperand, Val: v}
}
func newAxisNode(axeTyp, localName, prefix, prop string, n node) node {
	return &axisNode{
		nodeType:  nodeAxis,
		LocalName: localName,
		Prefix:    prefix,
		AxeType:   axeTyp,
		Prop:      prop,
		Input:     n,
	}
}
func newVariableNode(prefix, name string) node {
	return &variableNode{nodeType: nodeVariable, Name: name, Prefix: prefix}
}
func newFilterNode(n, m node) node {
	return &filterNode{nodeType: nodeFilter, Input: n, Condition: m}
}
func newGroupNode(n node) node {
	return &groupNode{nodeType: nodeGroup, Input: n}
}
func newRootNode(s string) node {
	return &rootNode{nodeType: nodeRoot, slash: s}
}
func newFunctionNode(name, prefix string, args []node) node {
	return &functionNode{nodeType: nodeFunction, Prefix: prefix, FuncName: name, Args: args}
}
func testOp(r *scanner, op string) bool {
	return r.typ == itemName && r.prefix == "" && r.name == op
}
func isPrimaryExpr(r *scanner) bool {
	switch r.typ {
	case itemString, itemNumber, itemDollar, itemLParens:
		return true
	case itemName:
		return r.canBeFunc && !isNodeType(r)
	}
	return false
}
func isNodeType(r *scanner) bool {
	switch r.name {
	case "node", "text", "processing-instruction", "comment":
		return r.prefix == ""
	}
	return false
}
func isStep(item itemType) bool {
	switch item {
	case itemDot, itemDotDot, itemAt, itemAxe, itemStar, itemName:
		return true
	}
	return false
}
func checkItem(r *scanner, typ itemType) {
	if r.typ != typ {
		panic(fmt.Sprintf("%s has an invalid token", r.text))
	}
}
func (p *parser) parseExpression(n node) node {
	if p.d = p.d + 1; p.d > 200 {
		panic("the xpath query is too complex(depth > 200)")
	}
	n = p.parseOrExpr(n)
	p.d--
	return n
}
func (p *parser) next() bool {
	return p.r.nextItem()
}
func (p *parser) skipItem(typ itemType) {
	checkItem(p.r, typ)
	p.next()
}
func (p *parser) parseOrExpr(n node) node {
	opnd := p.parseAndExpr(n)
	for {
		if !testOp(p.r, "or") {
			break
		}
		p.next()
		opnd = newOperatorNode("or", opnd, p.parseAndExpr(n))
	}
	return opnd
}
func (p *parser) parseAndExpr(n node) node {
	opnd := p.parseEqualityExpr(n)
	for {
		if !testOp(p.r, "and") {
			break
		}
		p.next()
		opnd = newOperatorNode("and", opnd, p.parseEqualityExpr(n))
	}
	return opnd
}
func (p *parser) parseEqualityExpr(n node) node {
	opnd := p.parseRelationalExpr(n)
Loop:
	for {
		var op string
		switch p.r.typ {
		case itemEq:
			op = "="
		case itemNe:
			op = "!="
		default:
			break Loop
		}
		p.next()
		opnd = newOperatorNode(op, opnd, p.parseRelationalExpr(n))
	}
	return opnd
}
func (p *parser) parseRelationalExpr(n node) node {
	opnd := p.parseAdditiveExpr(n)
Loop:
	for {
		var op string
		switch p.r.typ {
		case itemLt:
			op = "<"
		case itemGt:
			op = ">"
		case itemLe:
			op = "<="
		case itemGe:
			op = ">="
		default:
			break Loop
		}
		p.next()
		opnd = newOperatorNode(op, opnd, p.parseAdditiveExpr(n))
	}
	return opnd
}
func (p *parser) parseAdditiveExpr(n node) node {
	opnd := p.parseMultiplicativeExpr(n)
Loop:
	for {
		var op string
		switch p.r.typ {
		case itemPlus:
			op = "+"
		case itemMinus:
			op = "-"
		default:
			break Loop
		}
		p.next()
		opnd = newOperatorNode(op, opnd, p.parseMultiplicativeExpr(n))
	}
	return opnd
}
func (p *parser) parseMultiplicativeExpr(n node) node {
	opnd := p.parseUnaryExpr(n)
Loop:
	for {
		var op string
		if p.r.typ == itemStar {
			op = "*"
		} else if testOp(p.r, "div") || testOp(p.r, "mod") {
			op = p.r.name
		} else {
			break Loop
		}
		p.next()
		opnd = newOperatorNode(op, opnd, p.parseUnaryExpr(n))
	}
	return opnd
}
func (p *parser) parseUnaryExpr(n node) node {
	minus := false
	for p.r.typ == itemMinus {
		p.next()
		minus = !minus
	}
	opnd := p.parseUnionExpr(n)
	if minus {
		opnd = newOperatorNode("*", opnd, newOperandNode(float64(-1)))
	}
	return opnd
}
func (p *parser) parseUnionExpr(n node) node {
	opnd := p.parsePathExpr(n)
Loop:
	for {
		if p.r.typ != itemUnion {
			break Loop
		}
		p.next()
		opnd2 := p.parsePathExpr(n)
		opnd = newOperatorNode("|", opnd, opnd2)
	}
	return opnd
}
func (p *parser) parsePathExpr(n node) node {
	var opnd node
	if isPrimaryExpr(p.r) {
		opnd = p.parseFilterExpr(n)
		switch p.r.typ {
		case itemSlash:
			p.next()
			opnd = p.parseRelativeLocationPath(opnd)
		case itemSlashSlash:
			p.next()
			opnd = p.parseRelativeLocationPath(newAxisNode("descendant-or-self", "", "", "", opnd))
		}
	} else {
		opnd = p.parseLocationPath(nil)
	}
	return opnd
}
func (p *parser) parseFilterExpr(n node) node {
	opnd := p.parsePrimaryExpr(n)
	if p.r.typ == itemLBracket {
		opnd = newFilterNode(opnd, p.parsePredicate(opnd))
	}
	return opnd
}
func (p *parser) parsePredicate(n node) node {
	p.skipItem(itemLBracket)
	opnd := p.parseExpression(n)
	p.skipItem(itemRBracket)
	return opnd
}
func (p *parser) parseLocationPath(n node) (opnd node) {
	switch p.r.typ {
	case itemSlash:
		p.next()
		opnd = newRootNode("/")
		if isStep(p.r.typ) {
			opnd = p.parseRelativeLocationPath(opnd)  
		}
	case itemSlashSlash:
		p.next()
		opnd = newRootNode("//")
		opnd = p.parseRelativeLocationPath(newAxisNode("descendant-or-self", "", "", "", opnd))
	default:
		opnd = p.parseRelativeLocationPath(n)
	}
	return opnd
}