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(c.tr.leftDelim)
175 sb.WriteString(c.Text)
176 sb.WriteString(c.tr.rightDelim)
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(a.tr.leftDelim)
281 a.Pipe.writeTo(sb)
282 sb.WriteString(a.tr.rightDelim)
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 e.tr.leftDelim + "end" + e.tr.rightDelim
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 e.tr.leftDelim + "else" + e.tr.rightDelim
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(b.tr.leftDelim)
873 sb.WriteString(name)
874 sb.WriteByte(' ')
875 b.Pipe.writeTo(sb)
876 sb.WriteString(b.tr.rightDelim)
877 b.List.writeTo(sb)
878 if b.ElseList != nil {
879 sb.WriteString(b.tr.leftDelim)
880 sb.WriteString("else")
881 sb.WriteString(b.tr.rightDelim)
882 b.ElseList.writeTo(sb)
883 }
884 sb.WriteString(b.tr.leftDelim)
885 sb.WriteString("end")
886 sb.WriteString(b.tr.rightDelim)
887 }
888
889 func (b *BranchNode) tree() *Tree {
890 return b.tr
891 }
892
893 func (b *BranchNode) Copy() Node {
894 switch b.NodeType {
895 case NodeIf:
896 return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
897 case NodeRange:
898 return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
899 case NodeWith:
900 return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
901 default:
902 panic("unknown branch type")
903 }
904 }
905
906
907 type IfNode struct {
908 BranchNode
909 }
910
911 func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
912 return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
913 }
914
915 func (i *IfNode) Copy() Node {
916 return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
917 }
918
919
920 type BreakNode struct {
921 tr *Tree
922 NodeType
923 Pos
924 Line int
925 }
926
927 func (t *Tree) newBreak(pos Pos, line int) *BreakNode {
928 return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line}
929 }
930
931 func (b *BreakNode) Copy() Node { return b.tr.newBreak(b.Pos, b.Line) }
932 func (b *BreakNode) String() string { return b.tr.leftDelim + "break" + b.tr.rightDelim }
933 func (b *BreakNode) tree() *Tree { return b.tr }
934 func (b *BreakNode) writeTo(sb *strings.Builder) { sb.WriteString(b.String()) }
935
936
937 type ContinueNode struct {
938 tr *Tree
939 NodeType
940 Pos
941 Line int
942 }
943
944 func (t *Tree) newContinue(pos Pos, line int) *ContinueNode {
945 return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: line}
946 }
947
948 func (c *ContinueNode) Copy() Node { return c.tr.newContinue(c.Pos, c.Line) }
949 func (c *ContinueNode) String() string { return c.tr.leftDelim + "continue" + c.tr.rightDelim }
950 func (c *ContinueNode) tree() *Tree { return c.tr }
951 func (c *ContinueNode) writeTo(sb *strings.Builder) { sb.WriteString(c.String()) }
952
953
954 type RangeNode struct {
955 BranchNode
956 }
957
958 func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
959 return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
960 }
961
962 func (r *RangeNode) Copy() Node {
963 return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
964 }
965
966
967 type WithNode struct {
968 BranchNode
969 }
970
971 func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
972 return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
973 }
974
975 func (w *WithNode) Copy() Node {
976 return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
977 }
978
979
980 type TemplateNode struct {
981 NodeType
982 Pos
983 tr *Tree
984 Line int
985 Name string
986 Pipe *PipeNode
987 }
988
989 func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
990 return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe}
991 }
992
993 func (t *TemplateNode) String() string {
994 var sb strings.Builder
995 t.writeTo(&sb)
996 return sb.String()
997 }
998
999 func (t *TemplateNode) writeTo(sb *strings.Builder) {
1000 sb.WriteString(t.tr.leftDelim)
1001 sb.WriteString("template ")
1002 sb.WriteString(strconv.Quote(t.Name))
1003 if t.Pipe != nil {
1004 sb.WriteByte(' ')
1005 t.Pipe.writeTo(sb)
1006 }
1007 sb.WriteString(t.tr.rightDelim)
1008 }
1009
1010 func (t *TemplateNode) tree() *Tree {
1011 return t.tr
1012 }
1013
1014 func (t *TemplateNode) Copy() Node {
1015 return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
1016 }
1017
View as plain text