blob: c9d284b33fa8b01dd4ad026b40b3bd8a2371f789 [file] [log] [blame]
Colin Cross8e0c5112015-01-23 14:15:10 -08001// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Jamie Gennis1bc967e2014-05-27 16:34:41 -070015package parser
16
17import (
18 "bytes"
19 "reflect"
Colin Crossfdeaf882018-03-21 17:00:39 -070020 "strconv"
21 "strings"
Jamie Gennis1bc967e2014-05-27 16:34:41 -070022 "testing"
23 "text/scanner"
24)
25
26func mkpos(offset, line, column int) scanner.Position {
27 return scanner.Position{
28 Offset: offset,
29 Line: line,
30 Column: column,
31 }
32}
33
34var validParseTestCases = []struct {
Colin Crossd1facc12015-01-08 14:56:03 -080035 input string
36 defs []Definition
Colin Cross1e737942016-06-10 17:27:12 -070037 comments []*CommentGroup
Jamie Gennis1bc967e2014-05-27 16:34:41 -070038}{
39 {`
40 foo {}
41 `,
42 []Definition{
43 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -070044 Type: "foo",
45 TypePos: mkpos(3, 2, 3),
Colin Crosse32cc802016-06-07 12:28:16 -070046 Map: Map{
47 LBracePos: mkpos(7, 2, 7),
48 RBracePos: mkpos(8, 2, 8),
49 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -070050 },
51 },
Colin Crossd1facc12015-01-08 14:56:03 -080052 nil,
Jamie Gennis1bc967e2014-05-27 16:34:41 -070053 },
54
55 {`
56 foo {
57 name: "abc",
58 }
59 `,
60 []Definition{
61 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -070062 Type: "foo",
63 TypePos: mkpos(3, 2, 3),
Colin Crosse32cc802016-06-07 12:28:16 -070064 Map: Map{
65 LBracePos: mkpos(7, 2, 7),
66 RBracePos: mkpos(27, 4, 3),
67 Properties: []*Property{
68 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -070069 Name: "name",
70 NamePos: mkpos(12, 3, 4),
71 ColonPos: mkpos(16, 3, 8),
Colin Crosse32cc802016-06-07 12:28:16 -070072 Value: &String{
73 LiteralPos: mkpos(18, 3, 10),
74 Value: "abc",
75 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -070076 },
77 },
78 },
79 },
80 },
Colin Crossd1facc12015-01-08 14:56:03 -080081 nil,
Jamie Gennis1bc967e2014-05-27 16:34:41 -070082 },
83
84 {`
85 foo {
86 isGood: true,
87 }
88 `,
89 []Definition{
90 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -070091 Type: "foo",
92 TypePos: mkpos(3, 2, 3),
Colin Crosse32cc802016-06-07 12:28:16 -070093 Map: Map{
94 LBracePos: mkpos(7, 2, 7),
95 RBracePos: mkpos(28, 4, 3),
96 Properties: []*Property{
97 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -070098 Name: "isGood",
99 NamePos: mkpos(12, 3, 4),
100 ColonPos: mkpos(18, 3, 10),
Colin Crosse32cc802016-06-07 12:28:16 -0700101 Value: &Bool{
102 LiteralPos: mkpos(20, 3, 12),
103 Value: true,
Colin Crossfdeaf882018-03-21 17:00:39 -0700104 Token: "true",
Colin Crosse32cc802016-06-07 12:28:16 -0700105 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700106 },
107 },
108 },
109 },
110 },
Colin Crossd1facc12015-01-08 14:56:03 -0800111 nil,
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700112 },
113
114 {`
115 foo {
Nan Zhangf5865442017-11-01 14:03:28 -0700116 num: 4,
117 }
118 `,
119 []Definition{
120 &Module{
121 Type: "foo",
122 TypePos: mkpos(3, 2, 3),
123 Map: Map{
124 LBracePos: mkpos(7, 2, 7),
125 RBracePos: mkpos(22, 4, 3),
126 Properties: []*Property{
127 {
128 Name: "num",
129 NamePos: mkpos(12, 3, 4),
130 ColonPos: mkpos(15, 3, 7),
131 Value: &Int64{
132 LiteralPos: mkpos(17, 3, 9),
133 Value: 4,
Colin Crossfdeaf882018-03-21 17:00:39 -0700134 Token: "4",
Nan Zhangf5865442017-11-01 14:03:28 -0700135 },
136 },
137 },
138 },
139 },
140 },
141 nil,
142 },
143
144 {`
145 foo {
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700146 stuff: ["asdf", "jkl;", "qwert",
147 "uiop", "bnm,"]
148 }
149 `,
150 []Definition{
151 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -0700152 Type: "foo",
153 TypePos: mkpos(3, 2, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700154 Map: Map{
155 LBracePos: mkpos(7, 2, 7),
156 RBracePos: mkpos(67, 5, 3),
157 Properties: []*Property{
158 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700159 Name: "stuff",
160 NamePos: mkpos(12, 3, 4),
161 ColonPos: mkpos(17, 3, 9),
Colin Crosse32cc802016-06-07 12:28:16 -0700162 Value: &List{
163 LBracePos: mkpos(19, 3, 11),
164 RBracePos: mkpos(63, 4, 19),
165 Values: []Expression{
166 &String{
167 LiteralPos: mkpos(20, 3, 12),
168 Value: "asdf",
169 },
170 &String{
171 LiteralPos: mkpos(28, 3, 20),
172 Value: "jkl;",
173 },
174 &String{
175 LiteralPos: mkpos(36, 3, 28),
176 Value: "qwert",
177 },
178 &String{
179 LiteralPos: mkpos(49, 4, 5),
180 Value: "uiop",
181 },
182 &String{
183 LiteralPos: mkpos(57, 4, 13),
184 Value: "bnm,",
185 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700186 },
187 },
188 },
189 },
190 },
191 },
192 },
Colin Crossd1facc12015-01-08 14:56:03 -0800193 nil,
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700194 },
195
Sasha Smundak29fdcad2020-02-11 22:39:47 -0800196 {
197 `
198 foo {
199 list_of_maps: [
200 {
201 var: true,
202 name: "a",
203 },
204 {
205 var: false,
206 name: "b",
207 },
208 ],
209 }
210`,
211 []Definition{
212 &Module{
213 Type: "foo",
214 TypePos: mkpos(3, 2, 3),
215 Map: Map{
216 LBracePos: mkpos(7, 2, 7),
217 RBracePos: mkpos(127, 13, 3),
218 Properties: []*Property{
219 {
220 Name: "list_of_maps",
221 NamePos: mkpos(12, 3, 4),
222 ColonPos: mkpos(24, 3, 16),
223 Value: &List{
224 LBracePos: mkpos(26, 3, 18),
225 RBracePos: mkpos(122, 12, 4),
226 Values: []Expression{
227 &Map{
228 LBracePos: mkpos(32, 4, 5),
229 RBracePos: mkpos(70, 7, 5),
230 Properties: []*Property{
231 {
232 Name: "var",
233 NamePos: mkpos(39, 5, 6),
234 ColonPos: mkpos(42, 5, 9),
235 Value: &Bool{
236 LiteralPos: mkpos(44, 5, 11),
237 Value: true,
238 Token: "true",
239 },
240 },
241 {
242 Name: "name",
243 NamePos: mkpos(55, 6, 6),
244 ColonPos: mkpos(59, 6, 10),
245 Value: &String{
246 LiteralPos: mkpos(61, 6, 12),
247 Value: "a",
248 },
249 },
250 },
251 },
252 &Map{
253 LBracePos: mkpos(77, 8, 5),
254 RBracePos: mkpos(116, 11, 5),
255 Properties: []*Property{
256 {
257 Name: "var",
258 NamePos: mkpos(84, 9, 6),
259 ColonPos: mkpos(87, 9, 9),
260 Value: &Bool{
261 LiteralPos: mkpos(89, 9, 11),
262 Value: false,
263 Token: "false",
264 },
265 },
266 {
267 Name: "name",
268 NamePos: mkpos(101, 10, 6),
269 ColonPos: mkpos(105, 10, 10),
270 Value: &String{
271 LiteralPos: mkpos(107, 10, 12),
272 Value: "b",
273 },
274 },
275 },
276 },
277 },
278 },
279 },
280 },
281 },
282 },
283 },
284 nil,
285 },
286 {
287 `
288 foo {
289 list_of_lists: [
290 [ "a", "b" ],
291 [ "c", "d" ]
292 ],
293 }
294`,
295 []Definition{
296 &Module{
297 Type: "foo",
298 TypePos: mkpos(3, 2, 3),
299 Map: Map{
300 LBracePos: mkpos(7, 2, 7),
301 RBracePos: mkpos(72, 7, 3),
302 Properties: []*Property{
303 {
304 Name: "list_of_lists",
305 NamePos: mkpos(12, 3, 4),
306 ColonPos: mkpos(25, 3, 17),
307 Value: &List{
308 LBracePos: mkpos(27, 3, 19),
309 RBracePos: mkpos(67, 6, 4),
310 Values: []Expression{
311 &List{
312 LBracePos: mkpos(33, 4, 5),
313 RBracePos: mkpos(44, 4, 16),
314 Values: []Expression{
315 &String{
316 LiteralPos: mkpos(35, 4, 7),
317 Value: "a",
318 },
319 &String{
320 LiteralPos: mkpos(40, 4, 12),
321 Value: "b",
322 },
323 },
324 },
325 &List{
326 LBracePos: mkpos(51, 5, 5),
327 RBracePos: mkpos(62, 5, 16),
328 Values: []Expression{
329 &String{
330 LiteralPos: mkpos(53, 5, 7),
331 Value: "c",
332 },
333 &String{
334 LiteralPos: mkpos(58, 5, 12),
335 Value: "d",
336 },
337 },
338 },
339 },
340 },
341 },
342 },
343 },
344 },
345 },
346 nil,
347 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700348 {`
Romain Guy2476f812014-07-25 17:01:20 -0700349 foo {
350 stuff: {
351 isGood: true,
Nan Zhangf5865442017-11-01 14:03:28 -0700352 name: "bar",
353 num: 36,
Romain Guy2476f812014-07-25 17:01:20 -0700354 }
355 }
356 `,
357 []Definition{
358 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -0700359 Type: "foo",
360 TypePos: mkpos(3, 2, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700361 Map: Map{
362 LBracePos: mkpos(7, 2, 7),
Nan Zhangf5865442017-11-01 14:03:28 -0700363 RBracePos: mkpos(76, 8, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700364 Properties: []*Property{
365 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700366 Name: "stuff",
367 NamePos: mkpos(12, 3, 4),
368 ColonPos: mkpos(17, 3, 9),
Colin Crosse32cc802016-06-07 12:28:16 -0700369 Value: &Map{
370 LBracePos: mkpos(19, 3, 11),
Nan Zhangf5865442017-11-01 14:03:28 -0700371 RBracePos: mkpos(72, 7, 4),
Colin Crosse32cc802016-06-07 12:28:16 -0700372 Properties: []*Property{
373 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700374 Name: "isGood",
375 NamePos: mkpos(25, 4, 5),
376 ColonPos: mkpos(31, 4, 11),
Colin Crosse32cc802016-06-07 12:28:16 -0700377 Value: &Bool{
378 LiteralPos: mkpos(33, 4, 13),
379 Value: true,
Colin Crossfdeaf882018-03-21 17:00:39 -0700380 Token: "true",
Colin Crosse32cc802016-06-07 12:28:16 -0700381 },
Romain Guy2476f812014-07-25 17:01:20 -0700382 },
Colin Crosse32cc802016-06-07 12:28:16 -0700383 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700384 Name: "name",
385 NamePos: mkpos(43, 5, 5),
386 ColonPos: mkpos(47, 5, 9),
Colin Crosse32cc802016-06-07 12:28:16 -0700387 Value: &String{
388 LiteralPos: mkpos(49, 5, 11),
389 Value: "bar",
390 },
Romain Guy2476f812014-07-25 17:01:20 -0700391 },
Nan Zhangf5865442017-11-01 14:03:28 -0700392 {
393 Name: "num",
394 NamePos: mkpos(60, 6, 5),
395 ColonPos: mkpos(63, 6, 8),
396 Value: &Int64{
397 LiteralPos: mkpos(65, 6, 10),
398 Value: 36,
Colin Crossfdeaf882018-03-21 17:00:39 -0700399 Token: "36",
Nan Zhangf5865442017-11-01 14:03:28 -0700400 },
401 },
Romain Guy2476f812014-07-25 17:01:20 -0700402 },
403 },
404 },
405 },
406 },
407 },
408 },
Colin Crossd1facc12015-01-08 14:56:03 -0800409 nil,
Romain Guy2476f812014-07-25 17:01:20 -0700410 },
411
412 {`
Colin Crossd1facc12015-01-08 14:56:03 -0800413 // comment1
Colin Crosse32cc802016-06-07 12:28:16 -0700414 foo /* test */ {
Colin Crossd1facc12015-01-08 14:56:03 -0800415 // comment2
416 isGood: true, // comment3
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700417 }
418 `,
419 []Definition{
420 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -0700421 Type: "foo",
422 TypePos: mkpos(17, 3, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700423 Map: Map{
424 LBracePos: mkpos(32, 3, 18),
425 RBracePos: mkpos(81, 6, 3),
426 Properties: []*Property{
427 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700428 Name: "isGood",
429 NamePos: mkpos(52, 5, 4),
430 ColonPos: mkpos(58, 5, 10),
Colin Crosse32cc802016-06-07 12:28:16 -0700431 Value: &Bool{
432 LiteralPos: mkpos(60, 5, 12),
433 Value: true,
Colin Crossfdeaf882018-03-21 17:00:39 -0700434 Token: "true",
Colin Crosse32cc802016-06-07 12:28:16 -0700435 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700436 },
437 },
438 },
439 },
440 },
Colin Cross1e737942016-06-10 17:27:12 -0700441 []*CommentGroup{
442 {
443 Comments: []*Comment{
444 &Comment{
445 Comment: []string{"// comment1"},
446 Slash: mkpos(3, 2, 3),
447 },
448 },
Colin Crosse32cc802016-06-07 12:28:16 -0700449 },
Colin Cross1e737942016-06-10 17:27:12 -0700450 {
451 Comments: []*Comment{
452 &Comment{
453 Comment: []string{"/* test */"},
454 Slash: mkpos(21, 3, 7),
455 },
456 },
Colin Crossd1facc12015-01-08 14:56:03 -0800457 },
Colin Cross1e737942016-06-10 17:27:12 -0700458 {
459 Comments: []*Comment{
460 &Comment{
461 Comment: []string{"// comment2"},
462 Slash: mkpos(37, 4, 4),
463 },
464 },
Colin Crossd1facc12015-01-08 14:56:03 -0800465 },
Colin Cross1e737942016-06-10 17:27:12 -0700466 {
467 Comments: []*Comment{
468 &Comment{
469 Comment: []string{"// comment3"},
470 Slash: mkpos(67, 5, 19),
471 },
472 },
Colin Crossd1facc12015-01-08 14:56:03 -0800473 },
474 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700475 },
476
477 {`
478 foo {
479 name: "abc",
Nan Zhangf5865442017-11-01 14:03:28 -0700480 num: 4,
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700481 }
482
483 bar {
484 name: "def",
Nan Zhangf5865442017-11-01 14:03:28 -0700485 num: -5,
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700486 }
487 `,
488 []Definition{
489 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -0700490 Type: "foo",
491 TypePos: mkpos(3, 2, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700492 Map: Map{
493 LBracePos: mkpos(7, 2, 7),
Nan Zhangf5865442017-11-01 14:03:28 -0700494 RBracePos: mkpos(38, 5, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700495 Properties: []*Property{
496 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700497 Name: "name",
498 NamePos: mkpos(12, 3, 4),
499 ColonPos: mkpos(16, 3, 8),
Colin Crosse32cc802016-06-07 12:28:16 -0700500 Value: &String{
501 LiteralPos: mkpos(18, 3, 10),
502 Value: "abc",
503 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700504 },
Nan Zhangf5865442017-11-01 14:03:28 -0700505 {
506 Name: "num",
507 NamePos: mkpos(28, 4, 4),
508 ColonPos: mkpos(31, 4, 7),
509 Value: &Int64{
510 LiteralPos: mkpos(33, 4, 9),
511 Value: 4,
Colin Crossfdeaf882018-03-21 17:00:39 -0700512 Token: "4",
Nan Zhangf5865442017-11-01 14:03:28 -0700513 },
514 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700515 },
516 },
517 },
518 &Module{
Colin Crossc32c4792016-06-09 15:52:30 -0700519 Type: "bar",
Nan Zhangf5865442017-11-01 14:03:28 -0700520 TypePos: mkpos(43, 7, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700521 Map: Map{
Nan Zhangf5865442017-11-01 14:03:28 -0700522 LBracePos: mkpos(47, 7, 7),
523 RBracePos: mkpos(79, 10, 3),
Colin Crosse32cc802016-06-07 12:28:16 -0700524 Properties: []*Property{
525 {
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700526 Name: "name",
Nan Zhangf5865442017-11-01 14:03:28 -0700527 NamePos: mkpos(52, 8, 4),
528 ColonPos: mkpos(56, 8, 8),
Colin Crosse32cc802016-06-07 12:28:16 -0700529 Value: &String{
Nan Zhangf5865442017-11-01 14:03:28 -0700530 LiteralPos: mkpos(58, 8, 10),
Colin Crosse32cc802016-06-07 12:28:16 -0700531 Value: "def",
532 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700533 },
Nan Zhangf5865442017-11-01 14:03:28 -0700534 {
535 Name: "num",
536 NamePos: mkpos(68, 9, 4),
537 ColonPos: mkpos(71, 9, 7),
538 Value: &Int64{
539 LiteralPos: mkpos(73, 9, 9),
540 Value: -5,
Colin Crossfdeaf882018-03-21 17:00:39 -0700541 Token: "-5",
Nan Zhangf5865442017-11-01 14:03:28 -0700542 },
543 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700544 },
545 },
546 },
547 },
Colin Crossd1facc12015-01-08 14:56:03 -0800548 nil,
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700549 },
Nan Zhangf5865442017-11-01 14:03:28 -0700550
Colin Crossd1facc12015-01-08 14:56:03 -0800551 {`
552 foo = "stuff"
553 bar = foo
554 baz = foo + bar
Colin Crossb274e6c2015-02-04 10:50:22 -0800555 boo = baz
556 boo += foo
Colin Crossd1facc12015-01-08 14:56:03 -0800557 `,
558 []Definition{
559 &Assignment{
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700560 Name: "foo",
561 NamePos: mkpos(3, 2, 3),
562 EqualsPos: mkpos(7, 2, 7),
Colin Crosse32cc802016-06-07 12:28:16 -0700563 Value: &String{
564 LiteralPos: mkpos(9, 2, 9),
565 Value: "stuff",
Colin Crossd1facc12015-01-08 14:56:03 -0800566 },
Colin Crosse32cc802016-06-07 12:28:16 -0700567 OrigValue: &String{
568 LiteralPos: mkpos(9, 2, 9),
569 Value: "stuff",
Colin Crossb274e6c2015-02-04 10:50:22 -0800570 },
571 Assigner: "=",
572 Referenced: true,
Colin Crossd1facc12015-01-08 14:56:03 -0800573 },
574 &Assignment{
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700575 Name: "bar",
576 NamePos: mkpos(19, 3, 3),
577 EqualsPos: mkpos(23, 3, 7),
Colin Crosse32cc802016-06-07 12:28:16 -0700578 Value: &Variable{
579 Name: "foo",
580 NamePos: mkpos(25, 3, 9),
581 Value: &String{
582 LiteralPos: mkpos(9, 2, 9),
583 Value: "stuff",
584 },
Colin Crossd1facc12015-01-08 14:56:03 -0800585 },
Colin Crosse32cc802016-06-07 12:28:16 -0700586 OrigValue: &Variable{
587 Name: "foo",
588 NamePos: mkpos(25, 3, 9),
589 Value: &String{
590 LiteralPos: mkpos(9, 2, 9),
591 Value: "stuff",
592 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800593 },
594 Assigner: "=",
595 Referenced: true,
Colin Crossd1facc12015-01-08 14:56:03 -0800596 },
597 &Assignment{
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700598 Name: "baz",
599 NamePos: mkpos(31, 4, 3),
600 EqualsPos: mkpos(35, 4, 7),
Colin Crosse32cc802016-06-07 12:28:16 -0700601 Value: &Operator{
602 OperatorPos: mkpos(41, 4, 13),
603 Operator: '+',
604 Value: &String{
605 LiteralPos: mkpos(9, 2, 9),
606 Value: "stuffstuff",
607 },
608 Args: [2]Expression{
609 &Variable{
610 Name: "foo",
611 NamePos: mkpos(37, 4, 9),
612 Value: &String{
613 LiteralPos: mkpos(9, 2, 9),
614 Value: "stuff",
Colin Crossd1facc12015-01-08 14:56:03 -0800615 },
616 },
Colin Crosse32cc802016-06-07 12:28:16 -0700617 &Variable{
618 Name: "bar",
619 NamePos: mkpos(43, 4, 15),
620 Value: &Variable{
621 Name: "foo",
622 NamePos: mkpos(25, 3, 9),
623 Value: &String{
624 LiteralPos: mkpos(9, 2, 9),
625 Value: "stuff",
626 },
627 },
628 },
Colin Crossd1facc12015-01-08 14:56:03 -0800629 },
630 },
Colin Crosse32cc802016-06-07 12:28:16 -0700631 OrigValue: &Operator{
632 OperatorPos: mkpos(41, 4, 13),
633 Operator: '+',
634 Value: &String{
635 LiteralPos: mkpos(9, 2, 9),
636 Value: "stuffstuff",
637 },
638 Args: [2]Expression{
639 &Variable{
640 Name: "foo",
641 NamePos: mkpos(37, 4, 9),
642 Value: &String{
643 LiteralPos: mkpos(9, 2, 9),
644 Value: "stuff",
Colin Crossb274e6c2015-02-04 10:50:22 -0800645 },
646 },
Colin Crosse32cc802016-06-07 12:28:16 -0700647 &Variable{
648 Name: "bar",
649 NamePos: mkpos(43, 4, 15),
650 Value: &Variable{
651 Name: "foo",
652 NamePos: mkpos(25, 3, 9),
653 Value: &String{
654 LiteralPos: mkpos(9, 2, 9),
655 Value: "stuff",
656 },
657 },
658 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800659 },
660 },
661 Assigner: "=",
662 Referenced: true,
663 },
664 &Assignment{
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700665 Name: "boo",
666 NamePos: mkpos(49, 5, 3),
667 EqualsPos: mkpos(53, 5, 7),
Colin Crosse32cc802016-06-07 12:28:16 -0700668 Value: &Operator{
669 Args: [2]Expression{
670 &Variable{
671 Name: "baz",
672 NamePos: mkpos(55, 5, 9),
673 Value: &Operator{
674 OperatorPos: mkpos(41, 4, 13),
675 Operator: '+',
676 Value: &String{
677 LiteralPos: mkpos(9, 2, 9),
678 Value: "stuffstuff",
679 },
680 Args: [2]Expression{
681 &Variable{
682 Name: "foo",
683 NamePos: mkpos(37, 4, 9),
684 Value: &String{
685 LiteralPos: mkpos(9, 2, 9),
686 Value: "stuff",
Colin Crossb274e6c2015-02-04 10:50:22 -0800687 },
688 },
Colin Crosse32cc802016-06-07 12:28:16 -0700689 &Variable{
690 Name: "bar",
691 NamePos: mkpos(43, 4, 15),
692 Value: &Variable{
693 Name: "foo",
694 NamePos: mkpos(25, 3, 9),
695 Value: &String{
696 LiteralPos: mkpos(9, 2, 9),
697 Value: "stuff",
698 },
699 },
700 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800701 },
702 },
Colin Crosse32cc802016-06-07 12:28:16 -0700703 },
704 &Variable{
705 Name: "foo",
706 NamePos: mkpos(68, 6, 10),
707 Value: &String{
708 LiteralPos: mkpos(9, 2, 9),
709 Value: "stuff",
Colin Crossb274e6c2015-02-04 10:50:22 -0800710 },
711 },
Colin Crosse32cc802016-06-07 12:28:16 -0700712 },
713 OperatorPos: mkpos(66, 6, 8),
714 Operator: '+',
715 Value: &String{
716 LiteralPos: mkpos(9, 2, 9),
717 Value: "stuffstuffstuff",
Colin Crossb274e6c2015-02-04 10:50:22 -0800718 },
719 },
Colin Crosse32cc802016-06-07 12:28:16 -0700720 OrigValue: &Variable{
721 Name: "baz",
722 NamePos: mkpos(55, 5, 9),
723 Value: &Operator{
724 OperatorPos: mkpos(41, 4, 13),
725 Operator: '+',
726 Value: &String{
727 LiteralPos: mkpos(9, 2, 9),
728 Value: "stuffstuff",
729 },
730 Args: [2]Expression{
731 &Variable{
732 Name: "foo",
733 NamePos: mkpos(37, 4, 9),
734 Value: &String{
735 LiteralPos: mkpos(9, 2, 9),
736 Value: "stuff",
737 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800738 },
Colin Crosse32cc802016-06-07 12:28:16 -0700739 &Variable{
740 Name: "bar",
741 NamePos: mkpos(43, 4, 15),
742 Value: &Variable{
743 Name: "foo",
744 NamePos: mkpos(25, 3, 9),
745 Value: &String{
746 LiteralPos: mkpos(9, 2, 9),
747 Value: "stuff",
748 },
749 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800750 },
751 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800752 },
753 },
754 Assigner: "=",
755 },
756 &Assignment{
Colin Crossb3d0b8d2016-06-09 17:03:57 -0700757 Name: "boo",
758 NamePos: mkpos(61, 6, 3),
759 EqualsPos: mkpos(66, 6, 8),
Colin Crosse32cc802016-06-07 12:28:16 -0700760 Value: &Variable{
761 Name: "foo",
762 NamePos: mkpos(68, 6, 10),
763 Value: &String{
764 LiteralPos: mkpos(9, 2, 9),
765 Value: "stuff",
766 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800767 },
Colin Crosse32cc802016-06-07 12:28:16 -0700768 OrigValue: &Variable{
769 Name: "foo",
770 NamePos: mkpos(68, 6, 10),
771 Value: &String{
772 LiteralPos: mkpos(9, 2, 9),
773 Value: "stuff",
774 },
Colin Crossb274e6c2015-02-04 10:50:22 -0800775 },
776 Assigner: "+=",
Colin Crossd1facc12015-01-08 14:56:03 -0800777 },
778 },
779 nil,
780 },
Nan Zhangf5865442017-11-01 14:03:28 -0700781
782 {`
783 baz = -4 + -5 + 6
784 `,
785 []Definition{
786 &Assignment{
787 Name: "baz",
788 NamePos: mkpos(3, 2, 3),
789 EqualsPos: mkpos(7, 2, 7),
790 Value: &Operator{
791 OperatorPos: mkpos(12, 2, 12),
792 Operator: '+',
793 Value: &Int64{
794 LiteralPos: mkpos(9, 2, 9),
795 Value: -3,
796 },
797 Args: [2]Expression{
798 &Int64{
799 LiteralPos: mkpos(9, 2, 9),
800 Value: -4,
Colin Crossfdeaf882018-03-21 17:00:39 -0700801 Token: "-4",
Nan Zhangf5865442017-11-01 14:03:28 -0700802 },
803 &Operator{
804 OperatorPos: mkpos(17, 2, 17),
805 Operator: '+',
806 Value: &Int64{
807 LiteralPos: mkpos(14, 2, 14),
808 Value: 1,
809 },
810 Args: [2]Expression{
811 &Int64{
812 LiteralPos: mkpos(14, 2, 14),
813 Value: -5,
Colin Crossfdeaf882018-03-21 17:00:39 -0700814 Token: "-5",
Nan Zhangf5865442017-11-01 14:03:28 -0700815 },
816 &Int64{
817 LiteralPos: mkpos(19, 2, 19),
818 Value: 6,
Colin Crossfdeaf882018-03-21 17:00:39 -0700819 Token: "6",
Nan Zhangf5865442017-11-01 14:03:28 -0700820 },
821 },
822 },
823 },
824 },
825 OrigValue: &Operator{
826 OperatorPos: mkpos(12, 2, 12),
827 Operator: '+',
828 Value: &Int64{
829 LiteralPos: mkpos(9, 2, 9),
830 Value: -3,
831 },
832 Args: [2]Expression{
833 &Int64{
834 LiteralPos: mkpos(9, 2, 9),
835 Value: -4,
Colin Crossfdeaf882018-03-21 17:00:39 -0700836 Token: "-4",
Nan Zhangf5865442017-11-01 14:03:28 -0700837 },
838 &Operator{
839 OperatorPos: mkpos(17, 2, 17),
840 Operator: '+',
841 Value: &Int64{
842 LiteralPos: mkpos(14, 2, 14),
843 Value: 1,
844 },
845 Args: [2]Expression{
846 &Int64{
847 LiteralPos: mkpos(14, 2, 14),
848 Value: -5,
Colin Crossfdeaf882018-03-21 17:00:39 -0700849 Token: "-5",
Nan Zhangf5865442017-11-01 14:03:28 -0700850 },
851 &Int64{
852 LiteralPos: mkpos(19, 2, 19),
853 Value: 6,
Colin Crossfdeaf882018-03-21 17:00:39 -0700854 Token: "6",
Nan Zhangf5865442017-11-01 14:03:28 -0700855 },
856 },
857 },
858 },
859 },
860 Assigner: "=",
861 Referenced: false,
862 },
863 },
864 nil,
865 },
866
867 {`
868 foo = 1000000
869 bar = foo
870 baz = foo + bar
871 boo = baz
872 boo += foo
873 `,
874 []Definition{
875 &Assignment{
876 Name: "foo",
877 NamePos: mkpos(3, 2, 3),
878 EqualsPos: mkpos(7, 2, 7),
879 Value: &Int64{
880 LiteralPos: mkpos(9, 2, 9),
881 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700882 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700883 },
884 OrigValue: &Int64{
885 LiteralPos: mkpos(9, 2, 9),
886 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700887 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700888 },
889 Assigner: "=",
890 Referenced: true,
891 },
892 &Assignment{
893 Name: "bar",
894 NamePos: mkpos(19, 3, 3),
895 EqualsPos: mkpos(23, 3, 7),
896 Value: &Variable{
897 Name: "foo",
898 NamePos: mkpos(25, 3, 9),
899 Value: &Int64{
900 LiteralPos: mkpos(9, 2, 9),
901 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700902 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700903 },
904 },
905 OrigValue: &Variable{
906 Name: "foo",
907 NamePos: mkpos(25, 3, 9),
908 Value: &Int64{
909 LiteralPos: mkpos(9, 2, 9),
910 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700911 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700912 },
913 },
914 Assigner: "=",
915 Referenced: true,
916 },
917 &Assignment{
918 Name: "baz",
919 NamePos: mkpos(31, 4, 3),
920 EqualsPos: mkpos(35, 4, 7),
921 Value: &Operator{
922 OperatorPos: mkpos(41, 4, 13),
923 Operator: '+',
924 Value: &Int64{
925 LiteralPos: mkpos(9, 2, 9),
926 Value: 2000000,
927 },
928 Args: [2]Expression{
929 &Variable{
930 Name: "foo",
931 NamePos: mkpos(37, 4, 9),
932 Value: &Int64{
933 LiteralPos: mkpos(9, 2, 9),
934 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700935 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700936 },
937 },
938 &Variable{
939 Name: "bar",
940 NamePos: mkpos(43, 4, 15),
941 Value: &Variable{
942 Name: "foo",
943 NamePos: mkpos(25, 3, 9),
944 Value: &Int64{
945 LiteralPos: mkpos(9, 2, 9),
946 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700947 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700948 },
949 },
950 },
951 },
952 },
953 OrigValue: &Operator{
954 OperatorPos: mkpos(41, 4, 13),
955 Operator: '+',
956 Value: &Int64{
957 LiteralPos: mkpos(9, 2, 9),
958 Value: 2000000,
959 },
960 Args: [2]Expression{
961 &Variable{
962 Name: "foo",
963 NamePos: mkpos(37, 4, 9),
964 Value: &Int64{
965 LiteralPos: mkpos(9, 2, 9),
966 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700967 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700968 },
969 },
970 &Variable{
971 Name: "bar",
972 NamePos: mkpos(43, 4, 15),
973 Value: &Variable{
974 Name: "foo",
975 NamePos: mkpos(25, 3, 9),
976 Value: &Int64{
977 LiteralPos: mkpos(9, 2, 9),
978 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -0700979 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -0700980 },
981 },
982 },
983 },
984 },
985 Assigner: "=",
986 Referenced: true,
987 },
988 &Assignment{
989 Name: "boo",
990 NamePos: mkpos(49, 5, 3),
991 EqualsPos: mkpos(53, 5, 7),
992 Value: &Operator{
993 Args: [2]Expression{
994 &Variable{
995 Name: "baz",
996 NamePos: mkpos(55, 5, 9),
997 Value: &Operator{
998 OperatorPos: mkpos(41, 4, 13),
999 Operator: '+',
1000 Value: &Int64{
1001 LiteralPos: mkpos(9, 2, 9),
1002 Value: 2000000,
1003 },
1004 Args: [2]Expression{
1005 &Variable{
1006 Name: "foo",
1007 NamePos: mkpos(37, 4, 9),
1008 Value: &Int64{
1009 LiteralPos: mkpos(9, 2, 9),
1010 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001011 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001012 },
1013 },
1014 &Variable{
1015 Name: "bar",
1016 NamePos: mkpos(43, 4, 15),
1017 Value: &Variable{
1018 Name: "foo",
1019 NamePos: mkpos(25, 3, 9),
1020 Value: &Int64{
1021 LiteralPos: mkpos(9, 2, 9),
1022 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001023 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001024 },
1025 },
1026 },
1027 },
1028 },
1029 },
1030 &Variable{
1031 Name: "foo",
1032 NamePos: mkpos(68, 6, 10),
1033 Value: &Int64{
1034 LiteralPos: mkpos(9, 2, 9),
1035 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001036 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001037 },
1038 },
1039 },
1040 OperatorPos: mkpos(66, 6, 8),
1041 Operator: '+',
1042 Value: &Int64{
1043 LiteralPos: mkpos(9, 2, 9),
1044 Value: 3000000,
1045 },
1046 },
1047 OrigValue: &Variable{
1048 Name: "baz",
1049 NamePos: mkpos(55, 5, 9),
1050 Value: &Operator{
1051 OperatorPos: mkpos(41, 4, 13),
1052 Operator: '+',
1053 Value: &Int64{
1054 LiteralPos: mkpos(9, 2, 9),
1055 Value: 2000000,
1056 },
1057 Args: [2]Expression{
1058 &Variable{
1059 Name: "foo",
1060 NamePos: mkpos(37, 4, 9),
1061 Value: &Int64{
1062 LiteralPos: mkpos(9, 2, 9),
1063 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001064 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001065 },
1066 },
1067 &Variable{
1068 Name: "bar",
1069 NamePos: mkpos(43, 4, 15),
1070 Value: &Variable{
1071 Name: "foo",
1072 NamePos: mkpos(25, 3, 9),
1073 Value: &Int64{
1074 LiteralPos: mkpos(9, 2, 9),
1075 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001076 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001077 },
1078 },
1079 },
1080 },
1081 },
1082 },
1083 Assigner: "=",
1084 },
1085 &Assignment{
1086 Name: "boo",
1087 NamePos: mkpos(61, 6, 3),
1088 EqualsPos: mkpos(66, 6, 8),
1089 Value: &Variable{
1090 Name: "foo",
1091 NamePos: mkpos(68, 6, 10),
1092 Value: &Int64{
1093 LiteralPos: mkpos(9, 2, 9),
1094 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001095 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001096 },
1097 },
1098 OrigValue: &Variable{
1099 Name: "foo",
1100 NamePos: mkpos(68, 6, 10),
1101 Value: &Int64{
1102 LiteralPos: mkpos(9, 2, 9),
1103 Value: 1000000,
Colin Crossfdeaf882018-03-21 17:00:39 -07001104 Token: "1000000",
Nan Zhangf5865442017-11-01 14:03:28 -07001105 },
1106 },
1107 Assigner: "+=",
1108 },
1109 },
1110 nil,
1111 },
1112
Colin Cross1e737942016-06-10 17:27:12 -07001113 {`
1114 // comment1
1115 // comment2
1116
1117 /* comment3
1118 comment4 */
1119 // comment5
1120
1121 /* comment6 */ /* comment7 */ // comment8
1122 `,
1123 nil,
1124 []*CommentGroup{
1125 {
1126 Comments: []*Comment{
1127 &Comment{
1128 Comment: []string{"// comment1"},
1129 Slash: mkpos(3, 2, 3),
1130 },
1131 &Comment{
1132 Comment: []string{"// comment2"},
1133 Slash: mkpos(17, 3, 3),
1134 },
1135 },
1136 },
1137 {
1138 Comments: []*Comment{
1139 &Comment{
1140 Comment: []string{"/* comment3", " comment4 */"},
1141 Slash: mkpos(32, 5, 3),
1142 },
1143 &Comment{
1144 Comment: []string{"// comment5"},
1145 Slash: mkpos(63, 7, 3),
1146 },
1147 },
1148 },
1149 {
1150 Comments: []*Comment{
1151 &Comment{
1152 Comment: []string{"/* comment6 */"},
1153 Slash: mkpos(78, 9, 3),
1154 },
1155 &Comment{
1156 Comment: []string{"/* comment7 */"},
1157 Slash: mkpos(93, 9, 18),
1158 },
1159 &Comment{
1160 Comment: []string{"// comment8"},
1161 Slash: mkpos(108, 9, 33),
1162 },
1163 },
1164 },
1165 },
1166 },
Jamie Gennis1bc967e2014-05-27 16:34:41 -07001167}
1168
1169func TestParseValidInput(t *testing.T) {
Colin Crossfdeaf882018-03-21 17:00:39 -07001170 for i, testCase := range validParseTestCases {
1171 t.Run(strconv.Itoa(i), func(t *testing.T) {
1172 r := bytes.NewBufferString(testCase.input)
1173 file, errs := ParseAndEval("", r, NewScope(nil))
1174 if len(errs) != 0 {
1175 t.Errorf("test case: %s", testCase.input)
1176 t.Errorf("unexpected errors:")
1177 for _, err := range errs {
1178 t.Errorf(" %s", err)
Colin Crossd1facc12015-01-08 14:56:03 -08001179 }
Colin Crossfdeaf882018-03-21 17:00:39 -07001180 t.FailNow()
Colin Crossd1facc12015-01-08 14:56:03 -08001181 }
Colin Crossd1facc12015-01-08 14:56:03 -08001182
Colin Crossfdeaf882018-03-21 17:00:39 -07001183 if len(file.Defs) == len(testCase.defs) {
1184 for i := range file.Defs {
1185 if !reflect.DeepEqual(file.Defs[i], testCase.defs[i]) {
1186 t.Errorf("test case: %s", testCase.input)
Sasha Smundak29fdcad2020-02-11 22:39:47 -08001187 t.Errorf("incorrect definition %d:", i)
Colin Crossfdeaf882018-03-21 17:00:39 -07001188 t.Errorf(" expected: %s", testCase.defs[i])
1189 t.Errorf(" got: %s", file.Defs[i])
1190 }
Colin Crossd1facc12015-01-08 14:56:03 -08001191 }
Colin Crossfdeaf882018-03-21 17:00:39 -07001192 } else {
1193 t.Errorf("test case: %s", testCase.input)
1194 t.Errorf("length mismatch, expected %d definitions, got %d",
1195 len(testCase.defs), len(file.Defs))
Colin Crossd1facc12015-01-08 14:56:03 -08001196 }
Colin Crossfdeaf882018-03-21 17:00:39 -07001197
1198 if len(file.Comments) == len(testCase.comments) {
1199 for i := range file.Comments {
1200 if !reflect.DeepEqual(file.Comments[i], testCase.comments[i]) {
1201 t.Errorf("test case: %s", testCase.input)
1202 t.Errorf("incorrect comment %d:", i)
1203 t.Errorf(" expected: %s", testCase.comments[i])
1204 t.Errorf(" got: %s", file.Comments[i])
1205 }
1206 }
1207 } else {
1208 t.Errorf("test case: %s", testCase.input)
1209 t.Errorf("length mismatch, expected %d comments, got %d",
1210 len(testCase.comments), len(file.Comments))
1211 }
1212 })
Jamie Gennis1bc967e2014-05-27 16:34:41 -07001213 }
1214}
1215
1216// TODO: Test error strings
Colin Crossfdeaf882018-03-21 17:00:39 -07001217
1218func TestParserEndPos(t *testing.T) {
1219 in := `
1220 module {
1221 string: "string",
1222 stringexp: "string1" + "string2",
1223 int: -1,
1224 intexp: -1 + 2,
1225 list: ["a", "b"],
1226 listexp: ["c"] + ["d"],
1227 multilinelist: [
1228 "e",
1229 "f",
1230 ],
1231 map: {
1232 prop: "abc",
1233 },
1234 }
1235 `
1236
1237 // Strip each line to make it easier to compute the previous "," from each property
1238 lines := strings.Split(in, "\n")
1239 for i := range lines {
1240 lines[i] = strings.TrimSpace(lines[i])
1241 }
1242 in = strings.Join(lines, "\n")
1243
1244 r := bytes.NewBufferString(in)
1245
1246 file, errs := ParseAndEval("", r, NewScope(nil))
1247 if len(errs) != 0 {
1248 t.Errorf("unexpected errors:")
1249 for _, err := range errs {
1250 t.Errorf(" %s", err)
1251 }
1252 t.FailNow()
1253 }
1254
1255 mod := file.Defs[0].(*Module)
1256 modEnd := mkpos(len(in)-1, len(lines)-1, 2)
1257 if mod.End() != modEnd {
1258 t.Errorf("expected mod.End() %s, got %s", modEnd, mod.End())
1259 }
1260
1261 nextPos := make([]scanner.Position, len(mod.Properties))
1262 for i := 0; i < len(mod.Properties)-1; i++ {
1263 nextPos[i] = mod.Properties[i+1].Pos()
1264 }
1265 nextPos[len(mod.Properties)-1] = mod.RBracePos
1266
1267 for i, cur := range mod.Properties {
1268 endOffset := nextPos[i].Offset - len(",\n")
1269 endLine := nextPos[i].Line - 1
1270 endColumn := len(lines[endLine-1]) // scanner.Position.Line is starts at 1
1271 endPos := mkpos(endOffset, endLine, endColumn)
1272 if cur.End() != endPos {
1273 t.Errorf("expected property %s End() %s@%d, got %s@%d", cur.Name, endPos, endPos.Offset, cur.End(), cur.End().Offset)
1274 }
1275 }
1276}
Sasha Smundak77418b72020-01-21 13:31:06 -08001277
1278func TestParserNotEvaluated(t *testing.T) {
1279 // When parsing without evaluation, create variables correctly
1280 scope := NewScope(nil)
1281 input := "FOO=abc\n"
1282 _, errs := Parse("", bytes.NewBufferString(input), scope)
1283 if errs != nil {
1284 t.Errorf("unexpected errors:")
1285 for _, err := range errs {
1286 t.Errorf(" %s", err)
1287 }
1288 t.FailNow()
1289 }
1290 assignment, found := scope.Get("FOO")
1291 if !found {
1292 t.Fatalf("Expected to find FOO after parsing %s", input)
1293 }
1294 if s := assignment.String(); strings.Contains(s, "PANIC") {
1295 t.Errorf("Attempt to print FOO returned %s", s)
1296 }
1297}