fspl/lexer/test-common.go

140 lines
2.8 KiB
Go

package lexer
import "fmt"
import "testing"
import "strings"
import "git.tebibyte.media/fspl/fspl/errors"
func tok (kind TokenKind, value string) Token {
return Token {
Kind: kind,
Value: value,
}
}
func testString (
test *testing.T,
input string,
correct ...Token,
) {
testStringErr(test, "", "", 0, 0, input, correct...)
}
func testStringErr (
test *testing.T,
errMessage string,
errLine string,
errRow int,
errStart int,
input string,
correct ...Token,
) {
testError := func (err error) bool {
got := err.(errors.Error)
gotMessage := got.Error()
gotLine := got.Position().Line
gotRow := got.Position().Row
gotStart := got.Position().Start
correct :=
gotMessage == errMessage &&
gotLine == errLine &&
gotRow == errRow &&
gotStart == errStart
if !correct {
test.Log("errors do not match")
test.Log("got:\n" + errors.Format(got))
test.Log("correct:\n" + errors.Format(errors.Errorf (
errors.Position {
File: "input.fspl",
Line: errLine,
Row: errRow,
Start: errStart,
End: errStart,
},
errMessage,
)))
test.Fail()
}
return correct
}
printUnexpectedErr := func (err error) {
test.Log("lexer returned error:\n" + errors.Format(err))
}
reader := strings.NewReader(input)
lx, err := LexReader("input.fspl", reader)
if err != nil {
if errMessage == "" {
printUnexpectedErr(err)
test.Fail()
return
} else {
if !testError(err) { return }
}
}
var tokens []Token
for {
got, err := lx.Next()
tokens = append(tokens, got)
if got.EOF() { break }
if err != nil {
if errMessage == "" {
printUnexpectedErr(err)
test.Fail()
} else {
if !testError(err) { return }
}
break
}
}
printColumns := func (left, right string) {
test.Logf("%-50v | %v", left, right)
}
dumpToken := func (token Token) string {
return fmt.Sprintf("%12v: \"%s\"", token.Kind, token.Value)
}
compareTokens := func () {
length := len(tokens)
if len(correct) > length { length = len(correct) }
printColumns("CORRECT", "GOT")
for index := 0; index < length; index ++ {
left := "..."
right := "..."
if index < len(correct) {
left = dumpToken(correct[index])
}
if index < len(tokens) {
right = dumpToken(tokens[index])
}
printColumns(left, right)
}
}
if len(tokens) != len(correct) {
test.Logf (
"len(correct) and len(got) do not match (%v, %v)",
len(correct), len(tokens))
compareTokens()
test.Fail()
return
}
for index, token := range correct {
gotToken := tokens[index]
if token.Kind != gotToken.Kind || token.Value != gotToken.Value {
test.Logf("correct and got do not match at %v", index)
compareTokens()
test.Fail()
return
}
}
}