package parsekit // RouteTo tells the parser what StateHandler function to invoke on // the next parse cycle. func (p *ParseAPI) RouteTo(state StateHandler) *RouteFollowupAction { p.nextState = state return &RouteFollowupAction{p} } // RouteRepeat tells the parser that on the next parsing cycle, the current // StateHandler must be reinvoked. func (p *ParseAPI) 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 *ParseAPI) RouteReturn() { p.nextState = p.popRoute() } // RouteFollowupAction chains parsing routes. // It allows for routing code like p.RouteTo(handlerA).ThenTo(handlerB). type RouteFollowupAction struct { p *ParseAPI } // 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 *ParseAPI) pushRoute(state StateHandler) { p.routeStack = append(p.routeStack, state) } // popRoute pops the last pushed StateHandler from the route stack. func (p *ParseAPI) 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 *ParseAPI) ExpectEndOfFile() { p.RouteTo(func(p *ParseAPI) { p.Expects("end of file") if p.On(A.EndOfFile).Stay() { p.Emit(ItemEOF, "EOF") } }) }