1
2
3
4
5
6
7 package parse
8
9 import (
10 "fmt"
11 "strconv"
12 "strings"
13 )
14
15 var textFormat = "%s"
16
17
18
19
20 type Node interface {
21 Type() NodeType
22 String() string
23
24
25
26 Copy() Node
27 Position() Pos
28
29
30 tree() *Tree
31
32 writeTo(*strings.Builder)
33 }
34
35
36 type NodeType int
37
38
39
40 type Pos int
41
42 func (p Pos) Position() Pos {
43 return p
44 }
45
46
47
48 func (t NodeType) Type() NodeType {
49 return t
50 }
51
52 const (
53 NodeText NodeType = iota
54 NodeAction
55 NodeBool
56 NodeChain
57 NodeCommand
58 NodeDot
59 nodeElse
60 nodeEnd
61 NodeField
62 NodeIdentifier
63 NodeIf
64 NodeList
65 NodeNil
66 NodeNumber
67 NodePipe
68 NodeRange
69 NodeString
70 NodeTemplate
71 NodeVariable
72 NodeWith
73 NodeComment
74 NodeBreak
75 NodeContinue
76 )
77
78
79
80
81 type ListNode struct {
82 NodeType
83 Pos
84 tr *Tree
85 Nodes []Node
86 }
87
88 func (t *Tree) newList(pos Pos) *ListNode {
89 return &ListNode{tr: t, NodeType: NodeList, Pos: pos}
90 }
91
92 func (l *ListNode) append(n Node) {
93 l.Nodes = append(l.Nodes, n)
94 }
95
96 func (l *ListNode) tree() *Tree {
97 return l.tr
98 }
99
100 func (l *ListNode) String() string {
101 var sb strings.Builder
102 l.writeTo(&sb)
103 return sb.String()
104 }
105
106 func (l *ListNode) writeTo(sb *strings.Builder) {
107 for _, n := range l.Nodes {
108 n.writeTo(sb)
109 }
110 }
111
112 func (l *ListNode) CopyList() *ListNode {
113 if l == nil {
114 return l
115 }
116 n := l.tr.newList(l.Pos)
117 for _, elem := range l.Nodes {
118 n.append(elem.Copy())
119 }
120 return n
121 }
122
123 func (l *ListNode) Copy() Node {
124 return l.CopyList()
125 }
126
127
128 type TextNode struct {
129 NodeType
130 Pos
131 tr *Tree
132 Text []byte
133 }
134
135 func (t *Tree) newText(pos Pos, text string) *TextNode {
136 return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)}
137 }
138
139 func (t *TextNode) String() string {
140 return fmt.Sprintf(textFormat, t.Text)
141 }
142
143 func (t *TextNode) writeTo(sb *strings.Builder) {
144 sb.WriteString(t.String())
145 }
146
147 func (t *TextNode) tree() *Tree {
148 return t.tr
149 }
150
151 func (t *TextNode) Copy() Node {
152 return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)}
153 }
154
155
156 type CommentNode struct {
157 NodeType
158 Pos
159 tr *Tree
160 Text string
161 }
162
163 func (t *Tree) newComment(pos Pos, text string) *CommentNode {
164 return &CommentNode{tr: t, NodeType: NodeComment, Pos: pos, Text: text}
165 }
166
167 func (c *CommentNode) String() string {
168 var sb strings.Builder
169 c.writeTo(&sb)
170 return sb.String()
171 }
172
173 func (c *CommentNode) writeTo(sb *strings.Builder) {
174 sb.WriteString("{{")
175 sb.WriteString(c.Text)
176 sb.WriteString("}}")
177 }
178
179 func (c *CommentNode) tree() *Tree {
180 return c.tr
181 }
182
183 func (c *CommentNode) Copy() Node {
184 return &CommentNode{tr: c.tr, NodeType: NodeComment, Pos: c.Pos, Text: c.Text}
185 }
186
187
188 type PipeNode struct {
189 NodeType
190 Pos
191 tr *Tree
192 Line int
193 IsAssign bool
194 Decl []*VariableNode
195 Cmds []*CommandNode
196 }
197
198 func (t *Tree) newPipeline(pos Pos, line int, vars []*VariableNode) *PipeNode {
199 return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: vars}
200 }
201
202 func (p *PipeNode) append(command *CommandNode) {
203 p.Cmds = append(p.Cmds, command)
204 }
205
206 func (p *PipeNode) String() string {
207 var sb strings.Builder
208 p.writeTo(&sb)
209 return sb.String()
210 }
211
212 func (p *PipeNode) writeTo(sb *strings.Builder) {
213 if len(p.Decl) > 0 {
214 for i, v := range p.Decl {
215 if i > 0 {
216 sb.WriteString(", ")
217 }
218 v.writeTo(sb)
219 }
220 if p.IsAssign {
221 sb.WriteString(" = ")
222 } else {
223 sb.WriteString(" := ")
224 }
225 }
226 for i, c := range p.Cmds {
227 if i > 0 {
228 sb.WriteString(" | ")
229 }
230 c.writeTo(sb)
231 }
232 }
233
234 func (p *PipeNode) tree() *Tree {
235 return p.tr
236 }
237
238 func (p *PipeNode) CopyPipe() *PipeNode {
239 if p == nil {
240 return p
241 }
242 vars := make([]*VariableNode, len(p.Decl))
243 for i, d := range p.Decl {
244 vars[i] = d.Copy().(*VariableNode)
245 }
246 n := p.tr.newPipeline(p.Pos, p.Line, vars)
247 n.IsAssign = p.IsAssign
248 for _, c := range p.Cmds {
249 n.append(c.Copy().(*CommandNode))
250 }
251 return n
252 }
253
254 func (p *PipeNode) Copy() Node {
255 return p.CopyPipe()
256 }
257
258
259
260
261 type ActionNode struct {
262 NodeType
263 Pos
264 tr *Tree
265 Line int
266 Pipe *PipeNode
267 }
268
269 func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
270 return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
271 }
272
273 func (a *ActionNode) String() string {
274 var sb strings.Builder
275 a.writeTo(&sb)
276 return sb.String()
277 }
278
279 func (a *ActionNode) writeTo(sb *strings.Builder) {
280 sb.WriteString("{{")
281 a.Pipe.writeTo(sb)
282 sb.WriteString("}}")
283 }
284
285 func (a *ActionNode) tree() *Tree {
286 return a.tr
287 }
288
289 func (a *ActionNode) Copy() Node {
290 return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
291 }
292
293
294 type CommandNode struct {
295 NodeType
296 Pos
297 tr *Tree
298 Args []Node
299 }
300
301 func (t *Tree) newCommand(pos Pos) *CommandNode {
302 return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos}
303 }
304
305 func (c *CommandNode) append(arg Node) {
306 c.Args = append(c.Args, arg)
307 }
308
309 func (c *CommandNode) String() string {
310 var sb strings.Builder
311 c.writeTo(&sb)
312 return sb.String()
313 }
314
315 func (c *CommandNode) writeTo(sb *strings.Builder) {
316 for i, arg := range c.Args {
317 if i > 0 {
318 sb.WriteByte(' ')
319 }
320 if arg, ok := arg.(*PipeNode); ok {
321 sb.WriteByte('(')
322 arg.writeTo(sb)
323 sb.WriteByte(')')
324 continue
325 }
326 arg.writeTo(sb)
327 }
328 }
329
330 func (c *CommandNode) tree() *Tree {
331 return c.tr
332 }
333
334 func (c *CommandNode) Copy() Node {
335 if c == nil {
336 return c
337 }
338 n := c.tr.newCommand(c.Pos)
339 for _, c := range c.Args {
340 n.append(c.Copy())
341 }
342 return n
343 }
344
345
346 type IdentifierNode struct {
347 NodeType
348 Pos
349 tr *Tree
350 Ident string
351 }
352
353
354 func NewIdentifier(ident string) *IdentifierNode {
355 return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
356 }
357
358
359
360
361 func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
362 i.Pos = pos
363 return i
364 }
365
366
367
368
369 func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode {
370 i.tr = t
371 return i
372 }
373
374 func (i *IdentifierNode) String() string {
375 return i.Ident
376 }
377
378 func (i *IdentifierNode) writeTo(sb *strings.Builder) {
379 sb.WriteString(i.String())
380 }
381
382 func (i *IdentifierNode) tree() *Tree {
383 return i.tr
384 }
385
386 func (i *IdentifierNode) Copy() Node {
387 return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos)
388 }
389
390
391
392 type VariableNode struct {
393 NodeType
394 Pos
395 tr *Tree
396 Ident []string
397 }
398
399 func (t *Tree) newVariable(pos Pos, ident string) *VariableNode {
400 return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
401 }
402
403 func (v *VariableNode) String() string {
404 var sb strings.Builder
405 v.writeTo(&sb)
406 return sb.String()
407 }
408
409 func (v *VariableNode) writeTo(sb *strings.Builder) {
410 for i, id := range v.Ident {
411 if i > 0 {
412 sb.WriteByte('.')
413 }
414 sb.WriteString(id)
415 }
416 }
417
418 func (v *VariableNode) tree() *Tree {
419 return v.tr
420 }
421
422 func (v *VariableNode) Copy() Node {
423 return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
424 }
425
426
427 type DotNode struct {
428 NodeType
429 Pos
430 tr *Tree
431 }
432
433 func (t *Tree) newDot(pos Pos) *DotNode {
434 return &DotNode{tr: t, NodeType: NodeDot, Pos: pos}
435 }
436
437 func (d *DotNode) Type() NodeType {
438
439
440
441 return NodeDot
442 }
443
444 func (d *DotNode) String() string {
445 return "."
446 }
447
448 func (d *DotNode) writeTo(sb *strings.Builder) {
449 sb.WriteString(d.String())
450 }
451
452 func (d *DotNode) tree() *Tree {
453 return d.tr
454 }
455
456 func (d *DotNode) Copy() Node {
457 return d.tr.newDot(d.Pos)
458 }
459
460
461 type NilNode struct {
462 NodeType
463 Pos
464 tr *Tree
465 }
466
467 func (t *Tree) newNil(pos Pos) *NilNode {
468 return &NilNode{tr: t, NodeType: NodeNil, Pos: pos}
469 }
470
471 func (n *NilNode) Type() NodeType {
472
473
474
475 return NodeNil
476 }
477
478 func (n *NilNode) String() string {
479 return "nil"
480 }
481
482 func (n *NilNode) writeTo(sb *strings.Builder) {
483 sb.WriteString(n.String())
484 }
485
486 func (n *NilNode) tree() *Tree {
487 return n.tr
488 }
489
490 func (n *NilNode) Copy() Node {
491 return n.tr.newNil(n.Pos)
492 }
493
494
495
496
497 type FieldNode struct {
498 NodeType
499 Pos
500 tr *Tree
501 Ident []string
502 }
503
504 func (t *Tree) newField(pos Pos, ident string) *FieldNode {
505 return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")}
506 }
507
508 func (f *FieldNode) String() string {
509 var sb strings.Builder
510 f.writeTo(&sb)
511 return sb.String()
512 }
513
514 func (f *FieldNode) writeTo(sb *strings.Builder) {
515 for _, id := range f.Ident {
516 sb.WriteByte('.')
517 sb.WriteString(id)
518 }
519 }
520
521 func (f *FieldNode) tree() *Tree {
522 return f.tr
523 }
524
525 func (f *FieldNode) Copy() Node {
526 return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
527 }
528
529
530
531
532 type ChainNode struct {
533 NodeType
534 Pos
535 tr *Tree
536 Node Node
537 Field []string
538 }
539
540 func (t *Tree) newChain(pos Pos, node Node) *ChainNode {
541 return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node}
542 }
543
544
545 func (c *ChainNode) Add(field string) {
546 if len(field) == 0 || field[0] != '.' {
547 panic("no dot in field")
548 }
549 field = field[1:]
550 if field == "" {
551 panic("empty field")
552 }
553 c.Field = append(c.Field, field)
554 }
555
556 func (c *ChainNode) String() string {
557 var sb strings.Builder
558 c.writeTo(&sb)
559 return sb.String()
560 }
561
562 func (c *ChainNode) writeTo(sb *strings.Builder) {
563 if _, ok := c.Node.(*PipeNode); ok {
564 sb.WriteByte('(')
565 c.Node.writeTo(sb)
566 sb.WriteByte(')')
567 } else {
568 c.Node.writeTo(sb)
569 }
570 for _, field := range c.Field {
571 sb.WriteByte('.')
572 sb.WriteString(field)
573 }
574 }
575
576 func (c *ChainNode) tree() *Tree {
577 return c.tr
578 }
579
580 func (c *ChainNode) Copy() Node {
581 return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
582 }
583
584
585 type BoolNode struct {
586 NodeType
587 Pos
588 tr *Tree
589 True bool
590 }
591
592 func (t *Tree) newBool(pos Pos, true bool) *BoolNode {
593 return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true}
594 }
595
596 func (b *BoolNode) String() string {
597 if b.True {
598 return "true"
599 }
600 return "false"
601 }
602
603 func (b *BoolNode) writeTo(sb *strings.Builder) {
604 sb.WriteString(b.String())
605 }
606
607 func (b *BoolNode) tree() *Tree {
608 return b.tr
609 }
610
611 func (b *BoolNode) Copy() Node {
612 return b.tr.newBool(b.Pos, b.True)
613 }
614
615
616
617
618 type NumberNode struct {
619 NodeType
620 Pos
621 tr *Tree
622 IsInt bool
623 IsUint bool
624 IsFloat bool
625 IsComplex bool
626 Int64 int64
627 Uint64 uint64
628 Float64 float64
629 Complex128 complex128
630 Text string
631 }
632
633 func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
634 n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text}
635 switch typ {
636 case itemCharConstant:
637 rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
638 if err != nil {
639 return nil, err
640 }
641 if tail != "'" {
642 return nil, fmt.Errorf("malformed character constant: %s", text)
643 }
644 n.Int64 = int64(rune)
645 n.IsInt = true
646 n.Uint64 = uint64(rune)
647 n.IsUint = true
648 n.Float64 = float64(rune)
649 n.IsFloat = true
650 return n, nil
651 case itemComplex:
652
653 if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
654 return nil, err
655 }
656 n.IsComplex = true
657 n.simplifyComplex()
658 return n, nil
659 }
660
661 if len(text) > 0 && text[len(text)-1] == 'i' {
662 f, err := strconv.ParseFloat(text[:len(text)-1], 64)
663 if err == nil {
664 n.IsComplex = true
665 n.Complex128 = complex(0, f)
666 n.simplifyComplex()
667 return n, nil
668 }
669 }
670
671 u, err := strconv.ParseUint(text, 0, 64)
672 if err == nil {
673 n.IsUint = true
674 n.Uint64 = u
675 }
676 i, err := strconv.ParseInt(text, 0, 64)
677 if err == nil {
678 n.IsInt = true
679 n.Int64 = i
680 if i == 0 {
681 n.IsUint = true
682 n.Uint64 = u
683 }
684 }
685
686 if n.IsInt {
687 n.IsFloat = true
688 n.Float64 = float64(n.Int64)
689 } else if n.IsUint {
690 n.IsFloat = true
691 n.Float64 = float64(n.Uint64)
692 } else {
693 f, err := strconv.ParseFloat(text, 64)
694 if err == nil {
695
696
697 if !strings.ContainsAny(text, ".eEpP") {
698 return nil, fmt.Errorf("integer overflow: %q", text)
699 }
700 n.IsFloat = true
701 n.Float64 = f
702
703 if !n.IsInt && float64(int64(f)) == f {
704 n.IsInt = true
705 n.Int64 = int64(f)
706 }
707 if !n.IsUint && float64(uint64(f)) == f {
708 n.IsUint = true
709 n.Uint64 = uint64(f)
710 }
711 }
712 }
713 if !n.IsInt && !n.IsUint && !n.IsFloat {
714 return nil, fmt.Errorf("illegal number syntax: %q", text)
715 }
716 return n, nil
717 }
718
719
720
721 func (n *NumberNode) simplifyComplex() {
722 n.IsFloat = imag(n.Complex128) == 0
723 if n.IsFloat {
724 n.Float64 = real(n.Complex128)
725 n.IsInt = float64(int64(n.Float64)) == n.Float64
726 if n.IsInt {
727 n.Int64 = int64(n.Float64)
728 }
729 n.IsUint = float64(uint64(n.Float64)) == n.Float64
730 if n.IsUint {
731 n.Uint64 = uint64(n.Float64)
732 }
733 }
734 }
735
736 func (n *NumberNode) String() string {
737 return n.Text
738 }
739
740 func (n *NumberNode) writeTo(sb *strings.Builder) {
741 sb.WriteString(n.String())
742 }
743
744 func (n *NumberNode) tree() *Tree {
745 return n.tr
746 }
747
748 func (n *NumberNode) Copy() Node {
749 nn := new(NumberNode)
750 *nn = *n
751 return nn
752 }
753
754
755 type StringNode struct {
756 NodeType
757 Pos
758 tr *Tree
759 Quoted string
760 Text string
761 }
762
763 func (t *Tree) newString(pos Pos, orig, text string) *StringNode {
764 return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
765 }
766
767 func (s *StringNode) String() string {
768 return s.Quoted
769 }
770
771 func (s *StringNode) writeTo(sb *strings.Builder) {
772 sb.WriteString(s.String())
773 }
774
775 func (s *StringNode) tree() *Tree {
776 return s.tr
777 }
778
779 func (s *StringNode) Copy() Node {
780 return s.tr.newString(s.Pos, s.Quoted, s.Text)
781 }
782
783
784
785 type endNode struct {
786 NodeType
787 Pos
788 tr *Tree
789 }
790
791 func (t *Tree) newEnd(pos Pos) *endNode {
792 return &endNode{tr: t, NodeType: nodeEnd, Pos: pos}
793 }
794
795 func (e *endNode) String() string {
796 return "{{end}}"
797 }
798
799 func (e *endNode) writeTo(sb *strings.Builder) {
800 sb.WriteString(e.String())
801 }
802
803 func (e *endNode) tree() *Tree {
804 return e.tr
805 }
806
807 func (e *endNode) Copy() Node {
808 return e.tr.newEnd(e.Pos)
809 }
810
811
812 type elseNode struct {
813 NodeType
814 Pos
815 tr *Tree
816 Line int
817 }
818
819 func (t *Tree) newElse(pos Pos, line int) *elseNode {
820 return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line}
821 }
822
823 func (e *elseNode) Type() NodeType {
824 return nodeElse
825 }
826
827 func (e *elseNode) String() string {
828 return "{{else}}"
829 }
830
831 func (e *elseNode) writeTo(sb *strings.Builder) {
832 sb.WriteString(e.String())
833 }
834
835 func (e *elseNode) tree() *Tree {
836 return e.tr
837 }
838
839 func (e *elseNode) Copy() Node {
840 return e.tr.newElse(e.Pos, e.Line)
841 }
842
843
844 type BranchNode struct {
845 NodeType
846 Pos
847 tr *Tree
848 Line int
849 Pipe *PipeNode
850 List *ListNode
851 ElseList *ListNode
852 }
853
854 func (b *BranchNode) String() string {
855 var sb strings.Builder
856 b.writeTo(&sb)
857 return sb.String()
858 }
859
860 func (b *BranchNode) writeTo(sb *strings.Builder) {
861 name := ""
862 switch b.NodeType {
863 case NodeIf:
864 name = "if"
865 case NodeRange:
866 name = "range"
867 case NodeWith:
868 name = "with"
869 default:
870 panic("unknown branch type")
871 }
872 sb.WriteString("{{")
873 sb.WriteString(name)
874 sb.WriteByte(' ')
875 b.Pipe.writeTo(sb)
876 sb.WriteString("}}")
877 b.List.writeTo(sb)
878 if b.ElseList != nil {
879 sb.WriteString("{{else}}")
880 b.ElseList.writeTo(sb)
881 }
882 sb.WriteString("{{end}}")
883 }
884
885 func (b *BranchNode) tree() *Tree {
886 return b.tr
887 }
888
889 func (b *BranchNode) Copy() Node {
890 switch b.NodeType {
891 case NodeIf:
892 return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
893 case NodeRange:
894 return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
895 case NodeWith:
896 return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
897 default:
898 panic("unknown branch type")
899 }
900 }
901
902
903 type IfNode struct {
904 BranchNode
905 }
906
907 func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
908 return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
909 }
910
911 func (i *IfNode) Copy() Node {
912 return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
913 }
914
915
916 type BreakNode struct {
917 tr *Tree
918 NodeType
919 Pos
920 Line int
921 }
922
923 func (t *Tree) newBreak(pos Pos, line int) *BreakNode {
924 return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line}
925 }
926
927 func (b *BreakNode) Copy() Node { return b.tr.newBreak(b.Pos, b.Line) }
928 func (b *BreakNode) String() string { return "{{break}}" }
929 func (b *BreakNode) tree() *Tree { return b.tr }
930 func (b *BreakNode) writeTo(sb *strings.Builder) { sb.WriteString("{{break}}") }
931
932
933 type ContinueNode struct {
934 tr *Tree
935 NodeType
936 Pos
937 Line int
938 }
939
940 func (t *Tree) newContinue(pos Pos, line int) *ContinueNode {
941 return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: line}
942 }
943
944 func (c *ContinueNode) Copy() Node { return c.tr.newContinue(c.Pos, c.Line) }
945 func (c *ContinueNode) String() string { return "{{continue}}" }
946 func (c *ContinueNode) tree() *Tree { return c.tr }
947 func (c *ContinueNode) writeTo(sb *strings.Builder) { sb.WriteString("{{continue}}") }
948
949
950 type RangeNode struct {
951 BranchNode
952 }
953
954 func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
955 return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
956 }
957
958 func (r *RangeNode) Copy() Node {
959 return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
960 }
961
962
963 type WithNode struct {
964 BranchNode
965 }
966
967 func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
968 return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
969 }
970
971 func (w *WithNode) Copy() Node {
972 return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
973 }
974
975
976 type TemplateNode struct {
977 NodeType
978 Pos
979 tr *Tree
980 Line int
981 Name string
982 Pipe *PipeNode
983 }
984
985 func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
986 return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe}
987 }
988
989 func (t *TemplateNode) String() string {
990 var sb strings.Builder
991 t.writeTo(&sb)
992 return sb.String()
993 }
994
995 func (t *TemplateNode) writeTo(sb *strings.Builder) {
996 sb.WriteString("{{template ")
997 sb.WriteString(strconv.Quote(t.Name))
998 if t.Pipe != nil {
999 sb.WriteByte(' ')
1000 t.Pipe.writeTo(sb)
1001 }
1002 sb.WriteString("}}")
1003 }
1004
1005 func (t *TemplateNode) tree() *Tree {
1006 return t.tr
1007 }
1008
1009 func (t *TemplateNode) Copy() Node {
1010 return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
1011 }
1012
View as plain text