go-parsekit/parsehandler_route.go

136 lines
3.9 KiB
Go

package parsekit
// Handle is used to execute other ParseHandler functions from within your
// ParseHandler function.
func (p *ParseAPI) Handle(handlers ...ParseHandler) {
for _, handler := range handlers {
// When some previous parsing step yielded an error, skip this operation.
if p.err != nil || p.stopped {
break
}
handler(p)
}
}
// RouteTo tells the parser what ParseHandler function to invoke on
// the next parse cycle.
// Deprecated
func (p *ParseAPI) RouteTo(handler ParseHandler) *RouteFollowupAction {
p.nextState = handler
return &RouteFollowupAction{p}
}
// RouteRepeat tells the parser that on the next parsing cycle, the current
// ParseHandler must be reinvoked.
// Deprecated
func (p *ParseAPI) RouteRepeat() {
p.RouteTo(p.state)
}
// RouteReturn tells the parser that on the next cycle the last ParseHandler
// that was pushed on the route stack must be invoked.
//
// Using this method is optional. When implementating a ParseHandler 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.
// Deprecated
func (p *ParseAPI) RouteReturn() {
p.nextState = p.popRoute()
}
// RouteFollowupAction chains parsing routes.
// It allows for routing code like p.RouteTo(handlerA).ThenTo(handlerB).
// Deprecated
type RouteFollowupAction struct {
p *ParseAPI
}
// ThenTo schedules a ParseHandler that must be invoked after the RouteTo
// ParseHandler has been completed.
// For example:
//
// p.RouteTo(handlerA).ThenTo(handlerB)
// Deprecated
func (a *RouteFollowupAction) ThenTo(state ParseHandler) {
a.p.pushRoute(state)
}
// ThenReturnHere schedules the current ParseHandler to be invoked after
// the RouteTo ParseHandler has been completed.
// For example:
//
// p.RouteTo(handlerA).ThenReturnHere()
// Deprecated
func (a *RouteFollowupAction) ThenReturnHere() {
a.p.pushRoute(a.p.state)
}
// pushRoute adds the ParseHandler to the route stack.
// This is used for implementing nested parsing.
// Deprecated
func (p *ParseAPI) pushRoute(state ParseHandler) {
p.routeStack = append(p.routeStack, state)
}
// popRoute pops the last pushed ParseHandler from the route stack.
// Deprecated
func (p *ParseAPI) popRoute() ParseHandler {
last := len(p.routeStack) - 1
head, tail := p.routeStack[:last], p.routeStack[last]
p.routeStack = head
return tail
}
// ExpectEndOfFile can be used to check if the input is at end of file.
// Intended use:
//
// func yourParseHandler(p *parsekit.ParseAPI) {
// ...
// p.ExpectEndOfFile()
// }
//
// This will execute the end of file test right away. If you want to
// use the end of file check as a StateHandler instead, you can also
// make use of another form, for example:
//
// func yourParseHandler(p *parsekit.ParseAPI) {
// p.RouteTo(yourHandler).ThenTo(parsekit.ExpectEndOfFile)
// }
func (p *ParseAPI) ExpectEndOfFile() {
// When some previous parsing step yielded an error, skip this operation.
if p.err != nil || p.stopped {
return
}
if p.On(A.EndOfFile).Stay() {
p.Stop()
} else {
p.Expects("end of file")
p.UnexpectedInput()
}
}
// ExpectEndOfFile can be scheduled as a ParseHandler function.
// It makes sure that the input is at the end of file.
// Intended use:
//
// func yourParseHandler(p *parsekit.ParseAPI) {
// ...
// p.RouteTo(parsekit.ExpectEndOfFile)
// }
//
// It is not mandatory to use this ParseHandler. You can take care fo EOF
// yourself too. Simply emit an ItemEOF when the end of the input was reached
// to stop the parser loop:
//
// p.Stop()
// TODO meh, get rid of this one, once we don't use state scheduling anymore.
// Deprecated
func ExpectEndOfFile(p *ParseAPI) {
p.Expects("end of file")
if p.On(A.EndOfFile).Stay() {
p.Stop()
}
}