ginger/gg/lexer_test.go
2021-12-26 14:49:43 -07:00

208 lines
3.4 KiB
Go

package gg
import (
"errors"
"strconv"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
type mockReader struct {
body []byte
err error
}
func (r *mockReader) Read(b []byte) (int, error) {
n := copy(b, r.body)
r.body = r.body[n:]
if len(r.body) == 0 {
return n, r.err
}
return n, nil
}
func TestLexer(t *testing.T) {
expErr := errors.New("eof")
tests := []struct {
in string
exp []LexerToken
}{
{in: "", exp: []LexerToken{}},
{in: "* fooo", exp: []LexerToken{}},
{
in: "*\n",
exp: []LexerToken{
{
Kind: LexerTokenKindPunctuation,
Value: "\n",
Row: 0, Col: 1,
},
},
},
{
in: "foo\nbar\n\n",
exp: []LexerToken{
{
Kind: LexerTokenKindName,
Value: "foo",
Row: 0, Col: 0,
},
{
Kind: LexerTokenKindPunctuation,
Value: "\n",
Row: 0, Col: 3,
},
{
Kind: LexerTokenKindName,
Value: "bar",
Row: 1, Col: 0,
},
{
Kind: LexerTokenKindPunctuation,
Value: "\n",
Row: 1, Col: 3,
},
{
Kind: LexerTokenKindPunctuation,
Value: "\n",
Row: 2, Col: 0,
},
},
},
{
in: "foo",
exp: []LexerToken{
{
Kind: LexerTokenKindName,
Value: "foo",
Row: 0, Col: 0,
},
},
},
{
in: "foo bar f-o f0O Foo",
exp: []LexerToken{
{
Kind: LexerTokenKindName,
Value: "foo",
Row: 0, Col: 0,
},
{
Kind: LexerTokenKindName,
Value: "bar",
Row: 0, Col: 4,
},
{
Kind: LexerTokenKindName,
Value: "f-o",
Row: 0, Col: 8,
},
{
Kind: LexerTokenKindName,
Value: "f0O",
Row: 0, Col: 12,
},
{
Kind: LexerTokenKindName,
Value: "Foo",
Row: 0, Col: 16,
},
},
},
{
in: "1 100 -100",
exp: []LexerToken{
{
Kind: LexerTokenKindNumber,
Value: "1",
Row: 0, Col: 0,
},
{
Kind: LexerTokenKindNumber,
Value: "100",
Row: 0, Col: 2,
},
{
Kind: LexerTokenKindNumber,
Value: "-100",
Row: 0, Col: 6,
},
},
},
{
in: "1<2!-3 ()",
exp: []LexerToken{
{
Kind: LexerTokenKindNumber,
Value: "1",
Row: 0, Col: 0,
},
{
Kind: LexerTokenKindPunctuation,
Value: "<",
Row: 0, Col: 1,
},
{
Kind: LexerTokenKindNumber,
Value: "2",
Row: 0, Col: 2,
},
{
Kind: LexerTokenKindPunctuation,
Value: "!",
Row: 0, Col: 3,
},
{
Kind: LexerTokenKindNumber,
Value: "-3",
Row: 0, Col: 4,
},
{
Kind: LexerTokenKindPunctuation,
Value: "(",
Row: 0, Col: 7,
},
{
Kind: LexerTokenKindPunctuation,
Value: ")",
Row: 0, Col: 8,
},
},
},
}
for i, test := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
lexer := NewLexer(&mockReader{body: []byte(test.in), err: expErr})
for i := range test.exp {
tok, err := lexer.Next()
assert.NoError(t, err)
assert.Equal(t, test.exp[i], tok, "test.exp[%d]", i)
}
tok, err := lexer.Next()
assert.ErrorIs(t, err, expErr)
assert.Equal(t, LexerToken{}, tok)
lexErr := new(LexerError)
assert.True(t, errors.As(err, &lexErr))
inParts := strings.Split(test.in, "\n")
assert.ErrorIs(t, lexErr, expErr)
assert.Equal(t, lexErr.Row, len(inParts)-1)
assert.Equal(t, lexErr.Col, len(inParts[len(inParts)-1]))
})
}
}