package parsekit // MatchAction is a struct that is used for building On()-method chains. // // It embeds the RouteAction struct, to make it possible to go right into // a route action, which is basically a simple way of aliasing a chain // like p.On(...).Stay().RouteTo(...) into p.On(...).RouteTo(...). type MatchAction struct { RouteAction ChainAction runes []rune widths []int } // Accept tells the parser to move the cursor past a match that was found, // and to store the input that matched in the string buffer. // When no match was found, then no action is taken. // It returns a RouteAction struct, which provides methods that can be used // to tell the parser what state to go to next. func (a *MatchAction) Accept() *RouteAction { if a.ok { for i, r := range a.runes { a.p.buffer.writeRune(r) a.p.advanceCursor(r, a.widths[i]) } } return &RouteAction{ChainAction: ChainAction{a.p, a.ok}} } // Skip tells the parser to move the cursor past a match that was found, // without storing the actual match in the string buffer. // Returns true in case a match was found. // When no match was found, then no action is taken and false is returned. func (a *MatchAction) Skip() *RouteAction { if a.ok { for i, r := range a.runes { type C struct { Rune MatchRune } a.p.advanceCursor(r, a.widths[i]) } } return &RouteAction{ChainAction: ChainAction{a.p, a.ok}} } // Stay tells the parser to not move the cursor after finding a match. // Returns true in case a match was found, false otherwise. func (a *MatchAction) Stay() *RouteAction { return &RouteAction{ChainAction: ChainAction{a.p, a.ok}} } // RouteTo is a shortcut for p.On(...).Stay() + p.RouteTo(...). func (a *MatchAction) RouteTo(state StateHandler) *RouteFollowupAction { return a.Stay().RouteTo(state) } // RouteReturn is a shortcut for p.On(...).Stay() + p.RouteReturn(...). func (a *MatchAction) RouteReturn() *ChainAction { return a.Stay().RouteReturn() } // advanceCursor advances the rune cursor one position in the input data. // While doing so, it keeps tracks of newlines, so we can report on // row + column positions on error. func (p *P) advanceCursor(r rune, w int) { p.pos += w if p.newline { p.cursorLine++ p.cursorColumn = 1 } else { p.cursorColumn++ } p.newline = r == '\n' }