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 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}} } // 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' }