package parsekit import ( "unicode/utf8" ) // peek returns but does not advance the cursor to the next rune(s) in the input. // Returns the rune, its width in bytes and a boolean. // The boolean will be false in case no upcoming rune can be peeked // (end of data or invalid UTF8 character). func (p *P) peek(offsetInBytes int) (rune, int, bool) { r, w := utf8.DecodeRuneInString(p.input[p.pos+offsetInBytes:]) return handleRuneError(r, w) } // handleRuneError is used to normale rune value in case of errors. // When an error occurs, then utf8.RuneError will be in the rune. // This can however indicate one of two situations: // * w == 0: end of file is reached // * w == 1: invalid UTF character on input // This function lets these two cases return respectively the // package's own EOF or INVALID runes, to make it easy for client // code to distinct between these two cases. func handleRuneError(r rune, w int) (rune, int, bool) { if r == utf8.RuneError { if w == 0 { return EOF, 0, false } return INVALID, w, false } return r, w, true } // EOF is a special rune, which is used to indicate an end of file when // reading a character from the input. // It can be treated as a rune when writing parsing rules, so a valid way to // say 'I now expect the end of the file' is using something like: // if (p.On(c.Rune(EOF)).Skip()) { ... } const EOF rune = -1 // INVALID is a special rune, which is used to indicate an invalid UTF8 // rune on the input. const INVALID rune = utf8.RuneError