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