package parsekit // RouteRepeat indicates that on the next parsing cycle, // the current StateHandler must be invoked again. func (p *P) RouteRepeat() { p.RouteTo(p.state) } // RouteTo tells the parser what StateHandler function to invoke // in the next parsing cycle. func (p *P) RouteTo(state StateHandler) *RouteFollowup { p.nextState = state return &RouteFollowup{p} } // RouteFollowup chains parsing routes. // It allows for routing code like p.RouteTo(handlerA).ThenTo(handlerB). type RouteFollowup 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 (r *RouteFollowup) ThenTo(state StateHandler) { r.p.pushState(state) } // ThenReturnHere schedules the current StateHandler to be // invoked after the RouteTo StateHandler has been completed. // For example: p.RouteTo(handlerA).ThenReturnHere() func (r *RouteFollowup) ThenReturnHere() { r.p.pushState(r.p.state) } // RouteReturn tells the parser that on the next cycle the // next scheduled route 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()), // then you can refrain from providing a routing decision // from that handler. The parser will automatically assume // a RouteReturn in that case. func (p *P) RouteReturn() { p.nextState = p.popState() } // PushState adds the state function to the state stack. // This is used for implementing nested parsing. func (p *P) pushState(state StateHandler) { p.stack = append(p.stack, state) } // PopState pops the last pushed state from the state stack. func (p *P) popState() StateHandler { last := len(p.stack) - 1 head, tail := p.stack[:last], p.stack[last] p.stack = head return tail }