package main type PathFilter struct { initial PathFilterState } func (filter PathFilter) exec(space WalkItem) bool { pathFilterState := make(map[PathFilterState]struct{}) pathFilterState[filter.initial] = struct{}{} for _, segment := range space.path { nextPathFilterState := make(map[PathFilterState]struct{}) for curState := range pathFilterState { for nextState := range curState.eat(segment) { nextPathFilterState[nextState] = struct{}{} } } pathFilterState = nextPathFilterState } for pathState := range pathFilterState { if pathState.accept() { return true } } return false } type MapTerminalFilter struct {} func (filter MapTerminalFilter) exec(space WalkItem) bool { terminal, isTerminal := space.value.(TerminalValue) if !isTerminal { return false } return terminal == MapBegin || terminal == MapEnd } type BeginTerminalFilter struct {} func (filter BeginTerminalFilter) exec(space WalkItem) bool { terminal, isTerminal := space.value.(TerminalValue) if !isTerminal { return false } return terminal == ArrayBegin || terminal == MapBegin } type EndTerminalFilter struct {} func (filter EndTerminalFilter) exec(space WalkItem) bool { terminal, isTerminal := space.value.(TerminalValue) if !isTerminal { return false } return terminal == ArrayEnd || terminal == MapEnd } type TerminalFilter struct {} func (filter TerminalFilter) exec(space WalkItem) bool { _, isTerminal := space.value.(TerminalValue) return isTerminal } type RootFilter struct {} func (filter RootFilter) exec(space WalkItem) bool { return len(space.path) == 0 } type AndFilter struct { left Filter right Filter } func (filter AndFilter) exec(space WalkItem) bool { return filter.left.exec(space) && filter.right.exec(space) } type NotFilter struct { content Filter } func (filter NotFilter) exec(space WalkItem) bool { return !filter.content.exec(space) } type Filter interface { exec(WalkItem) bool }