package main import ( "fmt" "os" "bufio" ) type PathSegment interface {} type Path []PathSegment type TerminalValue int const ( ArrayBegin TerminalValue = iota ArrayEnd MapBegin MapEnd ) type ValueNull struct {} type ValueBool bool type ValueNumber float64 type ValueString string type WalkValue interface {} type Program []Command type ProgramState struct { space WalkItem in chan WalkItem out chan WalkItem program []Command } type StringSegmentPathFilterAST struct { index string } func (ast StringSegmentPathFilterAST) compileWith(next PathFilterState) PathFilterState { return StringSegmentPathFilter { index: ast.index, next: next, } } type RepeatPathFilterAST struct { content PathFilterAST } func (ast RepeatPathFilterAST) compileWith(next PathFilterState) PathFilterState { nextGroup := &GroupPathFilter{} repeatStart := ast.content.compileWith(nextGroup) nextGroup.filters = []PathFilterState{next, repeatStart} return nextGroup } type SequencePathFilterAST struct { sequence []PathFilterAST } func (ast SequencePathFilterAST) compileWith(next PathFilterState) PathFilterState { for i := len(ast.sequence) - 1; i >= 0; i -= 1 { next = ast.sequence[i].compileWith(next) } return next } type AnySegmentPathFilterAST struct {} func (ast AnySegmentPathFilterAST) compileWith(next PathFilterState) PathFilterState { return AnySegmentPathFilter{next: next} } type PathFilterAST interface { compileWith(PathFilterState) PathFilterState } func compilePathFilterAST(ast PathFilterAST) PathFilter { return PathFilter{ initial: ast.compileWith(NonePathFilter{}), } } func main() { if len(os.Args) < 2 { fmt.Println("Missing program arg") return } //input := os.Args[1] //tokens := Lex(input) //program := Parse(tokens) stdin := bufio.NewReader(os.Stdin) dataStream := Json(stdin) var allRemainingPathFilter AnySegmentPathFilter { g := GroupPathFilter { filters: []PathFilterState{NonePathFilter{}}, } allRemainingPathFilter = AnySegmentPathFilter { next: PathFilterState(&g), } g.filters = append(g.filters, PathFilterState(&allRemainingPathFilter)) } state := ProgramState { in: dataStream, out: make(chan WalkItem), program: []Command { FilteredCommand { filter: compilePathFilterAST( StringSegmentPathFilterAST {"people"}, ), command: PrintValueCommand{}, }, FilteredCommand { filter: compilePathFilterAST( SequencePathFilterAST { []PathFilterAST{ StringSegmentPathFilterAST {"people"}, AnySegmentPathFilterAST{}, StringSegmentPathFilterAST {"age"}, }, }, ), command: PrintValueCommand{}, }, }, } go func () { for walkItem := range dataStream { state.space = walkItem for _, cmd := range state.program { cmd.exec(&state) } } close(state.out) }() JsonOut(state.out) }