1package lexer 2 3// PeekingLexer supports arbitrary lookahead as well as cloning. 4type PeekingLexer struct { 5 cursor int 6 eof Token 7 tokens []Token 8} 9 10// Upgrade a Lexer to a PeekingLexer with arbitrary lookahead. 11func Upgrade(lex Lexer) (*PeekingLexer, error) { 12 r := &PeekingLexer{} 13 for { 14 t, err := lex.Next() 15 if err != nil { 16 return nil, err 17 } 18 if t.EOF() { 19 r.eof = t 20 break 21 } 22 r.tokens = append(r.tokens, t) 23 } 24 return r, nil 25} 26 27// Cursor position in tokens. 28func (p *PeekingLexer) Cursor() int { 29 return p.cursor 30} 31 32// Next consumes and returns the next token. 33func (p *PeekingLexer) Next() (Token, error) { 34 if p.cursor >= len(p.tokens) { 35 return p.eof, nil 36 } 37 p.cursor++ 38 return p.tokens[p.cursor-1], nil 39} 40 41// Peek ahead at the n+1 token. ie. Peek(0) will peek at the next token. 42func (p *PeekingLexer) Peek(n int) (Token, error) { 43 i := p.cursor + n 44 if i >= len(p.tokens) { 45 return p.eof, nil 46 } 47 return p.tokens[i], nil 48} 49 50// Clone creates a clone of this PeekingLexer at its current token. 51// 52// The parent and clone are completely independent. 53func (p *PeekingLexer) Clone() *PeekingLexer { 54 clone := *p 55 return &clone 56} 57