xref: /aosp_15_r20/build/blueprint/parser/parser_test.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage parser
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"bytes"
19*1fa6dee9SAndroid Build Coastguard Worker	"errors"
20*1fa6dee9SAndroid Build Coastguard Worker	"reflect"
21*1fa6dee9SAndroid Build Coastguard Worker	"strconv"
22*1fa6dee9SAndroid Build Coastguard Worker	"strings"
23*1fa6dee9SAndroid Build Coastguard Worker	"testing"
24*1fa6dee9SAndroid Build Coastguard Worker	"text/scanner"
25*1fa6dee9SAndroid Build Coastguard Worker)
26*1fa6dee9SAndroid Build Coastguard Worker
27*1fa6dee9SAndroid Build Coastguard Workerfunc mkpos(offset, line, column int) scanner.Position {
28*1fa6dee9SAndroid Build Coastguard Worker	return scanner.Position{
29*1fa6dee9SAndroid Build Coastguard Worker		Offset: offset,
30*1fa6dee9SAndroid Build Coastguard Worker		Line:   line,
31*1fa6dee9SAndroid Build Coastguard Worker		Column: column,
32*1fa6dee9SAndroid Build Coastguard Worker	}
33*1fa6dee9SAndroid Build Coastguard Worker}
34*1fa6dee9SAndroid Build Coastguard Worker
35*1fa6dee9SAndroid Build Coastguard Workervar validParseTestCases = []struct {
36*1fa6dee9SAndroid Build Coastguard Worker	input    string
37*1fa6dee9SAndroid Build Coastguard Worker	defs     []Definition
38*1fa6dee9SAndroid Build Coastguard Worker	comments []*CommentGroup
39*1fa6dee9SAndroid Build Coastguard Worker}{
40*1fa6dee9SAndroid Build Coastguard Worker	{`
41*1fa6dee9SAndroid Build Coastguard Worker		foo {}
42*1fa6dee9SAndroid Build Coastguard Worker		`,
43*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
44*1fa6dee9SAndroid Build Coastguard Worker			&Module{
45*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
46*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
47*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
48*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
49*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(8, 2, 8),
50*1fa6dee9SAndroid Build Coastguard Worker				},
51*1fa6dee9SAndroid Build Coastguard Worker			},
52*1fa6dee9SAndroid Build Coastguard Worker		},
53*1fa6dee9SAndroid Build Coastguard Worker		nil,
54*1fa6dee9SAndroid Build Coastguard Worker	},
55*1fa6dee9SAndroid Build Coastguard Worker
56*1fa6dee9SAndroid Build Coastguard Worker	{`
57*1fa6dee9SAndroid Build Coastguard Worker		foo {
58*1fa6dee9SAndroid Build Coastguard Worker			name: "abc",
59*1fa6dee9SAndroid Build Coastguard Worker		}
60*1fa6dee9SAndroid Build Coastguard Worker		`,
61*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
62*1fa6dee9SAndroid Build Coastguard Worker			&Module{
63*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
64*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
65*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
66*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
67*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(27, 4, 3),
68*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
69*1fa6dee9SAndroid Build Coastguard Worker						{
70*1fa6dee9SAndroid Build Coastguard Worker							Name:     "name",
71*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
72*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(16, 3, 8),
73*1fa6dee9SAndroid Build Coastguard Worker							Value: &String{
74*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(18, 3, 10),
75*1fa6dee9SAndroid Build Coastguard Worker								Value:      "abc",
76*1fa6dee9SAndroid Build Coastguard Worker							},
77*1fa6dee9SAndroid Build Coastguard Worker						},
78*1fa6dee9SAndroid Build Coastguard Worker					},
79*1fa6dee9SAndroid Build Coastguard Worker				},
80*1fa6dee9SAndroid Build Coastguard Worker			},
81*1fa6dee9SAndroid Build Coastguard Worker		},
82*1fa6dee9SAndroid Build Coastguard Worker		nil,
83*1fa6dee9SAndroid Build Coastguard Worker	},
84*1fa6dee9SAndroid Build Coastguard Worker
85*1fa6dee9SAndroid Build Coastguard Worker	{`
86*1fa6dee9SAndroid Build Coastguard Worker		foo {
87*1fa6dee9SAndroid Build Coastguard Worker			isGood: true,
88*1fa6dee9SAndroid Build Coastguard Worker		}
89*1fa6dee9SAndroid Build Coastguard Worker		`,
90*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
91*1fa6dee9SAndroid Build Coastguard Worker			&Module{
92*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
93*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
94*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
95*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
96*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(28, 4, 3),
97*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
98*1fa6dee9SAndroid Build Coastguard Worker						{
99*1fa6dee9SAndroid Build Coastguard Worker							Name:     "isGood",
100*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
101*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(18, 3, 10),
102*1fa6dee9SAndroid Build Coastguard Worker							Value: &Bool{
103*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(20, 3, 12),
104*1fa6dee9SAndroid Build Coastguard Worker								Value:      true,
105*1fa6dee9SAndroid Build Coastguard Worker								Token:      "true",
106*1fa6dee9SAndroid Build Coastguard Worker							},
107*1fa6dee9SAndroid Build Coastguard Worker						},
108*1fa6dee9SAndroid Build Coastguard Worker					},
109*1fa6dee9SAndroid Build Coastguard Worker				},
110*1fa6dee9SAndroid Build Coastguard Worker			},
111*1fa6dee9SAndroid Build Coastguard Worker		},
112*1fa6dee9SAndroid Build Coastguard Worker		nil,
113*1fa6dee9SAndroid Build Coastguard Worker	},
114*1fa6dee9SAndroid Build Coastguard Worker
115*1fa6dee9SAndroid Build Coastguard Worker	{`
116*1fa6dee9SAndroid Build Coastguard Worker		foo {
117*1fa6dee9SAndroid Build Coastguard Worker			num: 4,
118*1fa6dee9SAndroid Build Coastguard Worker		}
119*1fa6dee9SAndroid Build Coastguard Worker		`,
120*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
121*1fa6dee9SAndroid Build Coastguard Worker			&Module{
122*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
123*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
124*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
125*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
126*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(22, 4, 3),
127*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
128*1fa6dee9SAndroid Build Coastguard Worker						{
129*1fa6dee9SAndroid Build Coastguard Worker							Name:     "num",
130*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
131*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(15, 3, 7),
132*1fa6dee9SAndroid Build Coastguard Worker							Value: &Int64{
133*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(17, 3, 9),
134*1fa6dee9SAndroid Build Coastguard Worker								Value:      4,
135*1fa6dee9SAndroid Build Coastguard Worker								Token:      "4",
136*1fa6dee9SAndroid Build Coastguard Worker							},
137*1fa6dee9SAndroid Build Coastguard Worker						},
138*1fa6dee9SAndroid Build Coastguard Worker					},
139*1fa6dee9SAndroid Build Coastguard Worker				},
140*1fa6dee9SAndroid Build Coastguard Worker			},
141*1fa6dee9SAndroid Build Coastguard Worker		},
142*1fa6dee9SAndroid Build Coastguard Worker		nil,
143*1fa6dee9SAndroid Build Coastguard Worker	},
144*1fa6dee9SAndroid Build Coastguard Worker
145*1fa6dee9SAndroid Build Coastguard Worker	{`
146*1fa6dee9SAndroid Build Coastguard Worker		foo {
147*1fa6dee9SAndroid Build Coastguard Worker			stuff: ["asdf", "jkl;", "qwert",
148*1fa6dee9SAndroid Build Coastguard Worker				"uiop", ` + "`bnm,\n`" +
149*1fa6dee9SAndroid Build Coastguard Worker		`]
150*1fa6dee9SAndroid Build Coastguard Worker		}
151*1fa6dee9SAndroid Build Coastguard Worker		`,
152*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
153*1fa6dee9SAndroid Build Coastguard Worker			&Module{
154*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
155*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
156*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
157*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
158*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(68, 6, 3),
159*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
160*1fa6dee9SAndroid Build Coastguard Worker						{
161*1fa6dee9SAndroid Build Coastguard Worker							Name:     "stuff",
162*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
163*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(17, 3, 9),
164*1fa6dee9SAndroid Build Coastguard Worker							Value: &List{
165*1fa6dee9SAndroid Build Coastguard Worker								LBracePos: mkpos(19, 3, 11),
166*1fa6dee9SAndroid Build Coastguard Worker								RBracePos: mkpos(64, 5, 2),
167*1fa6dee9SAndroid Build Coastguard Worker								Values: []Expression{
168*1fa6dee9SAndroid Build Coastguard Worker									&String{
169*1fa6dee9SAndroid Build Coastguard Worker										LiteralPos: mkpos(20, 3, 12),
170*1fa6dee9SAndroid Build Coastguard Worker										Value:      "asdf",
171*1fa6dee9SAndroid Build Coastguard Worker									},
172*1fa6dee9SAndroid Build Coastguard Worker									&String{
173*1fa6dee9SAndroid Build Coastguard Worker										LiteralPos: mkpos(28, 3, 20),
174*1fa6dee9SAndroid Build Coastguard Worker										Value:      "jkl;",
175*1fa6dee9SAndroid Build Coastguard Worker									},
176*1fa6dee9SAndroid Build Coastguard Worker									&String{
177*1fa6dee9SAndroid Build Coastguard Worker										LiteralPos: mkpos(36, 3, 28),
178*1fa6dee9SAndroid Build Coastguard Worker										Value:      "qwert",
179*1fa6dee9SAndroid Build Coastguard Worker									},
180*1fa6dee9SAndroid Build Coastguard Worker									&String{
181*1fa6dee9SAndroid Build Coastguard Worker										LiteralPos: mkpos(49, 4, 5),
182*1fa6dee9SAndroid Build Coastguard Worker										Value:      "uiop",
183*1fa6dee9SAndroid Build Coastguard Worker									},
184*1fa6dee9SAndroid Build Coastguard Worker									&String{
185*1fa6dee9SAndroid Build Coastguard Worker										LiteralPos: mkpos(57, 4, 13),
186*1fa6dee9SAndroid Build Coastguard Worker										Value:      "bnm,\n",
187*1fa6dee9SAndroid Build Coastguard Worker									},
188*1fa6dee9SAndroid Build Coastguard Worker								},
189*1fa6dee9SAndroid Build Coastguard Worker							},
190*1fa6dee9SAndroid Build Coastguard Worker						},
191*1fa6dee9SAndroid Build Coastguard Worker					},
192*1fa6dee9SAndroid Build Coastguard Worker				},
193*1fa6dee9SAndroid Build Coastguard Worker			},
194*1fa6dee9SAndroid Build Coastguard Worker		},
195*1fa6dee9SAndroid Build Coastguard Worker		nil,
196*1fa6dee9SAndroid Build Coastguard Worker	},
197*1fa6dee9SAndroid Build Coastguard Worker
198*1fa6dee9SAndroid Build Coastguard Worker	{
199*1fa6dee9SAndroid Build Coastguard Worker		`
200*1fa6dee9SAndroid Build Coastguard Worker		foo {
201*1fa6dee9SAndroid Build Coastguard Worker			list_of_maps: [
202*1fa6dee9SAndroid Build Coastguard Worker				{
203*1fa6dee9SAndroid Build Coastguard Worker					var: true,
204*1fa6dee9SAndroid Build Coastguard Worker					name: "a",
205*1fa6dee9SAndroid Build Coastguard Worker				},
206*1fa6dee9SAndroid Build Coastguard Worker				{
207*1fa6dee9SAndroid Build Coastguard Worker					var: false,
208*1fa6dee9SAndroid Build Coastguard Worker					name: "b",
209*1fa6dee9SAndroid Build Coastguard Worker				},
210*1fa6dee9SAndroid Build Coastguard Worker			],
211*1fa6dee9SAndroid Build Coastguard Worker		}
212*1fa6dee9SAndroid Build Coastguard Worker`,
213*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
214*1fa6dee9SAndroid Build Coastguard Worker			&Module{
215*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
216*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
217*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
218*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
219*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(127, 13, 3),
220*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
221*1fa6dee9SAndroid Build Coastguard Worker						{
222*1fa6dee9SAndroid Build Coastguard Worker							Name:     "list_of_maps",
223*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
224*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(24, 3, 16),
225*1fa6dee9SAndroid Build Coastguard Worker							Value: &List{
226*1fa6dee9SAndroid Build Coastguard Worker								LBracePos: mkpos(26, 3, 18),
227*1fa6dee9SAndroid Build Coastguard Worker								RBracePos: mkpos(122, 12, 4),
228*1fa6dee9SAndroid Build Coastguard Worker								Values: []Expression{
229*1fa6dee9SAndroid Build Coastguard Worker									&Map{
230*1fa6dee9SAndroid Build Coastguard Worker										LBracePos: mkpos(32, 4, 5),
231*1fa6dee9SAndroid Build Coastguard Worker										RBracePos: mkpos(70, 7, 5),
232*1fa6dee9SAndroid Build Coastguard Worker										Properties: []*Property{
233*1fa6dee9SAndroid Build Coastguard Worker											{
234*1fa6dee9SAndroid Build Coastguard Worker												Name:     "var",
235*1fa6dee9SAndroid Build Coastguard Worker												NamePos:  mkpos(39, 5, 6),
236*1fa6dee9SAndroid Build Coastguard Worker												ColonPos: mkpos(42, 5, 9),
237*1fa6dee9SAndroid Build Coastguard Worker												Value: &Bool{
238*1fa6dee9SAndroid Build Coastguard Worker													LiteralPos: mkpos(44, 5, 11),
239*1fa6dee9SAndroid Build Coastguard Worker													Value:      true,
240*1fa6dee9SAndroid Build Coastguard Worker													Token:      "true",
241*1fa6dee9SAndroid Build Coastguard Worker												},
242*1fa6dee9SAndroid Build Coastguard Worker											},
243*1fa6dee9SAndroid Build Coastguard Worker											{
244*1fa6dee9SAndroid Build Coastguard Worker												Name:     "name",
245*1fa6dee9SAndroid Build Coastguard Worker												NamePos:  mkpos(55, 6, 6),
246*1fa6dee9SAndroid Build Coastguard Worker												ColonPos: mkpos(59, 6, 10),
247*1fa6dee9SAndroid Build Coastguard Worker												Value: &String{
248*1fa6dee9SAndroid Build Coastguard Worker													LiteralPos: mkpos(61, 6, 12),
249*1fa6dee9SAndroid Build Coastguard Worker													Value:      "a",
250*1fa6dee9SAndroid Build Coastguard Worker												},
251*1fa6dee9SAndroid Build Coastguard Worker											},
252*1fa6dee9SAndroid Build Coastguard Worker										},
253*1fa6dee9SAndroid Build Coastguard Worker									},
254*1fa6dee9SAndroid Build Coastguard Worker									&Map{
255*1fa6dee9SAndroid Build Coastguard Worker										LBracePos: mkpos(77, 8, 5),
256*1fa6dee9SAndroid Build Coastguard Worker										RBracePos: mkpos(116, 11, 5),
257*1fa6dee9SAndroid Build Coastguard Worker										Properties: []*Property{
258*1fa6dee9SAndroid Build Coastguard Worker											{
259*1fa6dee9SAndroid Build Coastguard Worker												Name:     "var",
260*1fa6dee9SAndroid Build Coastguard Worker												NamePos:  mkpos(84, 9, 6),
261*1fa6dee9SAndroid Build Coastguard Worker												ColonPos: mkpos(87, 9, 9),
262*1fa6dee9SAndroid Build Coastguard Worker												Value: &Bool{
263*1fa6dee9SAndroid Build Coastguard Worker													LiteralPos: mkpos(89, 9, 11),
264*1fa6dee9SAndroid Build Coastguard Worker													Value:      false,
265*1fa6dee9SAndroid Build Coastguard Worker													Token:      "false",
266*1fa6dee9SAndroid Build Coastguard Worker												},
267*1fa6dee9SAndroid Build Coastguard Worker											},
268*1fa6dee9SAndroid Build Coastguard Worker											{
269*1fa6dee9SAndroid Build Coastguard Worker												Name:     "name",
270*1fa6dee9SAndroid Build Coastguard Worker												NamePos:  mkpos(101, 10, 6),
271*1fa6dee9SAndroid Build Coastguard Worker												ColonPos: mkpos(105, 10, 10),
272*1fa6dee9SAndroid Build Coastguard Worker												Value: &String{
273*1fa6dee9SAndroid Build Coastguard Worker													LiteralPos: mkpos(107, 10, 12),
274*1fa6dee9SAndroid Build Coastguard Worker													Value:      "b",
275*1fa6dee9SAndroid Build Coastguard Worker												},
276*1fa6dee9SAndroid Build Coastguard Worker											},
277*1fa6dee9SAndroid Build Coastguard Worker										},
278*1fa6dee9SAndroid Build Coastguard Worker									},
279*1fa6dee9SAndroid Build Coastguard Worker								},
280*1fa6dee9SAndroid Build Coastguard Worker							},
281*1fa6dee9SAndroid Build Coastguard Worker						},
282*1fa6dee9SAndroid Build Coastguard Worker					},
283*1fa6dee9SAndroid Build Coastguard Worker				},
284*1fa6dee9SAndroid Build Coastguard Worker			},
285*1fa6dee9SAndroid Build Coastguard Worker		},
286*1fa6dee9SAndroid Build Coastguard Worker		nil,
287*1fa6dee9SAndroid Build Coastguard Worker	},
288*1fa6dee9SAndroid Build Coastguard Worker	{
289*1fa6dee9SAndroid Build Coastguard Worker		`
290*1fa6dee9SAndroid Build Coastguard Worker		foo {
291*1fa6dee9SAndroid Build Coastguard Worker			list_of_lists: [
292*1fa6dee9SAndroid Build Coastguard Worker				[ "a", "b" ],
293*1fa6dee9SAndroid Build Coastguard Worker				[ "c", "d" ]
294*1fa6dee9SAndroid Build Coastguard Worker			],
295*1fa6dee9SAndroid Build Coastguard Worker		}
296*1fa6dee9SAndroid Build Coastguard Worker`,
297*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
298*1fa6dee9SAndroid Build Coastguard Worker			&Module{
299*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
300*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
301*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
302*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
303*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(72, 7, 3),
304*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
305*1fa6dee9SAndroid Build Coastguard Worker						{
306*1fa6dee9SAndroid Build Coastguard Worker							Name:     "list_of_lists",
307*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
308*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(25, 3, 17),
309*1fa6dee9SAndroid Build Coastguard Worker							Value: &List{
310*1fa6dee9SAndroid Build Coastguard Worker								LBracePos: mkpos(27, 3, 19),
311*1fa6dee9SAndroid Build Coastguard Worker								RBracePos: mkpos(67, 6, 4),
312*1fa6dee9SAndroid Build Coastguard Worker								Values: []Expression{
313*1fa6dee9SAndroid Build Coastguard Worker									&List{
314*1fa6dee9SAndroid Build Coastguard Worker										LBracePos: mkpos(33, 4, 5),
315*1fa6dee9SAndroid Build Coastguard Worker										RBracePos: mkpos(44, 4, 16),
316*1fa6dee9SAndroid Build Coastguard Worker										Values: []Expression{
317*1fa6dee9SAndroid Build Coastguard Worker											&String{
318*1fa6dee9SAndroid Build Coastguard Worker												LiteralPos: mkpos(35, 4, 7),
319*1fa6dee9SAndroid Build Coastguard Worker												Value:      "a",
320*1fa6dee9SAndroid Build Coastguard Worker											},
321*1fa6dee9SAndroid Build Coastguard Worker											&String{
322*1fa6dee9SAndroid Build Coastguard Worker												LiteralPos: mkpos(40, 4, 12),
323*1fa6dee9SAndroid Build Coastguard Worker												Value:      "b",
324*1fa6dee9SAndroid Build Coastguard Worker											},
325*1fa6dee9SAndroid Build Coastguard Worker										},
326*1fa6dee9SAndroid Build Coastguard Worker									},
327*1fa6dee9SAndroid Build Coastguard Worker									&List{
328*1fa6dee9SAndroid Build Coastguard Worker										LBracePos: mkpos(51, 5, 5),
329*1fa6dee9SAndroid Build Coastguard Worker										RBracePos: mkpos(62, 5, 16),
330*1fa6dee9SAndroid Build Coastguard Worker										Values: []Expression{
331*1fa6dee9SAndroid Build Coastguard Worker											&String{
332*1fa6dee9SAndroid Build Coastguard Worker												LiteralPos: mkpos(53, 5, 7),
333*1fa6dee9SAndroid Build Coastguard Worker												Value:      "c",
334*1fa6dee9SAndroid Build Coastguard Worker											},
335*1fa6dee9SAndroid Build Coastguard Worker											&String{
336*1fa6dee9SAndroid Build Coastguard Worker												LiteralPos: mkpos(58, 5, 12),
337*1fa6dee9SAndroid Build Coastguard Worker												Value:      "d",
338*1fa6dee9SAndroid Build Coastguard Worker											},
339*1fa6dee9SAndroid Build Coastguard Worker										},
340*1fa6dee9SAndroid Build Coastguard Worker									},
341*1fa6dee9SAndroid Build Coastguard Worker								},
342*1fa6dee9SAndroid Build Coastguard Worker							},
343*1fa6dee9SAndroid Build Coastguard Worker						},
344*1fa6dee9SAndroid Build Coastguard Worker					},
345*1fa6dee9SAndroid Build Coastguard Worker				},
346*1fa6dee9SAndroid Build Coastguard Worker			},
347*1fa6dee9SAndroid Build Coastguard Worker		},
348*1fa6dee9SAndroid Build Coastguard Worker		nil,
349*1fa6dee9SAndroid Build Coastguard Worker	},
350*1fa6dee9SAndroid Build Coastguard Worker	{`
351*1fa6dee9SAndroid Build Coastguard Worker		foo {
352*1fa6dee9SAndroid Build Coastguard Worker			stuff: {
353*1fa6dee9SAndroid Build Coastguard Worker				isGood: true,
354*1fa6dee9SAndroid Build Coastguard Worker				name: "bar",
355*1fa6dee9SAndroid Build Coastguard Worker				num: 36,
356*1fa6dee9SAndroid Build Coastguard Worker			}
357*1fa6dee9SAndroid Build Coastguard Worker		}
358*1fa6dee9SAndroid Build Coastguard Worker		`,
359*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
360*1fa6dee9SAndroid Build Coastguard Worker			&Module{
361*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
362*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
363*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
364*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
365*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(76, 8, 3),
366*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
367*1fa6dee9SAndroid Build Coastguard Worker						{
368*1fa6dee9SAndroid Build Coastguard Worker							Name:     "stuff",
369*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
370*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(17, 3, 9),
371*1fa6dee9SAndroid Build Coastguard Worker							Value: &Map{
372*1fa6dee9SAndroid Build Coastguard Worker								LBracePos: mkpos(19, 3, 11),
373*1fa6dee9SAndroid Build Coastguard Worker								RBracePos: mkpos(72, 7, 4),
374*1fa6dee9SAndroid Build Coastguard Worker								Properties: []*Property{
375*1fa6dee9SAndroid Build Coastguard Worker									{
376*1fa6dee9SAndroid Build Coastguard Worker										Name:     "isGood",
377*1fa6dee9SAndroid Build Coastguard Worker										NamePos:  mkpos(25, 4, 5),
378*1fa6dee9SAndroid Build Coastguard Worker										ColonPos: mkpos(31, 4, 11),
379*1fa6dee9SAndroid Build Coastguard Worker										Value: &Bool{
380*1fa6dee9SAndroid Build Coastguard Worker											LiteralPos: mkpos(33, 4, 13),
381*1fa6dee9SAndroid Build Coastguard Worker											Value:      true,
382*1fa6dee9SAndroid Build Coastguard Worker											Token:      "true",
383*1fa6dee9SAndroid Build Coastguard Worker										},
384*1fa6dee9SAndroid Build Coastguard Worker									},
385*1fa6dee9SAndroid Build Coastguard Worker									{
386*1fa6dee9SAndroid Build Coastguard Worker										Name:     "name",
387*1fa6dee9SAndroid Build Coastguard Worker										NamePos:  mkpos(43, 5, 5),
388*1fa6dee9SAndroid Build Coastguard Worker										ColonPos: mkpos(47, 5, 9),
389*1fa6dee9SAndroid Build Coastguard Worker										Value: &String{
390*1fa6dee9SAndroid Build Coastguard Worker											LiteralPos: mkpos(49, 5, 11),
391*1fa6dee9SAndroid Build Coastguard Worker											Value:      "bar",
392*1fa6dee9SAndroid Build Coastguard Worker										},
393*1fa6dee9SAndroid Build Coastguard Worker									},
394*1fa6dee9SAndroid Build Coastguard Worker									{
395*1fa6dee9SAndroid Build Coastguard Worker										Name:     "num",
396*1fa6dee9SAndroid Build Coastguard Worker										NamePos:  mkpos(60, 6, 5),
397*1fa6dee9SAndroid Build Coastguard Worker										ColonPos: mkpos(63, 6, 8),
398*1fa6dee9SAndroid Build Coastguard Worker										Value: &Int64{
399*1fa6dee9SAndroid Build Coastguard Worker											LiteralPos: mkpos(65, 6, 10),
400*1fa6dee9SAndroid Build Coastguard Worker											Value:      36,
401*1fa6dee9SAndroid Build Coastguard Worker											Token:      "36",
402*1fa6dee9SAndroid Build Coastguard Worker										},
403*1fa6dee9SAndroid Build Coastguard Worker									},
404*1fa6dee9SAndroid Build Coastguard Worker								},
405*1fa6dee9SAndroid Build Coastguard Worker							},
406*1fa6dee9SAndroid Build Coastguard Worker						},
407*1fa6dee9SAndroid Build Coastguard Worker					},
408*1fa6dee9SAndroid Build Coastguard Worker				},
409*1fa6dee9SAndroid Build Coastguard Worker			},
410*1fa6dee9SAndroid Build Coastguard Worker		},
411*1fa6dee9SAndroid Build Coastguard Worker		nil,
412*1fa6dee9SAndroid Build Coastguard Worker	},
413*1fa6dee9SAndroid Build Coastguard Worker
414*1fa6dee9SAndroid Build Coastguard Worker	{`
415*1fa6dee9SAndroid Build Coastguard Worker		// comment1
416*1fa6dee9SAndroid Build Coastguard Worker		foo /* test */ {
417*1fa6dee9SAndroid Build Coastguard Worker			// comment2
418*1fa6dee9SAndroid Build Coastguard Worker			isGood: true,  // comment3
419*1fa6dee9SAndroid Build Coastguard Worker		}
420*1fa6dee9SAndroid Build Coastguard Worker		`,
421*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
422*1fa6dee9SAndroid Build Coastguard Worker			&Module{
423*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
424*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(17, 3, 3),
425*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
426*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(32, 3, 18),
427*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(81, 6, 3),
428*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
429*1fa6dee9SAndroid Build Coastguard Worker						{
430*1fa6dee9SAndroid Build Coastguard Worker							Name:     "isGood",
431*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(52, 5, 4),
432*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(58, 5, 10),
433*1fa6dee9SAndroid Build Coastguard Worker							Value: &Bool{
434*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(60, 5, 12),
435*1fa6dee9SAndroid Build Coastguard Worker								Value:      true,
436*1fa6dee9SAndroid Build Coastguard Worker								Token:      "true",
437*1fa6dee9SAndroid Build Coastguard Worker							},
438*1fa6dee9SAndroid Build Coastguard Worker						},
439*1fa6dee9SAndroid Build Coastguard Worker					},
440*1fa6dee9SAndroid Build Coastguard Worker				},
441*1fa6dee9SAndroid Build Coastguard Worker			},
442*1fa6dee9SAndroid Build Coastguard Worker		},
443*1fa6dee9SAndroid Build Coastguard Worker		[]*CommentGroup{
444*1fa6dee9SAndroid Build Coastguard Worker			{
445*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
446*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
447*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment1"},
448*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(3, 2, 3),
449*1fa6dee9SAndroid Build Coastguard Worker					},
450*1fa6dee9SAndroid Build Coastguard Worker				},
451*1fa6dee9SAndroid Build Coastguard Worker			},
452*1fa6dee9SAndroid Build Coastguard Worker			{
453*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
454*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
455*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"/* test */"},
456*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(21, 3, 7),
457*1fa6dee9SAndroid Build Coastguard Worker					},
458*1fa6dee9SAndroid Build Coastguard Worker				},
459*1fa6dee9SAndroid Build Coastguard Worker			},
460*1fa6dee9SAndroid Build Coastguard Worker			{
461*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
462*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
463*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment2"},
464*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(37, 4, 4),
465*1fa6dee9SAndroid Build Coastguard Worker					},
466*1fa6dee9SAndroid Build Coastguard Worker				},
467*1fa6dee9SAndroid Build Coastguard Worker			},
468*1fa6dee9SAndroid Build Coastguard Worker			{
469*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
470*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
471*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment3"},
472*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(67, 5, 19),
473*1fa6dee9SAndroid Build Coastguard Worker					},
474*1fa6dee9SAndroid Build Coastguard Worker				},
475*1fa6dee9SAndroid Build Coastguard Worker			},
476*1fa6dee9SAndroid Build Coastguard Worker		},
477*1fa6dee9SAndroid Build Coastguard Worker	},
478*1fa6dee9SAndroid Build Coastguard Worker
479*1fa6dee9SAndroid Build Coastguard Worker	{`
480*1fa6dee9SAndroid Build Coastguard Worker		foo {
481*1fa6dee9SAndroid Build Coastguard Worker			name: "abc",
482*1fa6dee9SAndroid Build Coastguard Worker			num: 4,
483*1fa6dee9SAndroid Build Coastguard Worker		}
484*1fa6dee9SAndroid Build Coastguard Worker
485*1fa6dee9SAndroid Build Coastguard Worker		bar {
486*1fa6dee9SAndroid Build Coastguard Worker			name: "def",
487*1fa6dee9SAndroid Build Coastguard Worker			num: -5,
488*1fa6dee9SAndroid Build Coastguard Worker		}
489*1fa6dee9SAndroid Build Coastguard Worker		`,
490*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
491*1fa6dee9SAndroid Build Coastguard Worker			&Module{
492*1fa6dee9SAndroid Build Coastguard Worker				Type:    "foo",
493*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(3, 2, 3),
494*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
495*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(7, 2, 7),
496*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(38, 5, 3),
497*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
498*1fa6dee9SAndroid Build Coastguard Worker						{
499*1fa6dee9SAndroid Build Coastguard Worker							Name:     "name",
500*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(12, 3, 4),
501*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(16, 3, 8),
502*1fa6dee9SAndroid Build Coastguard Worker							Value: &String{
503*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(18, 3, 10),
504*1fa6dee9SAndroid Build Coastguard Worker								Value:      "abc",
505*1fa6dee9SAndroid Build Coastguard Worker							},
506*1fa6dee9SAndroid Build Coastguard Worker						},
507*1fa6dee9SAndroid Build Coastguard Worker						{
508*1fa6dee9SAndroid Build Coastguard Worker							Name:     "num",
509*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(28, 4, 4),
510*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(31, 4, 7),
511*1fa6dee9SAndroid Build Coastguard Worker							Value: &Int64{
512*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(33, 4, 9),
513*1fa6dee9SAndroid Build Coastguard Worker								Value:      4,
514*1fa6dee9SAndroid Build Coastguard Worker								Token:      "4",
515*1fa6dee9SAndroid Build Coastguard Worker							},
516*1fa6dee9SAndroid Build Coastguard Worker						},
517*1fa6dee9SAndroid Build Coastguard Worker					},
518*1fa6dee9SAndroid Build Coastguard Worker				},
519*1fa6dee9SAndroid Build Coastguard Worker			},
520*1fa6dee9SAndroid Build Coastguard Worker			&Module{
521*1fa6dee9SAndroid Build Coastguard Worker				Type:    "bar",
522*1fa6dee9SAndroid Build Coastguard Worker				TypePos: mkpos(43, 7, 3),
523*1fa6dee9SAndroid Build Coastguard Worker				Map: Map{
524*1fa6dee9SAndroid Build Coastguard Worker					LBracePos: mkpos(47, 7, 7),
525*1fa6dee9SAndroid Build Coastguard Worker					RBracePos: mkpos(79, 10, 3),
526*1fa6dee9SAndroid Build Coastguard Worker					Properties: []*Property{
527*1fa6dee9SAndroid Build Coastguard Worker						{
528*1fa6dee9SAndroid Build Coastguard Worker							Name:     "name",
529*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(52, 8, 4),
530*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(56, 8, 8),
531*1fa6dee9SAndroid Build Coastguard Worker							Value: &String{
532*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(58, 8, 10),
533*1fa6dee9SAndroid Build Coastguard Worker								Value:      "def",
534*1fa6dee9SAndroid Build Coastguard Worker							},
535*1fa6dee9SAndroid Build Coastguard Worker						},
536*1fa6dee9SAndroid Build Coastguard Worker						{
537*1fa6dee9SAndroid Build Coastguard Worker							Name:     "num",
538*1fa6dee9SAndroid Build Coastguard Worker							NamePos:  mkpos(68, 9, 4),
539*1fa6dee9SAndroid Build Coastguard Worker							ColonPos: mkpos(71, 9, 7),
540*1fa6dee9SAndroid Build Coastguard Worker							Value: &Int64{
541*1fa6dee9SAndroid Build Coastguard Worker								LiteralPos: mkpos(73, 9, 9),
542*1fa6dee9SAndroid Build Coastguard Worker								Value:      -5,
543*1fa6dee9SAndroid Build Coastguard Worker								Token:      "-5",
544*1fa6dee9SAndroid Build Coastguard Worker							},
545*1fa6dee9SAndroid Build Coastguard Worker						},
546*1fa6dee9SAndroid Build Coastguard Worker					},
547*1fa6dee9SAndroid Build Coastguard Worker				},
548*1fa6dee9SAndroid Build Coastguard Worker			},
549*1fa6dee9SAndroid Build Coastguard Worker		},
550*1fa6dee9SAndroid Build Coastguard Worker		nil,
551*1fa6dee9SAndroid Build Coastguard Worker	},
552*1fa6dee9SAndroid Build Coastguard Worker
553*1fa6dee9SAndroid Build Coastguard Worker	{`
554*1fa6dee9SAndroid Build Coastguard Worker		foo = "stuff"
555*1fa6dee9SAndroid Build Coastguard Worker		bar = foo
556*1fa6dee9SAndroid Build Coastguard Worker		baz = foo + bar
557*1fa6dee9SAndroid Build Coastguard Worker		boo = baz
558*1fa6dee9SAndroid Build Coastguard Worker		boo += foo
559*1fa6dee9SAndroid Build Coastguard Worker		`,
560*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
561*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
562*1fa6dee9SAndroid Build Coastguard Worker				Name:      "foo",
563*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(3, 2, 3),
564*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(7, 2, 7),
565*1fa6dee9SAndroid Build Coastguard Worker				Value: &String{
566*1fa6dee9SAndroid Build Coastguard Worker					LiteralPos: mkpos(9, 2, 9),
567*1fa6dee9SAndroid Build Coastguard Worker					Value:      "stuff",
568*1fa6dee9SAndroid Build Coastguard Worker				},
569*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
570*1fa6dee9SAndroid Build Coastguard Worker			},
571*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
572*1fa6dee9SAndroid Build Coastguard Worker				Name:      "bar",
573*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(19, 3, 3),
574*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(23, 3, 7),
575*1fa6dee9SAndroid Build Coastguard Worker				Value: &Variable{
576*1fa6dee9SAndroid Build Coastguard Worker					Name:    "foo",
577*1fa6dee9SAndroid Build Coastguard Worker					NamePos: mkpos(25, 3, 9),
578*1fa6dee9SAndroid Build Coastguard Worker				},
579*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
580*1fa6dee9SAndroid Build Coastguard Worker			},
581*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
582*1fa6dee9SAndroid Build Coastguard Worker				Name:      "baz",
583*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(31, 4, 3),
584*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(35, 4, 7),
585*1fa6dee9SAndroid Build Coastguard Worker				Value: &Operator{
586*1fa6dee9SAndroid Build Coastguard Worker					OperatorPos: mkpos(41, 4, 13),
587*1fa6dee9SAndroid Build Coastguard Worker					Operator:    '+',
588*1fa6dee9SAndroid Build Coastguard Worker					Args: [2]Expression{
589*1fa6dee9SAndroid Build Coastguard Worker						&Variable{
590*1fa6dee9SAndroid Build Coastguard Worker							Name:    "foo",
591*1fa6dee9SAndroid Build Coastguard Worker							NamePos: mkpos(37, 4, 9),
592*1fa6dee9SAndroid Build Coastguard Worker						},
593*1fa6dee9SAndroid Build Coastguard Worker						&Variable{
594*1fa6dee9SAndroid Build Coastguard Worker							Name:    "bar",
595*1fa6dee9SAndroid Build Coastguard Worker							NamePos: mkpos(43, 4, 15),
596*1fa6dee9SAndroid Build Coastguard Worker						},
597*1fa6dee9SAndroid Build Coastguard Worker					},
598*1fa6dee9SAndroid Build Coastguard Worker				},
599*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
600*1fa6dee9SAndroid Build Coastguard Worker			},
601*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
602*1fa6dee9SAndroid Build Coastguard Worker				Name:      "boo",
603*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(49, 5, 3),
604*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(53, 5, 7),
605*1fa6dee9SAndroid Build Coastguard Worker				Value: &Variable{
606*1fa6dee9SAndroid Build Coastguard Worker					Name:    "baz",
607*1fa6dee9SAndroid Build Coastguard Worker					NamePos: mkpos(55, 5, 9),
608*1fa6dee9SAndroid Build Coastguard Worker				},
609*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
610*1fa6dee9SAndroid Build Coastguard Worker			},
611*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
612*1fa6dee9SAndroid Build Coastguard Worker				Name:      "boo",
613*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(61, 6, 3),
614*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(66, 6, 8),
615*1fa6dee9SAndroid Build Coastguard Worker				Value: &Variable{
616*1fa6dee9SAndroid Build Coastguard Worker					Name:    "foo",
617*1fa6dee9SAndroid Build Coastguard Worker					NamePos: mkpos(68, 6, 10),
618*1fa6dee9SAndroid Build Coastguard Worker				},
619*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "+=",
620*1fa6dee9SAndroid Build Coastguard Worker			},
621*1fa6dee9SAndroid Build Coastguard Worker		},
622*1fa6dee9SAndroid Build Coastguard Worker		nil,
623*1fa6dee9SAndroid Build Coastguard Worker	},
624*1fa6dee9SAndroid Build Coastguard Worker
625*1fa6dee9SAndroid Build Coastguard Worker	{`
626*1fa6dee9SAndroid Build Coastguard Worker		baz = -4 + -5 + 6
627*1fa6dee9SAndroid Build Coastguard Worker		`,
628*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
629*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
630*1fa6dee9SAndroid Build Coastguard Worker				Name:      "baz",
631*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(3, 2, 3),
632*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(7, 2, 7),
633*1fa6dee9SAndroid Build Coastguard Worker				Value: &Operator{
634*1fa6dee9SAndroid Build Coastguard Worker					OperatorPos: mkpos(12, 2, 12),
635*1fa6dee9SAndroid Build Coastguard Worker					Operator:    '+',
636*1fa6dee9SAndroid Build Coastguard Worker					Args: [2]Expression{
637*1fa6dee9SAndroid Build Coastguard Worker						&Int64{
638*1fa6dee9SAndroid Build Coastguard Worker							LiteralPos: mkpos(9, 2, 9),
639*1fa6dee9SAndroid Build Coastguard Worker							Value:      -4,
640*1fa6dee9SAndroid Build Coastguard Worker							Token:      "-4",
641*1fa6dee9SAndroid Build Coastguard Worker						},
642*1fa6dee9SAndroid Build Coastguard Worker						&Operator{
643*1fa6dee9SAndroid Build Coastguard Worker							OperatorPos: mkpos(17, 2, 17),
644*1fa6dee9SAndroid Build Coastguard Worker							Operator:    '+',
645*1fa6dee9SAndroid Build Coastguard Worker							Args: [2]Expression{
646*1fa6dee9SAndroid Build Coastguard Worker								&Int64{
647*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: mkpos(14, 2, 14),
648*1fa6dee9SAndroid Build Coastguard Worker									Value:      -5,
649*1fa6dee9SAndroid Build Coastguard Worker									Token:      "-5",
650*1fa6dee9SAndroid Build Coastguard Worker								},
651*1fa6dee9SAndroid Build Coastguard Worker								&Int64{
652*1fa6dee9SAndroid Build Coastguard Worker									LiteralPos: mkpos(19, 2, 19),
653*1fa6dee9SAndroid Build Coastguard Worker									Value:      6,
654*1fa6dee9SAndroid Build Coastguard Worker									Token:      "6",
655*1fa6dee9SAndroid Build Coastguard Worker								},
656*1fa6dee9SAndroid Build Coastguard Worker							},
657*1fa6dee9SAndroid Build Coastguard Worker						},
658*1fa6dee9SAndroid Build Coastguard Worker					},
659*1fa6dee9SAndroid Build Coastguard Worker				},
660*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
661*1fa6dee9SAndroid Build Coastguard Worker			},
662*1fa6dee9SAndroid Build Coastguard Worker		},
663*1fa6dee9SAndroid Build Coastguard Worker		nil,
664*1fa6dee9SAndroid Build Coastguard Worker	},
665*1fa6dee9SAndroid Build Coastguard Worker
666*1fa6dee9SAndroid Build Coastguard Worker	{`
667*1fa6dee9SAndroid Build Coastguard Worker		foo = 1000000
668*1fa6dee9SAndroid Build Coastguard Worker		bar = foo
669*1fa6dee9SAndroid Build Coastguard Worker		baz = foo + bar
670*1fa6dee9SAndroid Build Coastguard Worker		boo = baz
671*1fa6dee9SAndroid Build Coastguard Worker		boo += foo
672*1fa6dee9SAndroid Build Coastguard Worker		`,
673*1fa6dee9SAndroid Build Coastguard Worker		[]Definition{
674*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
675*1fa6dee9SAndroid Build Coastguard Worker				Name:      "foo",
676*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(3, 2, 3),
677*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(7, 2, 7),
678*1fa6dee9SAndroid Build Coastguard Worker				Value: &Int64{
679*1fa6dee9SAndroid Build Coastguard Worker					LiteralPos: mkpos(9, 2, 9),
680*1fa6dee9SAndroid Build Coastguard Worker					Value:      1000000,
681*1fa6dee9SAndroid Build Coastguard Worker					Token:      "1000000",
682*1fa6dee9SAndroid Build Coastguard Worker				},
683*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
684*1fa6dee9SAndroid Build Coastguard Worker			},
685*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
686*1fa6dee9SAndroid Build Coastguard Worker				Name:      "bar",
687*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(19, 3, 3),
688*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(23, 3, 7),
689*1fa6dee9SAndroid Build Coastguard Worker				Value: &Variable{
690*1fa6dee9SAndroid Build Coastguard Worker					Name:    "foo",
691*1fa6dee9SAndroid Build Coastguard Worker					NamePos: mkpos(25, 3, 9),
692*1fa6dee9SAndroid Build Coastguard Worker				},
693*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
694*1fa6dee9SAndroid Build Coastguard Worker			},
695*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
696*1fa6dee9SAndroid Build Coastguard Worker				Name:      "baz",
697*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(31, 4, 3),
698*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(35, 4, 7),
699*1fa6dee9SAndroid Build Coastguard Worker				Value: &Operator{
700*1fa6dee9SAndroid Build Coastguard Worker					OperatorPos: mkpos(41, 4, 13),
701*1fa6dee9SAndroid Build Coastguard Worker					Operator:    '+',
702*1fa6dee9SAndroid Build Coastguard Worker					Args: [2]Expression{
703*1fa6dee9SAndroid Build Coastguard Worker						&Variable{
704*1fa6dee9SAndroid Build Coastguard Worker							Name:    "foo",
705*1fa6dee9SAndroid Build Coastguard Worker							NamePos: mkpos(37, 4, 9),
706*1fa6dee9SAndroid Build Coastguard Worker						},
707*1fa6dee9SAndroid Build Coastguard Worker						&Variable{
708*1fa6dee9SAndroid Build Coastguard Worker							Name:    "bar",
709*1fa6dee9SAndroid Build Coastguard Worker							NamePos: mkpos(43, 4, 15),
710*1fa6dee9SAndroid Build Coastguard Worker						},
711*1fa6dee9SAndroid Build Coastguard Worker					},
712*1fa6dee9SAndroid Build Coastguard Worker				},
713*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
714*1fa6dee9SAndroid Build Coastguard Worker			},
715*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
716*1fa6dee9SAndroid Build Coastguard Worker				Name:      "boo",
717*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(49, 5, 3),
718*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(53, 5, 7),
719*1fa6dee9SAndroid Build Coastguard Worker				Value: &Variable{
720*1fa6dee9SAndroid Build Coastguard Worker					Name:    "baz",
721*1fa6dee9SAndroid Build Coastguard Worker					NamePos: mkpos(55, 5, 9),
722*1fa6dee9SAndroid Build Coastguard Worker				},
723*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "=",
724*1fa6dee9SAndroid Build Coastguard Worker			},
725*1fa6dee9SAndroid Build Coastguard Worker			&Assignment{
726*1fa6dee9SAndroid Build Coastguard Worker				Name:      "boo",
727*1fa6dee9SAndroid Build Coastguard Worker				NamePos:   mkpos(61, 6, 3),
728*1fa6dee9SAndroid Build Coastguard Worker				EqualsPos: mkpos(66, 6, 8),
729*1fa6dee9SAndroid Build Coastguard Worker				Value: &Variable{
730*1fa6dee9SAndroid Build Coastguard Worker					Name:    "foo",
731*1fa6dee9SAndroid Build Coastguard Worker					NamePos: mkpos(68, 6, 10),
732*1fa6dee9SAndroid Build Coastguard Worker				},
733*1fa6dee9SAndroid Build Coastguard Worker				Assigner: "+=",
734*1fa6dee9SAndroid Build Coastguard Worker			},
735*1fa6dee9SAndroid Build Coastguard Worker		},
736*1fa6dee9SAndroid Build Coastguard Worker		nil,
737*1fa6dee9SAndroid Build Coastguard Worker	},
738*1fa6dee9SAndroid Build Coastguard Worker
739*1fa6dee9SAndroid Build Coastguard Worker	{`
740*1fa6dee9SAndroid Build Coastguard Worker		// comment1
741*1fa6dee9SAndroid Build Coastguard Worker		// comment2
742*1fa6dee9SAndroid Build Coastguard Worker
743*1fa6dee9SAndroid Build Coastguard Worker		/* comment3
744*1fa6dee9SAndroid Build Coastguard Worker		   comment4 */
745*1fa6dee9SAndroid Build Coastguard Worker		// comment5
746*1fa6dee9SAndroid Build Coastguard Worker
747*1fa6dee9SAndroid Build Coastguard Worker		/* comment6 */ /* comment7 */ // comment8
748*1fa6dee9SAndroid Build Coastguard Worker		`,
749*1fa6dee9SAndroid Build Coastguard Worker		nil,
750*1fa6dee9SAndroid Build Coastguard Worker		[]*CommentGroup{
751*1fa6dee9SAndroid Build Coastguard Worker			{
752*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
753*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
754*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment1"},
755*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(3, 2, 3),
756*1fa6dee9SAndroid Build Coastguard Worker					},
757*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
758*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment2"},
759*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(17, 3, 3),
760*1fa6dee9SAndroid Build Coastguard Worker					},
761*1fa6dee9SAndroid Build Coastguard Worker				},
762*1fa6dee9SAndroid Build Coastguard Worker			},
763*1fa6dee9SAndroid Build Coastguard Worker			{
764*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
765*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
766*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"/* comment3", "		   comment4 */"},
767*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(32, 5, 3),
768*1fa6dee9SAndroid Build Coastguard Worker					},
769*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
770*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment5"},
771*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(63, 7, 3),
772*1fa6dee9SAndroid Build Coastguard Worker					},
773*1fa6dee9SAndroid Build Coastguard Worker				},
774*1fa6dee9SAndroid Build Coastguard Worker			},
775*1fa6dee9SAndroid Build Coastguard Worker			{
776*1fa6dee9SAndroid Build Coastguard Worker				Comments: []*Comment{
777*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
778*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"/* comment6 */"},
779*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(78, 9, 3),
780*1fa6dee9SAndroid Build Coastguard Worker					},
781*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
782*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"/* comment7 */"},
783*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(93, 9, 18),
784*1fa6dee9SAndroid Build Coastguard Worker					},
785*1fa6dee9SAndroid Build Coastguard Worker					&Comment{
786*1fa6dee9SAndroid Build Coastguard Worker						Comment: []string{"// comment8"},
787*1fa6dee9SAndroid Build Coastguard Worker						Slash:   mkpos(108, 9, 33),
788*1fa6dee9SAndroid Build Coastguard Worker					},
789*1fa6dee9SAndroid Build Coastguard Worker				},
790*1fa6dee9SAndroid Build Coastguard Worker			},
791*1fa6dee9SAndroid Build Coastguard Worker		},
792*1fa6dee9SAndroid Build Coastguard Worker	},
793*1fa6dee9SAndroid Build Coastguard Worker}
794*1fa6dee9SAndroid Build Coastguard Worker
795*1fa6dee9SAndroid Build Coastguard Workerfunc TestParseValidInput(t *testing.T) {
796*1fa6dee9SAndroid Build Coastguard Worker	for i, testCase := range validParseTestCases {
797*1fa6dee9SAndroid Build Coastguard Worker		t.Run(strconv.Itoa(i), func(t *testing.T) {
798*1fa6dee9SAndroid Build Coastguard Worker			r := bytes.NewBufferString(testCase.input)
799*1fa6dee9SAndroid Build Coastguard Worker			file, errs := Parse("", r)
800*1fa6dee9SAndroid Build Coastguard Worker			if len(errs) != 0 {
801*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("test case: %s", testCase.input)
802*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("unexpected errors:")
803*1fa6dee9SAndroid Build Coastguard Worker				for _, err := range errs {
804*1fa6dee9SAndroid Build Coastguard Worker					t.Errorf("  %s", err)
805*1fa6dee9SAndroid Build Coastguard Worker				}
806*1fa6dee9SAndroid Build Coastguard Worker				t.FailNow()
807*1fa6dee9SAndroid Build Coastguard Worker			}
808*1fa6dee9SAndroid Build Coastguard Worker
809*1fa6dee9SAndroid Build Coastguard Worker			if len(file.Defs) == len(testCase.defs) {
810*1fa6dee9SAndroid Build Coastguard Worker				for i := range file.Defs {
811*1fa6dee9SAndroid Build Coastguard Worker					if !reflect.DeepEqual(file.Defs[i], testCase.defs[i]) {
812*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("test case: %s", testCase.input)
813*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("incorrect definition %d:", i)
814*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("  expected: %s", testCase.defs[i])
815*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("       got: %s", file.Defs[i])
816*1fa6dee9SAndroid Build Coastguard Worker					}
817*1fa6dee9SAndroid Build Coastguard Worker				}
818*1fa6dee9SAndroid Build Coastguard Worker			} else {
819*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("test case: %s", testCase.input)
820*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("length mismatch, expected %d definitions, got %d",
821*1fa6dee9SAndroid Build Coastguard Worker					len(testCase.defs), len(file.Defs))
822*1fa6dee9SAndroid Build Coastguard Worker			}
823*1fa6dee9SAndroid Build Coastguard Worker
824*1fa6dee9SAndroid Build Coastguard Worker			if len(file.Comments) == len(testCase.comments) {
825*1fa6dee9SAndroid Build Coastguard Worker				for i := range file.Comments {
826*1fa6dee9SAndroid Build Coastguard Worker					if !reflect.DeepEqual(file.Comments[i], testCase.comments[i]) {
827*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("test case: %s", testCase.input)
828*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("incorrect comment %d:", i)
829*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("  expected: %s", testCase.comments[i])
830*1fa6dee9SAndroid Build Coastguard Worker						t.Errorf("       got: %s", file.Comments[i])
831*1fa6dee9SAndroid Build Coastguard Worker					}
832*1fa6dee9SAndroid Build Coastguard Worker				}
833*1fa6dee9SAndroid Build Coastguard Worker			} else {
834*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("test case: %s", testCase.input)
835*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("length mismatch, expected %d comments, got %d",
836*1fa6dee9SAndroid Build Coastguard Worker					len(testCase.comments), len(file.Comments))
837*1fa6dee9SAndroid Build Coastguard Worker			}
838*1fa6dee9SAndroid Build Coastguard Worker		})
839*1fa6dee9SAndroid Build Coastguard Worker	}
840*1fa6dee9SAndroid Build Coastguard Worker}
841*1fa6dee9SAndroid Build Coastguard Worker
842*1fa6dee9SAndroid Build Coastguard Workerfunc TestParseSelectWithoutTrailingComma(t *testing.T) {
843*1fa6dee9SAndroid Build Coastguard Worker	r := bytes.NewBufferString(`
844*1fa6dee9SAndroid Build Coastguard Worker	m {
845*1fa6dee9SAndroid Build Coastguard Worker		foo: select(arch(), {
846*1fa6dee9SAndroid Build Coastguard Worker			"arm64": true,
847*1fa6dee9SAndroid Build Coastguard Worker			default: false
848*1fa6dee9SAndroid Build Coastguard Worker		}),
849*1fa6dee9SAndroid Build Coastguard Worker	}
850*1fa6dee9SAndroid Build Coastguard Worker	`)
851*1fa6dee9SAndroid Build Coastguard Worker	file, errs := ParseAndEval("", r, NewScope(nil))
852*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) != 0 {
853*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("%s", errors.Join(errs...).Error())
854*1fa6dee9SAndroid Build Coastguard Worker	}
855*1fa6dee9SAndroid Build Coastguard Worker	_, ok := file.Defs[0].(*Module).Properties[0].Value.(*Select)
856*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
857*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("did not parse to select")
858*1fa6dee9SAndroid Build Coastguard Worker	}
859*1fa6dee9SAndroid Build Coastguard Worker}
860*1fa6dee9SAndroid Build Coastguard Worker
861*1fa6dee9SAndroid Build Coastguard Workerfunc TestParserError(t *testing.T) {
862*1fa6dee9SAndroid Build Coastguard Worker	testcases := []struct {
863*1fa6dee9SAndroid Build Coastguard Worker		name  string
864*1fa6dee9SAndroid Build Coastguard Worker		input string
865*1fa6dee9SAndroid Build Coastguard Worker		err   string
866*1fa6dee9SAndroid Build Coastguard Worker	}{
867*1fa6dee9SAndroid Build Coastguard Worker		{
868*1fa6dee9SAndroid Build Coastguard Worker			name:  "invalid first token",
869*1fa6dee9SAndroid Build Coastguard Worker			input: "\x00",
870*1fa6dee9SAndroid Build Coastguard Worker			err:   "invalid character NUL",
871*1fa6dee9SAndroid Build Coastguard Worker		},
872*1fa6dee9SAndroid Build Coastguard Worker		{
873*1fa6dee9SAndroid Build Coastguard Worker			name: "select with duplicate condition",
874*1fa6dee9SAndroid Build Coastguard Worker			input: `
875*1fa6dee9SAndroid Build Coastguard Worker			m {
876*1fa6dee9SAndroid Build Coastguard Worker				foo: select((arch(), arch()), {
877*1fa6dee9SAndroid Build Coastguard Worker					(default, default): true,
878*1fa6dee9SAndroid Build Coastguard Worker				}),
879*1fa6dee9SAndroid Build Coastguard Worker			}
880*1fa6dee9SAndroid Build Coastguard Worker			`,
881*1fa6dee9SAndroid Build Coastguard Worker			err: "Duplicate select condition found: arch()",
882*1fa6dee9SAndroid Build Coastguard Worker		},
883*1fa6dee9SAndroid Build Coastguard Worker		{
884*1fa6dee9SAndroid Build Coastguard Worker			name: "select with duplicate binding",
885*1fa6dee9SAndroid Build Coastguard Worker			input: `
886*1fa6dee9SAndroid Build Coastguard Worker			m {
887*1fa6dee9SAndroid Build Coastguard Worker				foo: select((arch(), os()), {
888*1fa6dee9SAndroid Build Coastguard Worker					(any @ bar, any @ bar): true,
889*1fa6dee9SAndroid Build Coastguard Worker				}),
890*1fa6dee9SAndroid Build Coastguard Worker			}
891*1fa6dee9SAndroid Build Coastguard Worker			`,
892*1fa6dee9SAndroid Build Coastguard Worker			err: "Found duplicate select pattern binding: bar",
893*1fa6dee9SAndroid Build Coastguard Worker		},
894*1fa6dee9SAndroid Build Coastguard Worker		// TODO: test more parser errors
895*1fa6dee9SAndroid Build Coastguard Worker	}
896*1fa6dee9SAndroid Build Coastguard Worker
897*1fa6dee9SAndroid Build Coastguard Worker	for _, tt := range testcases {
898*1fa6dee9SAndroid Build Coastguard Worker		t.Run(tt.name, func(t *testing.T) {
899*1fa6dee9SAndroid Build Coastguard Worker			r := bytes.NewBufferString(tt.input)
900*1fa6dee9SAndroid Build Coastguard Worker			_, errs := ParseAndEval("", r, NewScope(nil))
901*1fa6dee9SAndroid Build Coastguard Worker			if len(errs) == 0 {
902*1fa6dee9SAndroid Build Coastguard Worker				t.Fatalf("missing expected error")
903*1fa6dee9SAndroid Build Coastguard Worker			}
904*1fa6dee9SAndroid Build Coastguard Worker			if g, w := errs[0], tt.err; !strings.Contains(g.Error(), w) {
905*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("expected error %q, got %q", w, g)
906*1fa6dee9SAndroid Build Coastguard Worker			}
907*1fa6dee9SAndroid Build Coastguard Worker			for _, err := range errs[1:] {
908*1fa6dee9SAndroid Build Coastguard Worker				t.Errorf("got unexpected extra error %q", err)
909*1fa6dee9SAndroid Build Coastguard Worker			}
910*1fa6dee9SAndroid Build Coastguard Worker		})
911*1fa6dee9SAndroid Build Coastguard Worker	}
912*1fa6dee9SAndroid Build Coastguard Worker}
913*1fa6dee9SAndroid Build Coastguard Worker
914*1fa6dee9SAndroid Build Coastguard Workerfunc TestParserEndPos(t *testing.T) {
915*1fa6dee9SAndroid Build Coastguard Worker	in := `
916*1fa6dee9SAndroid Build Coastguard Worker		module {
917*1fa6dee9SAndroid Build Coastguard Worker			string: "string",
918*1fa6dee9SAndroid Build Coastguard Worker			stringexp: "string1" + "string2",
919*1fa6dee9SAndroid Build Coastguard Worker			int: -1,
920*1fa6dee9SAndroid Build Coastguard Worker			intexp: -1 + 2,
921*1fa6dee9SAndroid Build Coastguard Worker			list: ["a", "b"],
922*1fa6dee9SAndroid Build Coastguard Worker			listexp: ["c"] + ["d"],
923*1fa6dee9SAndroid Build Coastguard Worker			multilinelist: [
924*1fa6dee9SAndroid Build Coastguard Worker				"e",
925*1fa6dee9SAndroid Build Coastguard Worker				"f",
926*1fa6dee9SAndroid Build Coastguard Worker			],
927*1fa6dee9SAndroid Build Coastguard Worker			map: {
928*1fa6dee9SAndroid Build Coastguard Worker				prop: "abc",
929*1fa6dee9SAndroid Build Coastguard Worker			},
930*1fa6dee9SAndroid Build Coastguard Worker		}
931*1fa6dee9SAndroid Build Coastguard Worker	`
932*1fa6dee9SAndroid Build Coastguard Worker
933*1fa6dee9SAndroid Build Coastguard Worker	// Strip each line to make it easier to compute the previous "," from each property
934*1fa6dee9SAndroid Build Coastguard Worker	lines := strings.Split(in, "\n")
935*1fa6dee9SAndroid Build Coastguard Worker	for i := range lines {
936*1fa6dee9SAndroid Build Coastguard Worker		lines[i] = strings.TrimSpace(lines[i])
937*1fa6dee9SAndroid Build Coastguard Worker	}
938*1fa6dee9SAndroid Build Coastguard Worker	in = strings.Join(lines, "\n")
939*1fa6dee9SAndroid Build Coastguard Worker
940*1fa6dee9SAndroid Build Coastguard Worker	r := bytes.NewBufferString(in)
941*1fa6dee9SAndroid Build Coastguard Worker
942*1fa6dee9SAndroid Build Coastguard Worker	file, errs := Parse("", r)
943*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) != 0 {
944*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected errors:")
945*1fa6dee9SAndroid Build Coastguard Worker		for _, err := range errs {
946*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  %s", err)
947*1fa6dee9SAndroid Build Coastguard Worker		}
948*1fa6dee9SAndroid Build Coastguard Worker		t.FailNow()
949*1fa6dee9SAndroid Build Coastguard Worker	}
950*1fa6dee9SAndroid Build Coastguard Worker
951*1fa6dee9SAndroid Build Coastguard Worker	mod := file.Defs[0].(*Module)
952*1fa6dee9SAndroid Build Coastguard Worker	modEnd := mkpos(len(in)-1, len(lines)-1, 2)
953*1fa6dee9SAndroid Build Coastguard Worker	if mod.End() != modEnd {
954*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("expected mod.End() %s, got %s", modEnd, mod.End())
955*1fa6dee9SAndroid Build Coastguard Worker	}
956*1fa6dee9SAndroid Build Coastguard Worker
957*1fa6dee9SAndroid Build Coastguard Worker	nextPos := make([]scanner.Position, len(mod.Properties))
958*1fa6dee9SAndroid Build Coastguard Worker	for i := 0; i < len(mod.Properties)-1; i++ {
959*1fa6dee9SAndroid Build Coastguard Worker		nextPos[i] = mod.Properties[i+1].Pos()
960*1fa6dee9SAndroid Build Coastguard Worker	}
961*1fa6dee9SAndroid Build Coastguard Worker	nextPos[len(mod.Properties)-1] = mod.RBracePos
962*1fa6dee9SAndroid Build Coastguard Worker
963*1fa6dee9SAndroid Build Coastguard Worker	for i, cur := range mod.Properties {
964*1fa6dee9SAndroid Build Coastguard Worker		endOffset := nextPos[i].Offset - len(",\n")
965*1fa6dee9SAndroid Build Coastguard Worker		endLine := nextPos[i].Line - 1
966*1fa6dee9SAndroid Build Coastguard Worker		endColumn := len(lines[endLine-1]) // scanner.Position.Line is starts at 1
967*1fa6dee9SAndroid Build Coastguard Worker		endPos := mkpos(endOffset, endLine, endColumn)
968*1fa6dee9SAndroid Build Coastguard Worker		if cur.End() != endPos {
969*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("expected property %s End() %s@%d, got %s@%d", cur.Name, endPos, endPos.Offset, cur.End(), cur.End().Offset)
970*1fa6dee9SAndroid Build Coastguard Worker		}
971*1fa6dee9SAndroid Build Coastguard Worker	}
972*1fa6dee9SAndroid Build Coastguard Worker}
973*1fa6dee9SAndroid Build Coastguard Worker
974*1fa6dee9SAndroid Build Coastguard Workerfunc TestParserNotEvaluated(t *testing.T) {
975*1fa6dee9SAndroid Build Coastguard Worker	// When parsing without evaluation, create variables correctly
976*1fa6dee9SAndroid Build Coastguard Worker	input := "FOO=abc\n"
977*1fa6dee9SAndroid Build Coastguard Worker	file, errs := Parse("", bytes.NewBufferString(input))
978*1fa6dee9SAndroid Build Coastguard Worker	if errs != nil {
979*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("unexpected errors:")
980*1fa6dee9SAndroid Build Coastguard Worker		for _, err := range errs {
981*1fa6dee9SAndroid Build Coastguard Worker			t.Errorf("  %s", err)
982*1fa6dee9SAndroid Build Coastguard Worker		}
983*1fa6dee9SAndroid Build Coastguard Worker		t.FailNow()
984*1fa6dee9SAndroid Build Coastguard Worker	}
985*1fa6dee9SAndroid Build Coastguard Worker	assignment, ok := file.Defs[0].(*Assignment)
986*1fa6dee9SAndroid Build Coastguard Worker	if !ok || assignment.Name != "FOO" {
987*1fa6dee9SAndroid Build Coastguard Worker		t.Fatalf("Expected to find FOO after parsing %s", input)
988*1fa6dee9SAndroid Build Coastguard Worker	}
989*1fa6dee9SAndroid Build Coastguard Worker	if assignment.Value.String() != "abc" {
990*1fa6dee9SAndroid Build Coastguard Worker		t.Errorf("Attempt to print FOO returned %s", assignment.Value.String())
991*1fa6dee9SAndroid Build Coastguard Worker	}
992*1fa6dee9SAndroid Build Coastguard Worker}
993