javascript - ast_parser_test.go
1 package javascript
2
3 import (
4 "fmt"
5 "reflect"
6 "testing"
7
8 "vimagination.zapto.org/parser"
9 )
10
11 func TestNewJSParser(t *testing.T) {
12 for n, test := range [...]struct {
13 Source string
14 JSParser jsParser
15 Err error
16 }{
17 {"", jsParser{Token{Token: parser.Token{Type: parser.TokenDone}}}, nil},
18 {
19 "\"use strict\";\n\nvar hello = `World\n!`;",
20 jsParser{
21 {
22 parser.Token{Type: TokenStringLiteral, Data: "\"use strict\""},
23 0, 0, 0,
24 },
25 {
26 parser.Token{Type: TokenPunctuator, Data: ";"},
27 12, 0, 12,
28 },
29 {
30 parser.Token{Type: TokenLineTerminator, Data: "\n\n"},
31 13, 0, 13,
32 },
33 {
34 parser.Token{Type: TokenKeyword, Data: "var"},
35 15, 2, 0,
36 },
37 {
38 parser.Token{Type: TokenWhitespace, Data: " "},
39 18, 2, 3,
40 },
41 {
42 parser.Token{Type: TokenIdentifier, Data: "hello"},
43 19, 2, 4,
44 },
45 {
46 parser.Token{Type: TokenWhitespace, Data: " "},
47 24, 2, 9,
48 },
49 {
50 parser.Token{Type: TokenPunctuator, Data: "="},
51 25, 2, 10,
52 },
53 {
54 parser.Token{Type: TokenWhitespace, Data: " "},
55 26, 2, 11,
56 },
57 {
58 parser.Token{Type: TokenNoSubstitutionTemplate, Data: "`World\n!`"},
59 27, 2, 12,
60 },
61 {
62 parser.Token{Type: TokenPunctuator, Data: ";"},
63 36, 3, 2,
64 },
65 {
66 parser.Token{Type: parser.TokenDone, Data: ""},
67 37, 3, 3,
68 },
69 },
70 nil,
71 },
72 {
73 "@",
74 jsParser{
75 {
76 parser.Token{Type: parser.TokenError, Data: "invalid character: @"},
77 0, 0, 0,
78 },
79 },
80 Error{
81 Err: fmt.Errorf("%w: %s", ErrInvalidCharacter, "@"),
82 Parsing: "Tokens",
83 Token: Token{
84 parser.Token{Type: parser.TokenError, Data: "invalid character: @"},
85 0, 0, 0,
86 },
87 },
88 },
89 } {
90 j, err := newJSParser(makeTokeniser(parser.NewStringTokeniser(test.Source)))
91 if !reflect.DeepEqual(err, test.Err) {
92 t.Errorf("test %d: expecting error %q, got %q", n+1, test.Err, err)
93 }
94 for m, tk := range j[:cap(j)] {
95 tkp := j.Peek()
96 tkn := j.next()
97 tkl := j.GetLastToken()
98 if tkn != tk {
99 t.Errorf("test %d.%d.1: expecting %v, got %v", n+1, m+1, tk, tkn)
100 } else if tkp != tkn.Token {
101 t.Errorf("test %d.%d.2: expecting to Peek %v, got %v", n+1, m+1, tkn.Token, tkp)
102 } else if *tkl != tkn {
103 t.Errorf("test %d.%d.3: expectign to GetLast %v, got %v", n+1, m+1, tkn, *tkl)
104 }
105 }
106 if test.Err == nil {
107 if tk := j.next(); tk.Type != parser.TokenDone {
108 t.Errorf("test %d: expecting TokenDone, got %v", cap(j)+1, tk)
109 }
110 }
111 }
112 pErr := Error{
113 Err: fmt.Errorf("%w: %s", ErrInvalidCharacter, "@"),
114 Parsing: "Tokens",
115 Token: Token{
116 Token: parser.Token{
117 Type: parser.TokenError,
118 Data: "invalid character: @",
119 },
120 Pos: 0,
121 Line: 0,
122 LinePos: 0,
123 },
124 }
125 if _, err := ParseScript(makeTokeniser(parser.NewStringTokeniser("@"))); !reflect.DeepEqual(err, pErr) {
126 t.Errorf("Script token error test: expecting %s, got %s", pErr, err)
127 }
128 if _, err := ParseModule(makeTokeniser(parser.NewStringTokeniser("@"))); !reflect.DeepEqual(err, pErr) {
129 t.Errorf("Module token error test: expecting %s, got %s", pErr, err)
130 }
131 tk := Token{
132 Token: parser.Token{
133 Type: TokenPunctuator,
134 Data: "?",
135 },
136 Pos: 0,
137 Line: 0,
138 LinePos: 0,
139 }
140 sErr := Error{
141 Err: Error{
142 Err: Error{
143 Err: assignmentError(tk),
144 Parsing: "Expression",
145 Token: tk,
146 },
147 Parsing: "Statement",
148 Token: tk,
149 },
150 Parsing: "StatementListItem",
151 Token: tk,
152 }
153 if _, err := ParseScript(makeTokeniser(parser.NewStringTokeniser("?"))); !reflect.DeepEqual(err, sErr) {
154 t.Errorf("Script error test: expecting %s, got %s", sErr, err)
155 }
156 mErr := Error{
157 Err: sErr,
158 Parsing: "ModuleItem",
159 Token: tk,
160 }
161 if _, err := ParseModule(makeTokeniser(parser.NewStringTokeniser("?"))); !reflect.DeepEqual(err, mErr) {
162 t.Errorf("Module error test: expecting %s, got %s", mErr, err)
163 }
164 fErr := Error{
165 Err: errorStr("TEST"),
166 Parsing: "FAUX",
167 Token: Token{
168 Pos: 1,
169 Line: 2,
170 LinePos: 3,
171 },
172 }
173 const e = "FAUX: error at position 2 (3:4):\nTEST"
174 if str := fErr.Error(); str != e {
175 t.Errorf("error test: expecting %q, got %q", e, str)
176 }
177 }
178
179 type errorStr string
180
181 func (e errorStr) Error() string {
182 return string(e)
183 }
184