package main type MapTerminalFilter struct {} func (filter MapTerminalFilter) exec(state *ProgramState) bool { terminal, isTerminal := state.space.value.(TerminalValue) if !isTerminal { return false } return terminal == MapBegin || terminal == MapEnd } type NonTerminalFilter struct {} func (filter NonTerminalFilter) exec(state *ProgramState) bool { _, isTerminal := state.space.value.(TerminalValue) return !isTerminal } type AnySegmentPathFilter struct { next PathFilterState } func (filter AnySegmentPathFilter) eat(segment PathSegment) map[PathFilterState]struct{} { res := make(map[PathFilterState]struct{}) res[filter.next] = struct{}{} return res } func (filter AnySegmentPathFilter) accept() bool { return false } type GroupPathFilter struct { filters []PathFilterState } func (filter GroupPathFilter) eat(segment PathSegment) map[PathFilterState]struct{} { res := make(map[PathFilterState]struct{}) for _, f := range filter.filters { for r := range f.eat(segment) { res[r] = struct{}{} } } return res } func (filter GroupPathFilter) accept() bool { for _, f := range filter.filters { if f.accept() { return true } } return false } type NonePathFilter struct {} func (filter NonePathFilter) eat(segment PathSegment) map[PathFilterState]struct{} { return make(map[PathFilterState]struct{}) } func (filter NonePathFilter) accept() bool { return true } type StringSegmentPathFilter struct { index string next PathFilterState } func (filter StringSegmentPathFilter) eat(segment PathSegment) map[PathFilterState]struct{} { s, isString := segment.(string) res := make(map[PathFilterState]struct{}) if isString && s == filter.index { res[filter.next] = struct{}{} } return res } func (filter StringSegmentPathFilter) accept() bool { return false } type PathFilterState interface { eat(PathSegment) map[PathFilterState]struct{} accept() bool }