1package parser
2
3import (
4	"strings"
5
6	"github.com/d5/tengo/v2/token"
7)
8
9// Expr represents an expression node in the AST.
10type Expr interface {
11	Node
12	exprNode()
13}
14
15// ArrayLit represents an array literal.
16type ArrayLit struct {
17	Elements []Expr
18	LBrack   Pos
19	RBrack   Pos
20}
21
22func (e *ArrayLit) exprNode() {}
23
24// Pos returns the position of first character belonging to the node.
25func (e *ArrayLit) Pos() Pos {
26	return e.LBrack
27}
28
29// End returns the position of first character immediately after the node.
30func (e *ArrayLit) End() Pos {
31	return e.RBrack + 1
32}
33
34func (e *ArrayLit) String() string {
35	var elements []string
36	for _, m := range e.Elements {
37		elements = append(elements, m.String())
38	}
39	return "[" + strings.Join(elements, ", ") + "]"
40}
41
42// BadExpr represents a bad expression.
43type BadExpr struct {
44	From Pos
45	To   Pos
46}
47
48func (e *BadExpr) exprNode() {}
49
50// Pos returns the position of first character belonging to the node.
51func (e *BadExpr) Pos() Pos {
52	return e.From
53}
54
55// End returns the position of first character immediately after the node.
56func (e *BadExpr) End() Pos {
57	return e.To
58}
59
60func (e *BadExpr) String() string {
61	return "<bad expression>"
62}
63
64// BinaryExpr represents a binary operator expression.
65type BinaryExpr struct {
66	LHS      Expr
67	RHS      Expr
68	Token    token.Token
69	TokenPos Pos
70}
71
72func (e *BinaryExpr) exprNode() {}
73
74// Pos returns the position of first character belonging to the node.
75func (e *BinaryExpr) Pos() Pos {
76	return e.LHS.Pos()
77}
78
79// End returns the position of first character immediately after the node.
80func (e *BinaryExpr) End() Pos {
81	return e.RHS.End()
82}
83
84func (e *BinaryExpr) String() string {
85	return "(" + e.LHS.String() + " " + e.Token.String() +
86		" " + e.RHS.String() + ")"
87}
88
89// BoolLit represents a boolean literal.
90type BoolLit struct {
91	Value    bool
92	ValuePos Pos
93	Literal  string
94}
95
96func (e *BoolLit) exprNode() {}
97
98// Pos returns the position of first character belonging to the node.
99func (e *BoolLit) Pos() Pos {
100	return e.ValuePos
101}
102
103// End returns the position of first character immediately after the node.
104func (e *BoolLit) End() Pos {
105	return Pos(int(e.ValuePos) + len(e.Literal))
106}
107
108func (e *BoolLit) String() string {
109	return e.Literal
110}
111
112// CallExpr represents a function call expression.
113type CallExpr struct {
114	Func     Expr
115	LParen   Pos
116	Args     []Expr
117	Ellipsis Pos
118	RParen   Pos
119}
120
121func (e *CallExpr) exprNode() {}
122
123// Pos returns the position of first character belonging to the node.
124func (e *CallExpr) Pos() Pos {
125	return e.Func.Pos()
126}
127
128// End returns the position of first character immediately after the node.
129func (e *CallExpr) End() Pos {
130	return e.RParen + 1
131}
132
133func (e *CallExpr) String() string {
134	var args []string
135	for _, e := range e.Args {
136		args = append(args, e.String())
137	}
138	if len(args) > 0 && e.Ellipsis.IsValid() {
139		args[len(args)-1] = args[len(args)-1] + "..."
140	}
141	return e.Func.String() + "(" + strings.Join(args, ", ") + ")"
142}
143
144// CharLit represents a character literal.
145type CharLit struct {
146	Value    rune
147	ValuePos Pos
148	Literal  string
149}
150
151func (e *CharLit) exprNode() {}
152
153// Pos returns the position of first character belonging to the node.
154func (e *CharLit) Pos() Pos {
155	return e.ValuePos
156}
157
158// End returns the position of first character immediately after the node.
159func (e *CharLit) End() Pos {
160	return Pos(int(e.ValuePos) + len(e.Literal))
161}
162
163func (e *CharLit) String() string {
164	return e.Literal
165}
166
167// CondExpr represents a ternary conditional expression.
168type CondExpr struct {
169	Cond        Expr
170	True        Expr
171	False       Expr
172	QuestionPos Pos
173	ColonPos    Pos
174}
175
176func (e *CondExpr) exprNode() {}
177
178// Pos returns the position of first character belonging to the node.
179func (e *CondExpr) Pos() Pos {
180	return e.Cond.Pos()
181}
182
183// End returns the position of first character immediately after the node.
184func (e *CondExpr) End() Pos {
185	return e.False.End()
186}
187
188func (e *CondExpr) String() string {
189	return "(" + e.Cond.String() + " ? " + e.True.String() +
190		" : " + e.False.String() + ")"
191}
192
193// ErrorExpr represents an error expression
194type ErrorExpr struct {
195	Expr     Expr
196	ErrorPos Pos
197	LParen   Pos
198	RParen   Pos
199}
200
201func (e *ErrorExpr) exprNode() {}
202
203// Pos returns the position of first character belonging to the node.
204func (e *ErrorExpr) Pos() Pos {
205	return e.ErrorPos
206}
207
208// End returns the position of first character immediately after the node.
209func (e *ErrorExpr) End() Pos {
210	return e.RParen
211}
212
213func (e *ErrorExpr) String() string {
214	return "error(" + e.Expr.String() + ")"
215}
216
217// FloatLit represents a floating point literal.
218type FloatLit struct {
219	Value    float64
220	ValuePos Pos
221	Literal  string
222}
223
224func (e *FloatLit) exprNode() {}
225
226// Pos returns the position of first character belonging to the node.
227func (e *FloatLit) Pos() Pos {
228	return e.ValuePos
229}
230
231// End returns the position of first character immediately after the node.
232func (e *FloatLit) End() Pos {
233	return Pos(int(e.ValuePos) + len(e.Literal))
234}
235
236func (e *FloatLit) String() string {
237	return e.Literal
238}
239
240// FuncLit represents a function literal.
241type FuncLit struct {
242	Type *FuncType
243	Body *BlockStmt
244}
245
246func (e *FuncLit) exprNode() {}
247
248// Pos returns the position of first character belonging to the node.
249func (e *FuncLit) Pos() Pos {
250	return e.Type.Pos()
251}
252
253// End returns the position of first character immediately after the node.
254func (e *FuncLit) End() Pos {
255	return e.Body.End()
256}
257
258func (e *FuncLit) String() string {
259	return "func" + e.Type.Params.String() + " " + e.Body.String()
260}
261
262// FuncType represents a function type definition.
263type FuncType struct {
264	FuncPos Pos
265	Params  *IdentList
266}
267
268func (e *FuncType) exprNode() {}
269
270// Pos returns the position of first character belonging to the node.
271func (e *FuncType) Pos() Pos {
272	return e.FuncPos
273}
274
275// End returns the position of first character immediately after the node.
276func (e *FuncType) End() Pos {
277	return e.Params.End()
278}
279
280func (e *FuncType) String() string {
281	return "func" + e.Params.String()
282}
283
284// Ident represents an identifier.
285type Ident struct {
286	Name    string
287	NamePos Pos
288}
289
290func (e *Ident) exprNode() {}
291
292// Pos returns the position of first character belonging to the node.
293func (e *Ident) Pos() Pos {
294	return e.NamePos
295}
296
297// End returns the position of first character immediately after the node.
298func (e *Ident) End() Pos {
299	return Pos(int(e.NamePos) + len(e.Name))
300}
301
302func (e *Ident) String() string {
303	if e != nil {
304		return e.Name
305	}
306	return nullRep
307}
308
309// ImmutableExpr represents an immutable expression
310type ImmutableExpr struct {
311	Expr     Expr
312	ErrorPos Pos
313	LParen   Pos
314	RParen   Pos
315}
316
317func (e *ImmutableExpr) exprNode() {}
318
319// Pos returns the position of first character belonging to the node.
320func (e *ImmutableExpr) Pos() Pos {
321	return e.ErrorPos
322}
323
324// End returns the position of first character immediately after the node.
325func (e *ImmutableExpr) End() Pos {
326	return e.RParen
327}
328
329func (e *ImmutableExpr) String() string {
330	return "immutable(" + e.Expr.String() + ")"
331}
332
333// ImportExpr represents an import expression
334type ImportExpr struct {
335	ModuleName string
336	Token      token.Token
337	TokenPos   Pos
338}
339
340func (e *ImportExpr) exprNode() {}
341
342// Pos returns the position of first character belonging to the node.
343func (e *ImportExpr) Pos() Pos {
344	return e.TokenPos
345}
346
347// End returns the position of first character immediately after the node.
348func (e *ImportExpr) End() Pos {
349	// import("moduleName")
350	return Pos(int(e.TokenPos) + 10 + len(e.ModuleName))
351}
352
353func (e *ImportExpr) String() string {
354	return `import("` + e.ModuleName + `")"`
355}
356
357// IndexExpr represents an index expression.
358type IndexExpr struct {
359	Expr   Expr
360	LBrack Pos
361	Index  Expr
362	RBrack Pos
363}
364
365func (e *IndexExpr) exprNode() {}
366
367// Pos returns the position of first character belonging to the node.
368func (e *IndexExpr) Pos() Pos {
369	return e.Expr.Pos()
370}
371
372// End returns the position of first character immediately after the node.
373func (e *IndexExpr) End() Pos {
374	return e.RBrack + 1
375}
376
377func (e *IndexExpr) String() string {
378	var index string
379	if e.Index != nil {
380		index = e.Index.String()
381	}
382	return e.Expr.String() + "[" + index + "]"
383}
384
385// IntLit represents an integer literal.
386type IntLit struct {
387	Value    int64
388	ValuePos Pos
389	Literal  string
390}
391
392func (e *IntLit) exprNode() {}
393
394// Pos returns the position of first character belonging to the node.
395func (e *IntLit) Pos() Pos {
396	return e.ValuePos
397}
398
399// End returns the position of first character immediately after the node.
400func (e *IntLit) End() Pos {
401	return Pos(int(e.ValuePos) + len(e.Literal))
402}
403
404func (e *IntLit) String() string {
405	return e.Literal
406}
407
408// MapElementLit represents a map element.
409type MapElementLit struct {
410	Key      string
411	KeyPos   Pos
412	ColonPos Pos
413	Value    Expr
414}
415
416func (e *MapElementLit) exprNode() {}
417
418// Pos returns the position of first character belonging to the node.
419func (e *MapElementLit) Pos() Pos {
420	return e.KeyPos
421}
422
423// End returns the position of first character immediately after the node.
424func (e *MapElementLit) End() Pos {
425	return e.Value.End()
426}
427
428func (e *MapElementLit) String() string {
429	return e.Key + ": " + e.Value.String()
430}
431
432// MapLit represents a map literal.
433type MapLit struct {
434	LBrace   Pos
435	Elements []*MapElementLit
436	RBrace   Pos
437}
438
439func (e *MapLit) exprNode() {}
440
441// Pos returns the position of first character belonging to the node.
442func (e *MapLit) Pos() Pos {
443	return e.LBrace
444}
445
446// End returns the position of first character immediately after the node.
447func (e *MapLit) End() Pos {
448	return e.RBrace + 1
449}
450
451func (e *MapLit) String() string {
452	var elements []string
453	for _, m := range e.Elements {
454		elements = append(elements, m.String())
455	}
456	return "{" + strings.Join(elements, ", ") + "}"
457}
458
459// ParenExpr represents a parenthesis wrapped expression.
460type ParenExpr struct {
461	Expr   Expr
462	LParen Pos
463	RParen Pos
464}
465
466func (e *ParenExpr) exprNode() {}
467
468// Pos returns the position of first character belonging to the node.
469func (e *ParenExpr) Pos() Pos {
470	return e.LParen
471}
472
473// End returns the position of first character immediately after the node.
474func (e *ParenExpr) End() Pos {
475	return e.RParen + 1
476}
477
478func (e *ParenExpr) String() string {
479	return "(" + e.Expr.String() + ")"
480}
481
482// SelectorExpr represents a selector expression.
483type SelectorExpr struct {
484	Expr Expr
485	Sel  Expr
486}
487
488func (e *SelectorExpr) exprNode() {}
489
490// Pos returns the position of first character belonging to the node.
491func (e *SelectorExpr) Pos() Pos {
492	return e.Expr.Pos()
493}
494
495// End returns the position of first character immediately after the node.
496func (e *SelectorExpr) End() Pos {
497	return e.Sel.End()
498}
499
500func (e *SelectorExpr) String() string {
501	return e.Expr.String() + "." + e.Sel.String()
502}
503
504// SliceExpr represents a slice expression.
505type SliceExpr struct {
506	Expr   Expr
507	LBrack Pos
508	Low    Expr
509	High   Expr
510	RBrack Pos
511}
512
513func (e *SliceExpr) exprNode() {}
514
515// Pos returns the position of first character belonging to the node.
516func (e *SliceExpr) Pos() Pos {
517	return e.Expr.Pos()
518}
519
520// End returns the position of first character immediately after the node.
521func (e *SliceExpr) End() Pos {
522	return e.RBrack + 1
523}
524
525func (e *SliceExpr) String() string {
526	var low, high string
527	if e.Low != nil {
528		low = e.Low.String()
529	}
530	if e.High != nil {
531		high = e.High.String()
532	}
533	return e.Expr.String() + "[" + low + ":" + high + "]"
534}
535
536// StringLit represents a string literal.
537type StringLit struct {
538	Value    string
539	ValuePos Pos
540	Literal  string
541}
542
543func (e *StringLit) exprNode() {}
544
545// Pos returns the position of first character belonging to the node.
546func (e *StringLit) Pos() Pos {
547	return e.ValuePos
548}
549
550// End returns the position of first character immediately after the node.
551func (e *StringLit) End() Pos {
552	return Pos(int(e.ValuePos) + len(e.Literal))
553}
554
555func (e *StringLit) String() string {
556	return e.Literal
557}
558
559// UnaryExpr represents an unary operator expression.
560type UnaryExpr struct {
561	Expr     Expr
562	Token    token.Token
563	TokenPos Pos
564}
565
566func (e *UnaryExpr) exprNode() {}
567
568// Pos returns the position of first character belonging to the node.
569func (e *UnaryExpr) Pos() Pos {
570	return e.Expr.Pos()
571}
572
573// End returns the position of first character immediately after the node.
574func (e *UnaryExpr) End() Pos {
575	return e.Expr.End()
576}
577
578func (e *UnaryExpr) String() string {
579	return "(" + e.Token.String() + e.Expr.String() + ")"
580}
581
582// UndefinedLit represents an undefined literal.
583type UndefinedLit struct {
584	TokenPos Pos
585}
586
587func (e *UndefinedLit) exprNode() {}
588
589// Pos returns the position of first character belonging to the node.
590func (e *UndefinedLit) Pos() Pos {
591	return e.TokenPos
592}
593
594// End returns the position of first character immediately after the node.
595func (e *UndefinedLit) End() Pos {
596	return e.TokenPos + 9 // len(undefined) == 9
597}
598
599func (e *UndefinedLit) String() string {
600	return "undefined"
601}
602