summaryrefslogtreecommitdiff
path: root/scanner/scan_test.go
blob: 6a54d8efbe7bea5ea8191729aec89d59c5c0d4d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package scanner

import (
	"fmt"
	"testing"
)

var GoScanner = &Scanner{
	CharProp: [ASCIILen]uint{
		'\t': CharSep,
		'\n': CharLineSep,
		' ':  CharSep,
		'!':  CharOp,
		'"':  CharStr | StrEsc | StrNonl,
		'%':  CharOp,
		'&':  CharOp,
		'\'': CharStr | StrEsc,
		'(':  CharBlock,
		'*':  CharOp,
		'+':  CharOp,
		',':  CharGroupSep,
		'-':  CharOp,
		'`':  CharStr,
		'.':  CharOp,
		'/':  CharOp,
		':':  CharOp,
		';':  CharGroupSep,
		'<':  CharOp,
		'=':  CharOp,
		'>':  CharOp,
		'[':  CharBlock,
		'^':  CharOp,
		'{':  CharBlock,
		'|':  CharOp,
		'~':  CharOp,
	},
	End: map[string]string{
		"(":  ")",
		"{":  "}",
		"[":  "]",
		"/*": "*/",
		`"`:  `"`,
		"'":  "'",
		"`":  "`",
		"//": "\n",
	},
}

func TestScan(t *testing.T) {
	tests := []struct{ src, result, errStr string }{
		// Simple tokens: separators, identifiers, numbers, operators.
		{"", "[]", ""},
		{"   abc + 5", "[{3 1 abc 0 0 <nil>} {7 3 + 0 0 <nil>} {9 2 5 0 0 5}]", ""},
		{"abc0+5 ", "[{0 1 abc0 0 0 <nil>} {4 3 + 0 0 <nil>} {5 2 5 0 0 5}]", ""},
		{"a+5\na=x-4", "[{0 1 a 0 0 <nil>} {1 3 + 0 0 <nil>} {2 2 5 0 0 5} {3 4   0 0 <nil>} {4 1 a 0 0 <nil>} {5 3 = 0 0 <nil>} {6 1 x 0 0 <nil>} {7 3 - 0 0 <nil>} {8 2 4 0 0 4}]", ""},

		// Strings.
		{`return "hello world" + 4`, `[{0 1 return 0 0 <nil>} {7 5 "hello world" 1 1 <nil>} {21 3 + 0 0 <nil>} {23 2 4 0 0 4}]`, ""},
		{`print(4 * (3+7))`, "[{0 1 print 0 0 <nil>} {5 6 (4 * (3+7)) 1 1 <nil>}]", ""},
		{`"foo`, "[]", "1:1: block not terminated"},
		{`abc
def "foo truc`, "[]", "2:6: block not terminated"},
		{`"ab\"`, "[]", "1:1: block not terminated"},
		{`"ab\\"`, `[{0 5 "ab\\" 1 1 <nil>}]`, ""},
		{`"ab\\\"`, "[]", "1:1: block not terminated"},
		{`"ab\\\\"`, `[{0 5 "ab\\\\" 1 1 <nil>}]`, ""},
		{`"abc
def"`, "[]", "1:1: block not terminated"},
		{"`hello\nworld`", "[{0 5 `hello\nworld` 1 1 <nil>}]", ""},

		// Nested blocks.
		// {`f("a)bc")+1, 3)`, "[{0 1 f } {1 6 (\"a)bc\", 3) (}]", ""},
		{"2* (3+4", "[]", "1:4: block not terminated"},
		{`("fo)o")+1`, "[{0 6 (\"fo)o\") 1 1 <nil>} {8 3 + 0 0 <nil>} {9 2 1 0 0 1}]", ""},
		{`"foo""bar"`, "[{0 5 \"foo\" 1 1 <nil>} {5 5 \"bar\" 1 1 <nil>}]", ""},
	}

	for _, test := range tests {
		t.Run("", func(t *testing.T) {
			errStr := ""
			token, err := GoScanner.Scan(test.src)
			if err != nil {
				errStr = err.Error()
			}
			if errStr != test.errStr {
				t.Errorf("got error %#v, want error %#v", errStr, test.errStr)
			}
			result := fmt.Sprintf("%v", token)
			t.Logf("%#v\n%v %v\n", test.src, result, errStr)
			if result != test.result {
				t.Errorf("got %#v, want %#v", result, test.result)
			}
		})
	}
}