Files
2026-07-13 12:32:25 +08:00

81 lines
2.6 KiB
Go

// Copyright 2023-2024 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
// TokenReader may be used to easily read through a collection of tokens generated from a synopsis. Of note, a
// TokenReader will skip all short and medium spaces, as clients of a reader will only care about statement boundaries.
type TokenReader struct {
tokens []Token
index int
}
// NewTokenReader returns a new *TokenReader created from the given tokens.
func NewTokenReader(tokens []Token) *TokenReader {
sanitizedTokens := make([]Token, 0, len(tokens))
for _, token := range tokens {
if token.IsStandardSpace() {
continue
}
sanitizedTokens = append(sanitizedTokens, token)
}
return &TokenReader{
tokens: sanitizedTokens,
index: -1,
}
}
// Next returns the next token while advancing the reader. Returns false if there are no more tokens.
func (reader *TokenReader) Next() (Token, bool) {
if reader.index+1 >= len(reader.tokens) {
return Token{Type: TokenType_EOF}, false
}
reader.index++
return reader.tokens[reader.index], true
}
// Peek returns the next token. Does not advance the reader. Returns false if there are no more tokens.
func (reader *TokenReader) Peek() (Token, bool) {
if reader.index+1 >= len(reader.tokens) {
return Token{Type: TokenType_EOF}, false
}
return reader.tokens[reader.index+1], true
}
// PeekBy returns the next token that is n positions from the current token. Does not advance the reader. Returns false
// if we are peeking beyond the slice.
func (reader *TokenReader) PeekBy(n int) (Token, bool) {
if reader.index+n >= len(reader.tokens) || reader.index+n < 0 {
return Token{Type: TokenType_EOF}, false
}
return reader.tokens[reader.index+n], true
}
// Advance is equivalent to calling AdvanceBy(1).
func (reader *TokenReader) Advance() {
reader.AdvanceBy(1)
}
// AdvanceBy advances the reader by the given amount. If the amount is greater than the number of remaining tokens, then
// it advances to the end. Cannot advance backwards.
func (reader *TokenReader) AdvanceBy(n int) {
if n < 0 {
n = 0
}
if reader.index+n >= len(reader.tokens) {
n = len(reader.tokens) - reader.index - 1
}
reader.index += n
}