package parsekit // RouteTo tells the parser what StateHandler function to invoke // in the next parsing cycle. func (p *P) RouteTo(state StateHandler) *routeFollowupAction { p.nextState = state return &routeFollowupAction{p} } // RouteRepeat indicates that on the next parsing cycle, the current // StateHandler must be reinvoked. func (p *P) RouteRepeat() { p.RouteTo(p.state) } // RouteReturn tells the parser that on the next cycle the last // StateHandler that was pushed on the route stack must be invoked. // // Using this method is optional. When implementating a StateHandler that // is used as a sort of subroutine (using constructions like // p.RouteTo(subroutine).ThenReturnHere()), you can refrain from // providing an explicit routing decision from that handler. The parser will // automatically assume a RouteReturn() in that case. func (p *P) RouteReturn() { p.nextState = p.popRoute() } // routeFollowupAction chains parsing routes. // It allows for routing code like p.RouteTo(handlerA).ThenTo(handlerB). type routeFollowupAction struct { p *P } // ThenTo schedules a StateHandler that must be invoked after the RouteTo // StateHandler has been completed. // For example: // // p.RouteTo(handlerA).ThenTo(handlerB) func (a *routeFollowupAction) ThenTo(state StateHandler) { a.p.pushRoute(state) } // ThenReturnHere schedules the current StateHandler to be invoked after // the RouteTo StateHandler has been completed. // For example: // // p.RouteTo(handlerA).ThenReturnHere() func (a *routeFollowupAction) ThenReturnHere() { a.p.pushRoute(a.p.state) } // pushRoute adds the StateHandler to the route stack. // This is used for implementing nested parsing. func (p *P) pushRoute(state StateHandler) { p.routeStack = append(p.routeStack, state) } // popRoute pops the last pushed StateHandler from the route stack. func (p *P) popRoute() StateHandler { last := len(p.routeStack) - 1 head, tail := p.routeStack[:last], p.routeStack[last] p.routeStack = head return tail } // ExpectEndOfFile can be used from a StateHandler function to indicate that // your parser expects to be at the end of the file. This will schedule // a parsekit-provided StateHandler which will do the actual check for this. func (p *P) ExpectEndOfFile() { p.RouteTo(func(p *P) { p.Expects("end of file") if p.On(A.EndOfFile).Stay() { p.Emit(ItemEOF, "EOF") } }) }