diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hil/scanner/peeker.go')
-rw-r--r-- | vendor/github.com/hashicorp/hil/scanner/peeker.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hil/scanner/peeker.go b/vendor/github.com/hashicorp/hil/scanner/peeker.go new file mode 100644 index 0000000..4de3728 --- /dev/null +++ b/vendor/github.com/hashicorp/hil/scanner/peeker.go | |||
@@ -0,0 +1,55 @@ | |||
1 | package scanner | ||
2 | |||
3 | // Peeker is a utility that wraps a token channel returned by Scan and | ||
4 | // provides an interface that allows a caller (e.g. the parser) to | ||
5 | // work with the token stream in a mode that allows one token of lookahead, | ||
6 | // and provides utilities for more convenient processing of the stream. | ||
7 | type Peeker struct { | ||
8 | ch <-chan *Token | ||
9 | peeked *Token | ||
10 | } | ||
11 | |||
12 | func NewPeeker(ch <-chan *Token) *Peeker { | ||
13 | return &Peeker{ | ||
14 | ch: ch, | ||
15 | } | ||
16 | } | ||
17 | |||
18 | // Peek returns the next token in the stream without consuming it. A | ||
19 | // subsequent call to Read will return the same token. | ||
20 | func (p *Peeker) Peek() *Token { | ||
21 | if p.peeked == nil { | ||
22 | p.peeked = <-p.ch | ||
23 | } | ||
24 | return p.peeked | ||
25 | } | ||
26 | |||
27 | // Read consumes the next token in the stream and returns it. | ||
28 | func (p *Peeker) Read() *Token { | ||
29 | token := p.Peek() | ||
30 | |||
31 | // As a special case, we will produce the EOF token forever once | ||
32 | // it is reached. | ||
33 | if token.Type != EOF { | ||
34 | p.peeked = nil | ||
35 | } | ||
36 | |||
37 | return token | ||
38 | } | ||
39 | |||
40 | // Close ensures that the token stream has been exhausted, to prevent | ||
41 | // the goroutine in the underlying scanner from leaking. | ||
42 | // | ||
43 | // It's not necessary to call this if the caller reads the token stream | ||
44 | // to EOF, since that implicitly closes the scanner. | ||
45 | func (p *Peeker) Close() { | ||
46 | for _ = range p.ch { | ||
47 | // discard | ||
48 | } | ||
49 | // Install a synthetic EOF token in 'peeked' in case someone | ||
50 | // erroneously calls Peek() or Read() after we've closed. | ||
51 | p.peeked = &Token{ | ||
52 | Type: EOF, | ||
53 | Content: "", | ||
54 | } | ||
55 | } | ||