23cb83ef3e
This will make it easier for the parser to walk through the token sequence with one token of lookahead, maintaining state of where we've got to and also allowing us to switch into and out of the newline-sensitive mode as we transition to and from newline-sensitive constructs.
159 lines
2.4 KiB
Go
159 lines
2.4 KiB
Go
package zclsyntax
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestPeeker(t *testing.T) {
|
|
tokens := Tokens{
|
|
{
|
|
Type: TokenIdent,
|
|
},
|
|
{
|
|
Type: TokenComment,
|
|
},
|
|
{
|
|
Type: TokenIdent,
|
|
},
|
|
{
|
|
Type: TokenComment,
|
|
},
|
|
{
|
|
Type: TokenIdent,
|
|
},
|
|
{
|
|
Type: TokenNewline,
|
|
},
|
|
{
|
|
Type: TokenIdent,
|
|
},
|
|
{
|
|
Type: TokenNewline,
|
|
},
|
|
{
|
|
Type: TokenIdent,
|
|
},
|
|
{
|
|
Type: TokenNewline,
|
|
},
|
|
{
|
|
Type: TokenEOF,
|
|
},
|
|
}
|
|
|
|
{
|
|
peeker := newPeeker(tokens, true)
|
|
|
|
wantTypes := []TokenType{
|
|
TokenIdent,
|
|
TokenComment,
|
|
TokenIdent,
|
|
TokenComment,
|
|
TokenIdent,
|
|
TokenNewline,
|
|
TokenIdent,
|
|
TokenNewline,
|
|
TokenIdent,
|
|
TokenNewline,
|
|
TokenEOF,
|
|
}
|
|
var gotTypes []TokenType
|
|
|
|
for {
|
|
peeked := peeker.Peek()
|
|
read := peeker.Read()
|
|
if peeked.Type != read.Type {
|
|
t.Errorf("mismatched Peek %s and Read %s", peeked, read)
|
|
}
|
|
|
|
gotTypes = append(gotTypes, read.Type)
|
|
|
|
if read.Type == TokenEOF {
|
|
break
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(gotTypes, wantTypes) {
|
|
t.Errorf("wrong types\ngot: %#v\nwant: %#v", gotTypes, wantTypes)
|
|
}
|
|
}
|
|
|
|
{
|
|
peeker := newPeeker(tokens, false)
|
|
|
|
wantTypes := []TokenType{
|
|
TokenIdent,
|
|
TokenIdent,
|
|
TokenIdent,
|
|
TokenNewline,
|
|
TokenIdent,
|
|
TokenNewline,
|
|
TokenIdent,
|
|
TokenNewline,
|
|
TokenEOF,
|
|
}
|
|
var gotTypes []TokenType
|
|
|
|
for {
|
|
peeked := peeker.Peek()
|
|
read := peeker.Read()
|
|
if peeked.Type != read.Type {
|
|
t.Errorf("mismatched Peek %s and Read %s", peeked, read)
|
|
}
|
|
|
|
gotTypes = append(gotTypes, read.Type)
|
|
|
|
if read.Type == TokenEOF {
|
|
break
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(gotTypes, wantTypes) {
|
|
t.Errorf("wrong types\ngot: %#v\nwant: %#v", gotTypes, wantTypes)
|
|
}
|
|
}
|
|
|
|
{
|
|
peeker := newPeeker(tokens, false)
|
|
|
|
peeker.PushIncludeNewlines(false)
|
|
|
|
wantTypes := []TokenType{
|
|
TokenIdent,
|
|
TokenIdent,
|
|
TokenIdent,
|
|
TokenIdent,
|
|
TokenIdent,
|
|
TokenNewline, // we'll pop off the PushIncludeNewlines before we get here
|
|
TokenEOF,
|
|
}
|
|
var gotTypes []TokenType
|
|
|
|
idx := 0
|
|
for {
|
|
peeked := peeker.Peek()
|
|
read := peeker.Read()
|
|
if peeked.Type != read.Type {
|
|
t.Errorf("mismatched Peek %s and Read %s", peeked, read)
|
|
}
|
|
|
|
gotTypes = append(gotTypes, read.Type)
|
|
|
|
if read.Type == TokenEOF {
|
|
break
|
|
}
|
|
|
|
if idx == 4 {
|
|
peeker.PopIncludeNewlines()
|
|
}
|
|
|
|
idx++
|
|
}
|
|
|
|
if !reflect.DeepEqual(gotTypes, wantTypes) {
|
|
t.Errorf("wrong types\ngot: %#v\nwant: %#v", gotTypes, wantTypes)
|
|
}
|
|
}
|
|
}
|