44 lines
1.5 KiB
Go
44 lines
1.5 KiB
Go
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
|