func (c *filterCompiler) scanOperatorOrPath() (*Expression, error) {
	start := c.off - 1
	end := c.scanWhile(scanFilterContinue)
	switch c.op {
	case scanFilterEndPath:
		return newPath(string(c.data[start:end])), nil
	case scanFilterEndOp:
		return newOperator(string(c.data[start:end])), nil
	default:
		return nil, c.errCompile()
	}
}
Produce a path or operator node from the current offset. This fits the case where we read 'n' at the start of the
predicate, we are not quite sure whether it is going to be 'not' and just another path with prefix 'n'. This should
only be called when scanFilterBeginAny is returned as op code.
package expr
import (
	"fmt"
	"github.com/imulab/go-scim/pkg/v2/spec"
	"strings"
)
func CompileFilter(filter string) (*Expression, error) {
	compiler := &filterCompiler{
		scan:    &filterScanner{},
		data:    append(copyOf(filter), 0, 0),
		off:     0,
		op:      scanFilterSkipSpace,
		opStack: make([]*Expression, 0),
		rsStack: make([]*Expression, 0),
	}
	compiler.scan.init()
	for compiler.hasMore() {
		step, err := compiler.next()
		if err != nil {
			return nil, err
		}
		if step == nil {
			break
		}
		if step.IsLiteral() || step.IsPath() {
			if err := compiler.pushBuildResult(step); err != nil {
				return nil, err
			}
			continue
		}
		switch compiler.pushOperator(step) {
		case pushOpOk:
			break
		case pushOpRightParenthesis:
			for {
				popped := compiler.popOperatorIf(func(top *Expression) bool {
					return !top.IsLeftParenthesis()
				})
				if popped != nil {
					_ = compiler.pushBuildResult(popped)
				} else {
					break
				}
			}
			if len(compiler.opStack) == 0 {
				return nil, fmt.Errorf("%w: mismatched parenthesis", spec.ErrInvalidFilter)
			} else {
				compiler.opStack = compiler.opStack[:len(compiler.opStack)-1]
			}
			break
		case pushOpInsufficientPriority:
			minPriority := opPriority(step.token)
			for {
				popped := compiler.popOperatorIf(func(top *Expression) bool {
					return opPriority(top.token) >= minPriority
				})
				if popped != nil {
					_ = compiler.pushBuildResult(popped)
				} else {
					break
				}
			}
			if compiler.pushOperator(step) != pushOpOk {
				panic("flaw in algorithm")
			}
			break
		}
	}
	for len(compiler.opStack) > 0 {
		_ = compiler.pushBuildResult(compiler.popOperatorIf(func(top *Expression) bool {
			return true
		}))
	}
	if len(compiler.rsStack) != 1 || !compiler.rsStack[0].IsOperator() {
		panic("flaw in algorithm")
	}
	root := compiler.rsStack[0]
	compiler.rsStack = nil
	return root, nil
}
var (
	opPriority = func(op string) int {
		switch strings.ToLower(op) {
		case And, Or, Not:
			return 50
		case Eq, Ne, Sw, Ew, Co, Pr, Gt, Ge, Lt, Le:
			return 100
		default:
			panic("not an operator")
		}
	}
	opLeftAssociative = func(op string) bool {
		switch strings.ToLower(op) {
		case Not:
			return false
		case And, Or, Eq, Ne, Sw, Ew, Co, Pr, Gt, Ge, Lt, Le:
			return true
		default:
			panic("not an operator")
		}
	}
	opCardinality = func(op string) int {
		switch op {
		case Not, Pr:
			return 1
		case And, Or, Eq, Ne, Sw, Ew, Co, Gt, Ge, Lt, Le:
			return 2
		default:
			panic("not an operator")
		}
	}
)
type filterCompiler struct {
	scan *filterScanner
	data []byte
	off int
	op int
	opStack []*Expression
	rsStack []*Expression
}
func (c *filterCompiler) pushOperator(step *Expression) int {
	if step.IsRightParenthesis() {
		return pushOpRightParenthesis
	}
	if step.IsOperator() && len(c.opStack) > 0 {
		p := c.opStack[len(c.opStack)-1]
		if p.IsOperator() {
			if opLeftAssociative(step.token) && opPriority(step.token) <= opPriority(p.token) {
				return pushOpInsufficientPriority
			} else if opLeftAssociative(step.token) && opPriority(step.token) < opPriority(p.token) {
				return pushOpInsufficientPriority
			}
		}
	}
	c.opStack = append(c.opStack, step)
	return pushOpOk
}
func (c *filterCompiler) popOperatorIf(condition func(top *Expression) bool) *Expression {
	if len(c.opStack) == 0 {
		return nil
	}
	top := c.opStack[len(c.opStack)-1]
	if condition(top) {
		c.opStack = c.opStack[0 : len(c.opStack)-1]
		return top
	}
	return nil
}
func (c *filterCompiler) pushBuildResult(step *Expression) error {
	if step.IsLiteral() {
		c.rsStack = append(c.rsStack, step)
		return nil
	}
	if step.IsPath() {
		head, err := CompilePath(step.token)
		if err != nil {
			return fmt.Errorf("%w: invalid path in filter", spec.ErrInvalidFilter)
		} else if head.ContainsFilter() {
			return fmt.Errorf("%w: illegal nested filter", spec.ErrInvalidFilter)
		}
		c.rsStack = append(c.rsStack, head)
		return nil
	}
	if !step.IsOperator() || len(c.rsStack) == 0 {
		panic("algorithm flaw")
	}
	switch opCardinality(step.token) {
	case 1:
		{
			first := c.rsStack[len(c.rsStack)-1]
			c.rsStack = c.rsStack[:len(c.rsStack)-1]
			step.left = first
		}
	case 2:
		{
			first, second := c.rsStack[len(c.rsStack)-1], c.rsStack[len(c.rsStack)-2]
			c.rsStack = c.rsStack[:len(c.rsStack)-2]
			step.left = second
			step.right = first
		}
	default:
		panic("unsupported cardinality")
	}
	c.rsStack = append(c.rsStack, step)
	return nil
}
func (c *filterCompiler) hasMore() bool {
	return c.op != scanFilterEnd && c.op != scanFilterError
}
func (c *filterCompiler) next() (*Expression, error) {
	if c.op == scanFilterError {
		return nil, c.scan.err
	}
	_ = c.scanWhile(scanFilterSkipSpace)
	switch c.op {
	case scanFilterEnd:
		return nil, nil
	case scanFilterParenthesis:
		return newParenthesis(string(c.data[c.off-1])), nil
	case scanFilterBeginAny:
		return c.scanOperatorOrPath()
	case scanFilterBeginPath:
		return c.scanPath()
	case scanFilterBeginOp:
		return c.scanOperator()
	case scanFilterBeginLiteral:
		return c.scanLiteral()
	default:
		return nil, c.errCompile()
	}
}
func (c *filterCompiler) scanLiteral() (*Expression, error) {
	start := c.off - 1
	end := c.scanWhile(scanFilterContinue)
	switch c.op {
	case scanFilterEndLiteral, scanFilterEnd:
		return newLiteral(string(c.data[start:end])), nil
	default:
		return nil, c.errCompile()
	}
}
func (c *filterCompiler) scanOperator() (*Expression, error) {
	start := c.off - 1
	end := c.scanWhile(scanFilterContinue)
	switch c.op {
	case scanFilterEndOp, scanFilterEnd:
		return newOperator(string(c.data[start:end])), nil
	default:
		return nil, c.errCompile()
	}
}
func (c *filterCompiler) scanPath() (*Expression, error) {
	start := c.off - 1
	end := c.scanWhile(scanFilterContinue)
	switch c.op {
	case scanFilterEndPath, scanFilterEnd:
		return newPath(string(c.data[start:end])), nil
	default:
		return nil, c.errCompile()
	}
}