func (ps *pathScanner) init() {
	ps.step = ps.stateBeginStep
	ps.err = nil
	ps.bytes = 0
}
Initialize value of this scanner.
package expr
import (
	"fmt"
	"github.com/imulab/go-scim/pkg/v2/spec"
	"strconv"
)
func CompilePath(path string) (*Expression, error) {
	compiler := &pathCompiler{
		scan: &pathScanner{},
		data: append(copyOf(path), 0, 0),
		off:  0,
		op:   scanPathContinue,
	}
	compiler.scan.init()
	head := &Expression{}
	cursor := head
	for compiler.hasMore() {
		next, err := compiler.next()
		if err != nil {
			return nil, err
		}
		cursor.next = next
		cursor = cursor.next
	}
	cursor = head.next
	head = cursor
	return head, nil
}
type pathCompiler struct {
	scan *pathScanner
	data []byte
	off int
	op int
}
func (c *pathCompiler) hasMore() bool {
	return c.op != scanPathEnd && c.op != scanPathError
}
func (c *pathCompiler) next() (*Expression, error) {
	if c.op == scanPathError {
		return nil, c.scan.err
	}
	if c.op == scanPathContinue {
		_ = c.skipWhile(scanPathContinue)
	}
	switch c.op {
	case scanPathEnd:
		return nil, nil
	case scanPathBeginStep:
		return c.scanStep()
	case scanPathBeginFilter:
		return c.scanFilter()
	default:
		return nil, c.errCompile()
	}
}
func (c *pathCompiler) scanStep() (*Expression, error) {
	start := c.off - 1
	end := c.skipWhile(scanPathContinue)
	switch c.op {
	case scanPathEndStep, scanPathEnd:
		c.scanOne()  
		return &Expression{
			token: string(c.data[start:end]),
			typ:   path,
		}, nil
	case scanPathBeginFilter:
		return &Expression{
			token: string(c.data[start:end]),
			typ:   path,
		}, nil
	default:
		return nil, c.errCompile()
	}
}
func (c *pathCompiler) scanFilter() (*Expression, error) {
	start := c.off
	end := c.skipWhile(scanPathContinue)
	switch c.op {
	case scanPathEndFilter, scanPathEnd:
		root, err := CompileFilter(string(c.data[start:end]))
		if err != nil {
			return nil, err
		}
		c.scanOne()
		return root, nil
	default:
		return nil, c.errCompile()
	}
}
func (c *pathCompiler) scanOne() {
	c.op = c.scan.step(c.scan, c.data[c.off])
	c.off++
}
func (c *pathCompiler) skipWhile(op int) int {
	for c.off < len(c.data) {
		c.scanOne()
		if c.op != op {
			return c.off - 1
		}
	}
	return len(c.data) + 1
}
func (c *pathCompiler) errCompile() error {
	return fmt.Errorf("%w: error compiling path", spec.ErrInvalidPath)
}
const (
	scanPathContinue = iota
	scanPathBeginStep
	scanPathEndStep
	scanPathBeginFilter
	scanPathEndFilter
	scanPathError
	scanPathEnd
)
func explainPathEvent(op int) string {
	switch op {
	case scanPathContinue:
		return "continue"
	case scanPathBeginStep:
		return "begin step"
	case scanPathEndStep:
		return "end step"
	case scanPathBeginFilter:
		return "begin filter"
	case scanPathEndFilter:
		return "end filter"
	case scanPathError:
		return "error"
	case scanPathEnd:
		return "end"
	default:
		return "unknown"
	}
}
type pathScanner struct {
	step func(*pathScanner, byte) int
	err error
	bytes int64
}