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 NonTerminalFilter struct {} func (filter NonTerminalFilter) exec(space WalkItem) bool { _, isTerminal := space.value.(TerminalValue) return !isTerminal } type RangeFilter struct { start Filter end Filter active bool } func (filter *RangeFilter) exec(space WalkItem) bool { if filter.active { if filter.end.exec(space) { filter.active = false } return true } else { if filter.start.exec(space) { filter.active = true } return filter.active } } 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 Filter interface { exec(WalkItem) bool }