package main import ( "main/walk" ) type PathFilter struct { initial PathFilterState } func (filter PathFilter) exec(space walk.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 walk.WalkItem) bool { terminal, isTerminal := space.Value.(walk.TerminalValue) if !isTerminal { return false } return terminal == walk.MapBegin || terminal == walk.MapEnd } type BeginTerminalFilter struct {} func (filter BeginTerminalFilter) exec(space walk.WalkItem) bool { terminal, isTerminal := space.Value.(walk.TerminalValue) if !isTerminal { return false } return terminal == walk.ArrayBegin || terminal == walk.MapBegin } type EndTerminalFilter struct {} func (filter EndTerminalFilter) exec(space walk.WalkItem) bool { terminal, isTerminal := space.Value.(walk.TerminalValue) if !isTerminal { return false } return terminal == walk.ArrayEnd || terminal == walk.MapEnd } type TerminalFilter struct {} func (filter TerminalFilter) exec(space walk.WalkItem) bool { _, isTerminal := space.Value.(walk.TerminalValue) return isTerminal } type RootFilter struct {} func (filter RootFilter) exec(space walk.WalkItem) bool { return len(space.Path) == 0 } type AndFilter struct { left Filter right Filter } func (filter AndFilter) exec(space walk.WalkItem) bool { return filter.left.exec(space) && filter.right.exec(space) } type OrFilter struct { left Filter right Filter } func (filter OrFilter) exec(space walk.WalkItem) bool { return filter.left.exec(space) || filter.right.exec(space) } type NotFilter struct { content Filter } func (filter NotFilter) exec(space walk.WalkItem) bool { return !filter.content.exec(space) } type Filter interface { exec(walk.WalkItem) bool }