77 lines
2.3 KiB
Go
77 lines
2.3 KiB
Go
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")
|
|
}
|
|
})
|
|
}
|