go-parsekit/tokenize/api_bytemode.go

70 lines
2.3 KiB
Go

package tokenize
import "git.makaay.nl/mauricem/go-parsekit/read"
// ByteMode provides byte-driven input/output functionality for the tokenize API.
type ByteMode struct {
api *API
reader *read.Buffer // the buffered input reader
}
// Peek returns the byte at the provided byte offset.
//
// When an error occurs during reading the input, an error will be returned.
// When an offset is requested that is beyond the length of the available input
// data, then the error will be io.EOF.
func (byteMode ByteMode) Peek(offset int) (byte, error) {
return byteMode.reader.ByteAt(byteMode.api.stackFrame.offset + offset)
}
func (byteMode ByteMode) Accept(b byte) {
byteMode.api.Output.AddByte(b)
byteMode.MoveCursor(b)
}
// AcceptMulti is used to accept one or more bytes that were read from the input.
// This tells the tokenizer: "I've seen these bytes. I want to make use of them
// for the final output, so please remember them for me. I will now continue
// reading after these bytes."
//
// This will update the position of the cursor (which keeps track of what line
// and column we are on in the input data) and add the bytes to the tokenizer
// output.
//
// After the call, byte offset 0 for PeekByte() and PeekRune() will point at
// the first byte after the accepted bytes.
func (byteMode ByteMode) AcceptMulti(bytes ...byte) {
byteMode.api.Output.AddBytes(bytes...)
byteMode.MoveCursorMulti(bytes...)
}
// MoveCursor updates the position of the read cursor, based on the provided byte.
// This method takes newlines into account to keep track of line numbers and
// column positions for the input cursor.
//
// After the call, byte offset 0 for Peek() and PeekMulti() will point at
// the first byte at the new cursor position.
func (byteMode ByteMode) MoveCursor(b byte) {
f := byteMode.api.stackFrame
if b == '\n' {
f.column = 0
f.line++
} else {
f.column++
}
f.offset++
}
// MoveCursorMulti updates the position of the read cursor, based on the provided bytes.
// This method takes newlines into account to keep track of line numbers and
// column positions for the input cursor.
//
// After the call, byte offset 0 for Peek() and PeekMulti() will point at
// the first byte at the new cursor position.
func (byteMode ByteMode) MoveCursorMulti(bytes ...byte) {
for _, b := range bytes {
byteMode.MoveCursor(b)
}
}