1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package d2ast
24
25 import (
26 "bytes"
27 "encoding"
28 "errors"
29 "fmt"
30 "math/big"
31 "path"
32 "strconv"
33 "strings"
34 "unicode"
35 "unicode/utf16"
36 "unicode/utf8"
37
38 "oss.terrastruct.com/util-go/xdefer"
39 )
40
41
42
43 type Node interface {
44 node()
45
46
47 Type() string
48
49
50 GetRange() Range
51
52
53
54 }
55
56 var _ Node = &Comment{}
57 var _ Node = &BlockComment{}
58
59 var _ Node = &Null{}
60 var _ Node = &Boolean{}
61 var _ Node = &Number{}
62 var _ Node = &UnquotedString{}
63 var _ Node = &DoubleQuotedString{}
64 var _ Node = &SingleQuotedString{}
65 var _ Node = &BlockString{}
66 var _ Node = &Substitution{}
67 var _ Node = &Import{}
68
69 var _ Node = &Array{}
70 var _ Node = &Map{}
71 var _ Node = &Key{}
72 var _ Node = &KeyPath{}
73 var _ Node = &Edge{}
74 var _ Node = &EdgeIndex{}
75
76
77
78
79
80
81
82
83
84
85
86 type Range struct {
87 Path string
88 Start Position
89 End Position
90 }
91
92 var _ fmt.Stringer = Range{}
93 var _ encoding.TextMarshaler = Range{}
94 var _ encoding.TextUnmarshaler = &Range{}
95
96 func MakeRange(s string) Range {
97 var r Range
98 _ = r.UnmarshalText([]byte(s))
99 return r
100 }
101
102
103
104
105
106
107 func (r Range) String() string {
108 var s strings.Builder
109 if r.Path != "" {
110 s.WriteString(r.Path)
111 s.WriteByte(':')
112 }
113
114 s.WriteString(r.Start.String())
115 return s.String()
116 }
117
118
119 func (r Range) OneLine() bool {
120 return r.Start.Line == r.End.Line
121 }
122
123
124 func (r Range) MarshalText() ([]byte, error) {
125 start, _ := r.Start.MarshalText()
126 end, _ := r.End.MarshalText()
127 return []byte(fmt.Sprintf("%s,%s-%s", r.Path, start, end)), nil
128 }
129
130
131 func (r *Range) UnmarshalText(b []byte) (err error) {
132 defer xdefer.Errorf(&err, "failed to unmarshal Range from %q", b)
133
134 i := bytes.LastIndexByte(b, '-')
135 if i == -1 {
136 return errors.New("missing End field")
137 }
138 end := b[i+1:]
139 b = b[:i]
140
141 i = bytes.LastIndexByte(b, ',')
142 if i == -1 {
143 return errors.New("missing Start field")
144 }
145 start := b[i+1:]
146 b = b[:i]
147
148 r.Path = string(b)
149 err = r.Start.UnmarshalText(start)
150 if err != nil {
151 return err
152 }
153 return r.End.UnmarshalText(end)
154 }
155
156 func (r Range) Before(r2 Range) bool {
157 return r.Start.Before(r2.Start)
158 }
159
160
161
162
163
164
165
166
167 type Position struct {
168 Line int
169 Column int
170 Byte int
171 }
172
173 var _ fmt.Stringer = Position{}
174 var _ encoding.TextMarshaler = Position{}
175 var _ encoding.TextUnmarshaler = &Position{}
176
177
178
179
180 func (p Position) String() string {
181 return fmt.Sprintf("%d:%d", p.Line+1, p.Column+1)
182 }
183
184 func (p Position) Debug() string {
185 return fmt.Sprintf("%d:%d:%d", p.Line, p.Column, p.Byte)
186 }
187
188
189 func (p Position) MarshalText() ([]byte, error) {
190 return []byte(fmt.Sprintf("%d:%d:%d", p.Line, p.Column, p.Byte)), nil
191 }
192
193
194 func (p *Position) UnmarshalText(b []byte) (err error) {
195 defer xdefer.Errorf(&err, "failed to unmarshal Position from %q", b)
196
197 fields := bytes.Split(b, []byte{':'})
198 if len(fields) != 3 {
199 return errors.New("expected three fields")
200 }
201
202 p.Line, err = strconv.Atoi(string(fields[0]))
203 if err != nil {
204 return err
205 }
206 p.Column, err = strconv.Atoi(string(fields[1]))
207 if err != nil {
208 return err
209 }
210 p.Byte, err = strconv.Atoi(string(fields[2]))
211 return err
212 }
213
214
215
216 func (p *Position) From(src *Position) {
217 *p = *src
218 }
219
220
221
222
223
224 func (p Position) Advance(r rune, byUTF16 bool) Position {
225 size := utf8.RuneLen(r)
226 if byUTF16 {
227 size = 1
228 r1, r2 := utf16.EncodeRune(r)
229 if r1 != '\uFFFD' && r2 != '\uFFFD' {
230 size = 2
231 }
232 }
233
234 if r == '\n' {
235 p.Line++
236 p.Column = 0
237 } else {
238 p.Column += size
239 }
240 p.Byte += size
241
242 return p
243 }
244
245 func (p Position) Subtract(r rune, byUTF16 bool) Position {
246 size := utf8.RuneLen(r)
247 if byUTF16 {
248 size = 1
249 r1, r2 := utf16.EncodeRune(r)
250 if r1 != '\uFFFD' && r2 != '\uFFFD' {
251 size = 2
252 }
253 }
254
255 if r == '\n' {
256 panic("d2ast: cannot subtract newline from Position")
257 } else {
258 p.Column -= size
259 }
260 p.Byte -= size
261
262 return p
263 }
264
265 func (p Position) AdvanceString(s string, byUTF16 bool) Position {
266 for _, r := range s {
267 p = p.Advance(r, byUTF16)
268 }
269 return p
270 }
271
272 func (p Position) SubtractString(s string, byUTF16 bool) Position {
273 for _, r := range s {
274 p = p.Subtract(r, byUTF16)
275 }
276 return p
277 }
278
279 func (p Position) Before(p2 Position) bool {
280 return p.Byte < p2.Byte
281 }
282
283
284 type MapNode interface {
285 Node
286 mapNode()
287 }
288
289 var _ MapNode = &Comment{}
290 var _ MapNode = &BlockComment{}
291 var _ MapNode = &Key{}
292 var _ MapNode = &Substitution{}
293 var _ MapNode = &Import{}
294
295
296 type ArrayNode interface {
297 Node
298 arrayNode()
299 }
300
301
302 var _ ArrayNode = &Comment{}
303 var _ ArrayNode = &BlockComment{}
304 var _ ArrayNode = &Substitution{}
305 var _ ArrayNode = &Import{}
306
307
308 type Value interface {
309 ArrayNode
310 value()
311 }
312
313
314 var _ Value = &Array{}
315 var _ Value = &Map{}
316
317
318 type Scalar interface {
319 Value
320 scalar()
321 ScalarString() string
322 }
323
324
325 var _ Scalar = &Null{}
326 var _ Scalar = &Boolean{}
327 var _ Scalar = &Number{}
328
329
330 type String interface {
331 Scalar
332 SetString(string)
333 Copy() String
334 _string()
335 }
336
337 var _ String = &UnquotedString{}
338 var _ String = &SingleQuotedString{}
339 var _ String = &DoubleQuotedString{}
340 var _ String = &BlockString{}
341
342 func (c *Comment) node() {}
343 func (c *BlockComment) node() {}
344 func (n *Null) node() {}
345 func (b *Boolean) node() {}
346 func (n *Number) node() {}
347 func (s *UnquotedString) node() {}
348 func (s *DoubleQuotedString) node() {}
349 func (s *SingleQuotedString) node() {}
350 func (s *BlockString) node() {}
351 func (s *Substitution) node() {}
352 func (i *Import) node() {}
353 func (a *Array) node() {}
354 func (m *Map) node() {}
355 func (k *Key) node() {}
356 func (k *KeyPath) node() {}
357 func (e *Edge) node() {}
358 func (i *EdgeIndex) node() {}
359
360 func (c *Comment) Type() string { return "comment" }
361 func (c *BlockComment) Type() string { return "block comment" }
362 func (n *Null) Type() string { return "null" }
363 func (b *Boolean) Type() string { return "boolean" }
364 func (n *Number) Type() string { return "number" }
365 func (s *UnquotedString) Type() string { return "unquoted string" }
366 func (s *DoubleQuotedString) Type() string { return "double quoted string" }
367 func (s *SingleQuotedString) Type() string { return "single quoted string" }
368 func (s *BlockString) Type() string { return s.Tag + " block string" }
369 func (s *Substitution) Type() string { return "substitution" }
370 func (i *Import) Type() string { return "import" }
371 func (a *Array) Type() string { return "array" }
372 func (m *Map) Type() string { return "map" }
373 func (k *Key) Type() string { return "map key" }
374 func (k *KeyPath) Type() string { return "key path" }
375 func (e *Edge) Type() string { return "edge" }
376 func (i *EdgeIndex) Type() string { return "edge index" }
377
378 func (c *Comment) GetRange() Range { return c.Range }
379 func (c *BlockComment) GetRange() Range { return c.Range }
380 func (n *Null) GetRange() Range { return n.Range }
381 func (b *Boolean) GetRange() Range { return b.Range }
382 func (n *Number) GetRange() Range { return n.Range }
383 func (s *UnquotedString) GetRange() Range { return s.Range }
384 func (s *DoubleQuotedString) GetRange() Range { return s.Range }
385 func (s *SingleQuotedString) GetRange() Range { return s.Range }
386 func (s *BlockString) GetRange() Range { return s.Range }
387 func (s *Substitution) GetRange() Range { return s.Range }
388 func (i *Import) GetRange() Range { return i.Range }
389 func (a *Array) GetRange() Range { return a.Range }
390 func (m *Map) GetRange() Range { return m.Range }
391 func (k *Key) GetRange() Range { return k.Range }
392 func (k *KeyPath) GetRange() Range { return k.Range }
393 func (e *Edge) GetRange() Range { return e.Range }
394 func (i *EdgeIndex) GetRange() Range { return i.Range }
395
396 func (c *Comment) mapNode() {}
397 func (c *BlockComment) mapNode() {}
398 func (k *Key) mapNode() {}
399 func (s *Substitution) mapNode() {}
400 func (i *Import) mapNode() {}
401
402 func (c *Comment) arrayNode() {}
403 func (c *BlockComment) arrayNode() {}
404 func (n *Null) arrayNode() {}
405 func (b *Boolean) arrayNode() {}
406 func (n *Number) arrayNode() {}
407 func (s *UnquotedString) arrayNode() {}
408 func (s *DoubleQuotedString) arrayNode() {}
409 func (s *SingleQuotedString) arrayNode() {}
410 func (s *BlockString) arrayNode() {}
411 func (s *Substitution) arrayNode() {}
412 func (i *Import) arrayNode() {}
413 func (a *Array) arrayNode() {}
414 func (m *Map) arrayNode() {}
415
416 func (n *Null) value() {}
417 func (b *Boolean) value() {}
418 func (n *Number) value() {}
419 func (s *UnquotedString) value() {}
420 func (s *DoubleQuotedString) value() {}
421 func (s *SingleQuotedString) value() {}
422 func (s *BlockString) value() {}
423 func (a *Array) value() {}
424 func (m *Map) value() {}
425 func (i *Import) value() {}
426
427 func (n *Null) scalar() {}
428 func (b *Boolean) scalar() {}
429 func (n *Number) scalar() {}
430 func (s *UnquotedString) scalar() {}
431 func (s *DoubleQuotedString) scalar() {}
432 func (s *SingleQuotedString) scalar() {}
433 func (s *BlockString) scalar() {}
434
435
436 func (n *Null) ScalarString() string { return "" }
437 func (b *Boolean) ScalarString() string { return strconv.FormatBool(b.Value) }
438 func (n *Number) ScalarString() string { return n.Raw }
439 func (s *UnquotedString) ScalarString() string {
440 if len(s.Value) == 0 {
441 return ""
442 }
443 if s.Value[0].String == nil {
444 return ""
445 }
446 return *s.Value[0].String
447 }
448 func (s *DoubleQuotedString) ScalarString() string {
449 if len(s.Value) == 0 {
450 return ""
451 }
452 if s.Value[0].String == nil {
453 return ""
454 }
455 return *s.Value[0].String
456 }
457 func (s *SingleQuotedString) ScalarString() string { return s.Value }
458 func (s *BlockString) ScalarString() string { return s.Value }
459
460 func (s *UnquotedString) SetString(s2 string) { s.Value = []InterpolationBox{{String: &s2}} }
461 func (s *DoubleQuotedString) SetString(s2 string) { s.Value = []InterpolationBox{{String: &s2}} }
462 func (s *SingleQuotedString) SetString(s2 string) { s.Raw = ""; s.Value = s2 }
463 func (s *BlockString) SetString(s2 string) { s.Value = s2 }
464
465 func (s *UnquotedString) Copy() String { tmp := *s; return &tmp }
466 func (s *DoubleQuotedString) Copy() String { tmp := *s; return &tmp }
467 func (s *SingleQuotedString) Copy() String { tmp := *s; return &tmp }
468 func (s *BlockString) Copy() String { tmp := *s; return &tmp }
469
470 func (s *UnquotedString) _string() {}
471 func (s *DoubleQuotedString) _string() {}
472 func (s *SingleQuotedString) _string() {}
473 func (s *BlockString) _string() {}
474
475 type Comment struct {
476 Range Range `json:"range"`
477 Value string `json:"value"`
478 }
479
480 type BlockComment struct {
481 Range Range `json:"range"`
482 Value string `json:"value"`
483 }
484
485 type Null struct {
486 Range Range `json:"range"`
487 }
488
489 type Boolean struct {
490 Range Range `json:"range"`
491 Value bool `json:"value"`
492 }
493
494 type Number struct {
495 Range Range `json:"range"`
496 Raw string `json:"raw"`
497 Value *big.Rat `json:"value"`
498 }
499
500 type UnquotedString struct {
501 Range Range `json:"range"`
502 Value []InterpolationBox `json:"value"`
503
504 Pattern []string `json:"pattern,omitempty"`
505 }
506
507 func (s *UnquotedString) Coalesce() {
508 var b strings.Builder
509 for _, box := range s.Value {
510 if box.String == nil {
511 break
512 }
513 b.WriteString(*box.String)
514 }
515 s.SetString(b.String())
516 }
517
518 func FlatUnquotedString(s string) *UnquotedString {
519 return &UnquotedString{
520 Value: []InterpolationBox{{String: &s}},
521 }
522 }
523
524 type DoubleQuotedString struct {
525 Range Range `json:"range"`
526 Value []InterpolationBox `json:"value"`
527 }
528
529 func (s *DoubleQuotedString) Coalesce() {
530 var b strings.Builder
531 for _, box := range s.Value {
532 if box.String == nil {
533 break
534 }
535 b.WriteString(*box.String)
536 }
537 s.SetString(b.String())
538 }
539
540 func FlatDoubleQuotedString(s string) *DoubleQuotedString {
541 return &DoubleQuotedString{
542 Value: []InterpolationBox{{String: &s}},
543 }
544 }
545
546 type SingleQuotedString struct {
547 Range Range `json:"range"`
548 Raw string `json:"raw"`
549 Value string `json:"value"`
550 }
551
552 type BlockString struct {
553 Range Range `json:"range"`
554
555
556
557
558 Quote string `json:"quote"`
559 Tag string `json:"tag"`
560 Value string `json:"value"`
561 }
562
563 type Array struct {
564 Range Range `json:"range"`
565 Nodes []ArrayNodeBox `json:"nodes"`
566 }
567
568 type Map struct {
569 Range Range `json:"range"`
570 Nodes []MapNodeBox `json:"nodes"`
571 }
572
573 func (m *Map) InsertAfter(cursor, n MapNode) {
574 afterIndex := len(m.Nodes) - 1
575
576 for i, n := range m.Nodes {
577 if n.Unbox() == cursor {
578 afterIndex = i
579 }
580 }
581
582 a := make([]MapNodeBox, 0, len(m.Nodes))
583 a = append(a, m.Nodes[:afterIndex+1]...)
584 a = append(a, MakeMapNodeBox(n))
585 a = append(a, m.Nodes[afterIndex+1:]...)
586 m.Nodes = a
587 }
588
589 func (m *Map) InsertBefore(cursor, n MapNode) {
590 beforeIndex := len(m.Nodes)
591
592 for i, n := range m.Nodes {
593 if n.Unbox() == cursor {
594 beforeIndex = i
595 }
596 }
597
598 a := make([]MapNodeBox, 0, len(m.Nodes))
599 a = append(a, m.Nodes[:beforeIndex]...)
600 a = append(a, MakeMapNodeBox(n))
601 a = append(a, m.Nodes[beforeIndex:]...)
602 m.Nodes = a
603 }
604
605 func (m *Map) IsFileMap() bool {
606 return m.Range.Start.Line == 0 && m.Range.Start.Column == 0
607 }
608
609 func (m *Map) HasFilter() bool {
610 for _, n := range m.Nodes {
611 if n.MapKey != nil && (n.MapKey.Ampersand || n.MapKey.NotAmpersand) {
612 return true
613 }
614 }
615 return false
616 }
617
618
619 type Key struct {
620 Range Range `json:"range"`
621
622
623 Ampersand bool `json:"ampersand,omitempty"`
624
625
626 NotAmpersand bool `json:"not_ampersand,omitempty"`
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644 Key *KeyPath `json:"key,omitempty"`
645 Edges []*Edge `json:"edges,omitempty"`
646 EdgeIndex *EdgeIndex `json:"edge_index,omitempty"`
647 EdgeKey *KeyPath `json:"edge_key,omitempty"`
648
649 Primary ScalarBox `json:"primary,omitempty"`
650 Value ValueBox `json:"value"`
651 }
652
653 func (mk1 *Key) D2OracleEquals(mk2 *Key) bool {
654 if mk1 == nil && mk2 == nil {
655 return true
656 }
657 if (mk1 == nil) || (mk2 == nil) {
658 return false
659 }
660 if mk1.Ampersand != mk2.Ampersand {
661 return false
662 }
663 if (mk1.Key == nil) != (mk2.Key == nil) {
664 return false
665 }
666 if (mk1.EdgeIndex == nil) != (mk2.EdgeIndex == nil) {
667 return false
668 }
669 if (mk1.EdgeKey == nil) != (mk2.EdgeKey == nil) {
670 return false
671 }
672 if len(mk1.Edges) != len(mk2.Edges) {
673 return false
674 }
675 if (mk1.Value.Map == nil) != (mk2.Value.Map == nil) {
676 if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
677 return false
678 }
679 if mk2.Value.Map != nil && len(mk2.Value.Map.Nodes) > 0 {
680 return false
681 }
682 } else if (mk1.Value.Unbox() == nil) != (mk2.Value.Unbox() == nil) {
683 return false
684 }
685
686 if mk1.Key != nil {
687 if len(mk1.Key.Path) != len(mk2.Key.Path) {
688 return false
689 }
690 for i, id := range mk1.Key.Path {
691 if id.Unbox().ScalarString() != mk2.Key.Path[i].Unbox().ScalarString() {
692 return false
693 }
694 }
695 }
696 if mk1.EdgeKey != nil {
697 if len(mk1.EdgeKey.Path) != len(mk2.EdgeKey.Path) {
698 return false
699 }
700 for i, id := range mk1.EdgeKey.Path {
701 if id.Unbox().ScalarString() != mk2.EdgeKey.Path[i].Unbox().ScalarString() {
702 return false
703 }
704 }
705 }
706
707 if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
708 if len(mk1.Value.Map.Nodes) != len(mk2.Value.Map.Nodes) {
709 return false
710 }
711 for i := range mk1.Value.Map.Nodes {
712 if !mk1.Value.Map.Nodes[i].MapKey.Equals(mk2.Value.Map.Nodes[i].MapKey) {
713 return false
714 }
715 }
716 }
717
718 if mk1.Value.Unbox() != nil {
719 if (mk1.Value.ScalarBox().Unbox() == nil) != (mk2.Value.ScalarBox().Unbox() == nil) {
720 return false
721 }
722 if mk1.Value.ScalarBox().Unbox() != nil {
723 if mk1.Value.ScalarBox().Unbox().ScalarString() != mk2.Value.ScalarBox().Unbox().ScalarString() {
724 return false
725 }
726 }
727 }
728
729 return true
730 }
731
732 func (mk1 *Key) Equals(mk2 *Key) bool {
733 if mk1 == nil && mk2 == nil {
734 return true
735 }
736 if (mk1 == nil) || (mk2 == nil) {
737 return false
738 }
739 if mk1.Ampersand != mk2.Ampersand {
740 return false
741 }
742 if (mk1.Key == nil) != (mk2.Key == nil) {
743 return false
744 }
745 if (mk1.EdgeIndex == nil) != (mk2.EdgeIndex == nil) {
746 return false
747 }
748 if mk1.EdgeIndex != nil {
749 if !mk1.EdgeIndex.Equals(mk2.EdgeIndex) {
750 return false
751 }
752 }
753 if (mk1.EdgeKey == nil) != (mk2.EdgeKey == nil) {
754 return false
755 }
756 if len(mk1.Edges) != len(mk2.Edges) {
757 return false
758 }
759 for i := range mk1.Edges {
760 if !mk1.Edges[i].Equals(mk2.Edges[i]) {
761 return false
762 }
763 }
764 if (mk1.Value.Map == nil) != (mk2.Value.Map == nil) {
765 if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
766 return false
767 }
768 if mk2.Value.Map != nil && len(mk2.Value.Map.Nodes) > 0 {
769 return false
770 }
771 } else if (mk1.Value.Unbox() == nil) != (mk2.Value.Unbox() == nil) {
772 return false
773 }
774
775 if mk1.Key != nil {
776 if len(mk1.Key.Path) != len(mk2.Key.Path) {
777 return false
778 }
779 for i, id := range mk1.Key.Path {
780 if id.Unbox().ScalarString() != mk2.Key.Path[i].Unbox().ScalarString() {
781 return false
782 }
783 }
784 }
785 if mk1.EdgeKey != nil {
786 if len(mk1.EdgeKey.Path) != len(mk2.EdgeKey.Path) {
787 return false
788 }
789 for i, id := range mk1.EdgeKey.Path {
790 if id.Unbox().ScalarString() != mk2.EdgeKey.Path[i].Unbox().ScalarString() {
791 return false
792 }
793 }
794 }
795
796 if mk1.Value.Map != nil && len(mk1.Value.Map.Nodes) > 0 {
797 if len(mk1.Value.Map.Nodes) != len(mk2.Value.Map.Nodes) {
798 return false
799 }
800 for i := range mk1.Value.Map.Nodes {
801 if !mk1.Value.Map.Nodes[i].MapKey.Equals(mk2.Value.Map.Nodes[i].MapKey) {
802 return false
803 }
804 }
805 }
806
807 if mk1.Value.Unbox() != nil {
808 if (mk1.Value.ScalarBox().Unbox() == nil) != (mk2.Value.ScalarBox().Unbox() == nil) {
809 return false
810 }
811 if mk1.Value.ScalarBox().Unbox() != nil {
812 if mk1.Value.ScalarBox().Unbox().ScalarString() != mk2.Value.ScalarBox().Unbox().ScalarString() {
813 return false
814 }
815 }
816 }
817
818 if mk1.Primary.Unbox() != nil {
819 if (mk1.Primary.Unbox() == nil) != (mk2.Primary.Unbox() == nil) {
820 return false
821 }
822 if mk1.Primary.ScalarString() != mk2.Primary.ScalarString() {
823 return false
824 }
825 }
826
827 return true
828 }
829
830 func (mk *Key) SetScalar(scalar ScalarBox) {
831 if mk.Value.Unbox() != nil && mk.Value.ScalarBox().Unbox() == nil {
832 mk.Primary = scalar
833 } else {
834 mk.Value = MakeValueBox(scalar.Unbox())
835 }
836 }
837
838 func (mk *Key) HasGlob() bool {
839 if mk.Key.HasGlob() {
840 return true
841 }
842 for _, e := range mk.Edges {
843 if e.Src.HasGlob() || e.Dst.HasGlob() {
844 return true
845 }
846 }
847 if mk.EdgeIndex != nil && mk.EdgeIndex.Glob {
848 return true
849 }
850 if mk.EdgeKey.HasGlob() {
851 return true
852 }
853 return false
854 }
855
856 func (mk *Key) HasTripleGlob() bool {
857 if mk.Key.HasTripleGlob() {
858 return true
859 }
860 for _, e := range mk.Edges {
861 if e.Src.HasTripleGlob() || e.Dst.HasTripleGlob() {
862 return true
863 }
864 }
865 if mk.EdgeIndex != nil && mk.EdgeIndex.Glob {
866 return true
867 }
868 if mk.EdgeKey.HasTripleGlob() {
869 return true
870 }
871 return false
872 }
873
874 func (mk *Key) SupportsGlobFilters() bool {
875 if mk.Key.HasGlob() && len(mk.Edges) == 0 {
876 return true
877 }
878 if mk.EdgeIndex != nil && mk.EdgeIndex.Glob && mk.EdgeKey == nil {
879 return true
880 }
881 if mk.EdgeKey.HasGlob() {
882 return true
883 }
884 return false
885 }
886
887 func (mk *Key) Copy() *Key {
888 mk2 := *mk
889 return &mk2
890 }
891
892 type KeyPath struct {
893 Range Range `json:"range"`
894 Path []*StringBox `json:"path"`
895 }
896
897 func MakeKeyPath(a []string) *KeyPath {
898 kp := &KeyPath{}
899 for _, el := range a {
900 kp.Path = append(kp.Path, MakeValueBox(RawString(el, true)).StringBox())
901 }
902 return kp
903 }
904
905 func (kp *KeyPath) IDA() (ida []string) {
906 for _, el := range kp.Path {
907 ida = append(ida, el.Unbox().ScalarString())
908 }
909 return ida
910 }
911
912 func (kp *KeyPath) Copy() *KeyPath {
913 kp2 := *kp
914 kp2.Path = nil
915 kp2.Path = append(kp2.Path, kp.Path...)
916 return &kp2
917 }
918
919 func (kp *KeyPath) Last() *StringBox {
920 return kp.Path[len(kp.Path)-1]
921 }
922
923 func IsDoubleGlob(pattern []string) bool {
924 return len(pattern) == 3 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*"
925 }
926
927 func IsTripleGlob(pattern []string) bool {
928 return len(pattern) == 5 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*" && pattern[3] == "" && pattern[4] == "*"
929 }
930
931 func (kp *KeyPath) HasGlob() bool {
932 if kp == nil {
933 return false
934 }
935 for _, el := range kp.Path {
936 if el.UnquotedString != nil && len(el.UnquotedString.Pattern) > 0 {
937 return true
938 }
939 }
940 return false
941 }
942
943 func (kp *KeyPath) FirstGlob() int {
944 if kp == nil {
945 return -1
946 }
947 for i, el := range kp.Path {
948 if el.UnquotedString != nil && len(el.UnquotedString.Pattern) > 0 {
949 return i
950 }
951 }
952 return -1
953 }
954
955 func (kp *KeyPath) HasTripleGlob() bool {
956 if kp == nil {
957 return false
958 }
959 for _, el := range kp.Path {
960 if el.UnquotedString != nil && IsTripleGlob(el.UnquotedString.Pattern) {
961 return true
962 }
963 }
964 return false
965 }
966
967 func (kp *KeyPath) HasMultiGlob() bool {
968 if kp == nil {
969 return false
970 }
971 for _, el := range kp.Path {
972 if el.UnquotedString != nil && (IsDoubleGlob(el.UnquotedString.Pattern) || IsTripleGlob(el.UnquotedString.Pattern)) {
973 return true
974 }
975 }
976 return false
977 }
978
979 func (kp1 *KeyPath) Equals(kp2 *KeyPath) bool {
980 if len(kp1.Path) != len(kp2.Path) {
981 return false
982 }
983 for i, id := range kp1.Path {
984 if id.Unbox().ScalarString() != kp2.Path[i].Unbox().ScalarString() {
985 return false
986 }
987 }
988 return true
989 }
990
991 type Edge struct {
992 Range Range `json:"range"`
993
994 Src *KeyPath `json:"src"`
995
996 SrcArrow string `json:"src_arrow"`
997
998 Dst *KeyPath `json:"dst"`
999
1000 DstArrow string `json:"dst_arrow"`
1001 }
1002
1003 func (e1 *Edge) Equals(e2 *Edge) bool {
1004 if !e1.Src.Equals(e2.Src) {
1005 return false
1006 }
1007 if e1.SrcArrow != e2.SrcArrow {
1008 return false
1009 }
1010 if !e1.Dst.Equals(e2.Dst) {
1011 return false
1012 }
1013 if e1.DstArrow != e2.DstArrow {
1014 return false
1015 }
1016 return true
1017 }
1018
1019 type EdgeIndex struct {
1020 Range Range `json:"range"`
1021
1022
1023 Int *int `json:"int"`
1024 Glob bool `json:"glob"`
1025 }
1026
1027 func (ei1 *EdgeIndex) Equals(ei2 *EdgeIndex) bool {
1028 if ei1.Int != ei2.Int {
1029 return false
1030 }
1031 if ei1.Glob != ei2.Glob {
1032 return false
1033 }
1034 return true
1035 }
1036
1037 type Substitution struct {
1038 Range Range `json:"range"`
1039
1040 Spread bool `json:"spread"`
1041 Path []*StringBox `json:"path"`
1042 }
1043
1044 type Import struct {
1045 Range Range `json:"range"`
1046
1047 Spread bool `json:"spread"`
1048 Pre string `json:"pre"`
1049 Path []*StringBox `json:"path"`
1050 }
1051
1052
1053 type MapNodeBox struct {
1054 Comment *Comment `json:"comment,omitempty"`
1055 BlockComment *BlockComment `json:"block_comment,omitempty"`
1056 Substitution *Substitution `json:"substitution,omitempty"`
1057 Import *Import `json:"import,omitempty"`
1058 MapKey *Key `json:"map_key,omitempty"`
1059 }
1060
1061 func MakeMapNodeBox(n MapNode) MapNodeBox {
1062 var box MapNodeBox
1063 switch n := n.(type) {
1064 case *Comment:
1065 box.Comment = n
1066 case *BlockComment:
1067 box.BlockComment = n
1068 case *Substitution:
1069 box.Substitution = n
1070 case *Import:
1071 box.Import = n
1072 case *Key:
1073 box.MapKey = n
1074 }
1075 return box
1076 }
1077
1078 func (mb MapNodeBox) Unbox() MapNode {
1079 switch {
1080 case mb.Comment != nil:
1081 return mb.Comment
1082 case mb.BlockComment != nil:
1083 return mb.BlockComment
1084 case mb.Substitution != nil:
1085 return mb.Substitution
1086 case mb.Import != nil:
1087 return mb.Import
1088 case mb.MapKey != nil:
1089 return mb.MapKey
1090 default:
1091 return nil
1092 }
1093 }
1094
1095 func (mb MapNodeBox) IsBoardNode() bool {
1096 if mb.MapKey == nil || mb.MapKey.Key == nil || len(mb.MapKey.Key.Path) != 1 {
1097 return false
1098 }
1099 switch mb.MapKey.Key.Path[0].Unbox().ScalarString() {
1100 case "layers", "scenarios", "steps":
1101 return true
1102 default:
1103 return false
1104 }
1105 }
1106
1107
1108 type ArrayNodeBox struct {
1109 Comment *Comment `json:"comment,omitempty"`
1110 BlockComment *BlockComment `json:"block_comment,omitempty"`
1111 Substitution *Substitution `json:"substitution,omitempty"`
1112 Import *Import `json:"import,omitempty"`
1113 Null *Null `json:"null,omitempty"`
1114 Boolean *Boolean `json:"boolean,omitempty"`
1115 Number *Number `json:"number,omitempty"`
1116 UnquotedString *UnquotedString `json:"unquoted_string,omitempty"`
1117 DoubleQuotedString *DoubleQuotedString `json:"double_quoted_string,omitempty"`
1118 SingleQuotedString *SingleQuotedString `json:"single_quoted_string,omitempty"`
1119 BlockString *BlockString `json:"block_string,omitempty"`
1120 Array *Array `json:"array,omitempty"`
1121 Map *Map `json:"map,omitempty"`
1122 }
1123
1124 func MakeArrayNodeBox(an ArrayNode) ArrayNodeBox {
1125 var ab ArrayNodeBox
1126 switch an := an.(type) {
1127 case *Comment:
1128 ab.Comment = an
1129 case *BlockComment:
1130 ab.BlockComment = an
1131 case *Substitution:
1132 ab.Substitution = an
1133 case *Import:
1134 ab.Import = an
1135 case *Null:
1136 ab.Null = an
1137 case *Boolean:
1138 ab.Boolean = an
1139 case *Number:
1140 ab.Number = an
1141 case *UnquotedString:
1142 ab.UnquotedString = an
1143 case *DoubleQuotedString:
1144 ab.DoubleQuotedString = an
1145 case *SingleQuotedString:
1146 ab.SingleQuotedString = an
1147 case *BlockString:
1148 ab.BlockString = an
1149 case *Array:
1150 ab.Array = an
1151 case *Map:
1152 ab.Map = an
1153 }
1154 return ab
1155 }
1156
1157 func (ab ArrayNodeBox) Unbox() ArrayNode {
1158 switch {
1159 case ab.Comment != nil:
1160 return ab.Comment
1161 case ab.BlockComment != nil:
1162 return ab.BlockComment
1163 case ab.Substitution != nil:
1164 return ab.Substitution
1165 case ab.Import != nil:
1166 return ab.Import
1167 case ab.Null != nil:
1168 return ab.Null
1169 case ab.Boolean != nil:
1170 return ab.Boolean
1171 case ab.Number != nil:
1172 return ab.Number
1173 case ab.UnquotedString != nil:
1174 return ab.UnquotedString
1175 case ab.DoubleQuotedString != nil:
1176 return ab.DoubleQuotedString
1177 case ab.SingleQuotedString != nil:
1178 return ab.SingleQuotedString
1179 case ab.BlockString != nil:
1180 return ab.BlockString
1181 case ab.Array != nil:
1182 return ab.Array
1183 case ab.Map != nil:
1184 return ab.Map
1185 default:
1186 return nil
1187 }
1188 }
1189
1190
1191 type ValueBox struct {
1192 Null *Null `json:"null,omitempty"`
1193 Boolean *Boolean `json:"boolean,omitempty"`
1194 Number *Number `json:"number,omitempty"`
1195 UnquotedString *UnquotedString `json:"unquoted_string,omitempty"`
1196 DoubleQuotedString *DoubleQuotedString `json:"double_quoted_string,omitempty"`
1197 SingleQuotedString *SingleQuotedString `json:"single_quoted_string,omitempty"`
1198 BlockString *BlockString `json:"block_string,omitempty"`
1199 Array *Array `json:"array,omitempty"`
1200 Map *Map `json:"map,omitempty"`
1201 Import *Import `json:"import,omitempty"`
1202 }
1203
1204 func (vb ValueBox) Unbox() Value {
1205 switch {
1206 case vb.Null != nil:
1207 return vb.Null
1208 case vb.Boolean != nil:
1209 return vb.Boolean
1210 case vb.Number != nil:
1211 return vb.Number
1212 case vb.UnquotedString != nil:
1213 return vb.UnquotedString
1214 case vb.DoubleQuotedString != nil:
1215 return vb.DoubleQuotedString
1216 case vb.SingleQuotedString != nil:
1217 return vb.SingleQuotedString
1218 case vb.BlockString != nil:
1219 return vb.BlockString
1220 case vb.Array != nil:
1221 return vb.Array
1222 case vb.Map != nil:
1223 return vb.Map
1224 case vb.Import != nil:
1225 return vb.Import
1226 default:
1227 return nil
1228 }
1229 }
1230
1231 func MakeValueBox(v Value) ValueBox {
1232 var vb ValueBox
1233 switch v := v.(type) {
1234 case *Null:
1235 vb.Null = v
1236 case *Boolean:
1237 vb.Boolean = v
1238 case *Number:
1239 vb.Number = v
1240 case *UnquotedString:
1241 vb.UnquotedString = v
1242 case *DoubleQuotedString:
1243 vb.DoubleQuotedString = v
1244 case *SingleQuotedString:
1245 vb.SingleQuotedString = v
1246 case *BlockString:
1247 vb.BlockString = v
1248 case *Array:
1249 vb.Array = v
1250 case *Map:
1251 vb.Map = v
1252 case *Import:
1253 vb.Import = v
1254 }
1255 return vb
1256 }
1257
1258 func (vb ValueBox) ScalarBox() ScalarBox {
1259 var sb ScalarBox
1260 sb.Null = vb.Null
1261 sb.Boolean = vb.Boolean
1262 sb.Number = vb.Number
1263 sb.UnquotedString = vb.UnquotedString
1264 sb.DoubleQuotedString = vb.DoubleQuotedString
1265 sb.SingleQuotedString = vb.SingleQuotedString
1266 sb.BlockString = vb.BlockString
1267 return sb
1268 }
1269
1270 func (vb ValueBox) StringBox() *StringBox {
1271 var sb StringBox
1272 sb.UnquotedString = vb.UnquotedString
1273 sb.DoubleQuotedString = vb.DoubleQuotedString
1274 sb.SingleQuotedString = vb.SingleQuotedString
1275 sb.BlockString = vb.BlockString
1276 return &sb
1277 }
1278
1279
1280
1281 type ScalarBox struct {
1282 Null *Null `json:"null,omitempty"`
1283 Boolean *Boolean `json:"boolean,omitempty"`
1284 Number *Number `json:"number,omitempty"`
1285 UnquotedString *UnquotedString `json:"unquoted_string,omitempty"`
1286 DoubleQuotedString *DoubleQuotedString `json:"double_quoted_string,omitempty"`
1287 SingleQuotedString *SingleQuotedString `json:"single_quoted_string,omitempty"`
1288 BlockString *BlockString `json:"block_string,omitempty"`
1289 }
1290
1291 func (sb ScalarBox) Unbox() Scalar {
1292 switch {
1293 case sb.Null != nil:
1294 return sb.Null
1295 case sb.Boolean != nil:
1296 return sb.Boolean
1297 case sb.Number != nil:
1298 return sb.Number
1299 case sb.UnquotedString != nil:
1300 return sb.UnquotedString
1301 case sb.DoubleQuotedString != nil:
1302 return sb.DoubleQuotedString
1303 case sb.SingleQuotedString != nil:
1304 return sb.SingleQuotedString
1305 case sb.BlockString != nil:
1306 return sb.BlockString
1307 default:
1308 return nil
1309 }
1310 }
1311
1312 func (sb ScalarBox) ScalarString() string {
1313 return sb.Unbox().ScalarString()
1314 }
1315
1316
1317 type StringBox struct {
1318 UnquotedString *UnquotedString `json:"unquoted_string,omitempty"`
1319 DoubleQuotedString *DoubleQuotedString `json:"double_quoted_string,omitempty"`
1320 SingleQuotedString *SingleQuotedString `json:"single_quoted_string,omitempty"`
1321 BlockString *BlockString `json:"block_string,omitempty"`
1322 }
1323
1324 func (sb *StringBox) Unbox() String {
1325 switch {
1326 case sb.UnquotedString != nil:
1327 return sb.UnquotedString
1328 case sb.DoubleQuotedString != nil:
1329 return sb.DoubleQuotedString
1330 case sb.SingleQuotedString != nil:
1331 return sb.SingleQuotedString
1332 case sb.BlockString != nil:
1333 return sb.BlockString
1334 default:
1335 return nil
1336 }
1337 }
1338
1339 func (sb *StringBox) ScalarString() string {
1340 return sb.Unbox().ScalarString()
1341 }
1342
1343
1344
1345
1346 type InterpolationBox struct {
1347 String *string `json:"string,omitempty"`
1348 StringRaw *string `json:"raw_string,omitempty"`
1349 Substitution *Substitution `json:"substitution,omitempty"`
1350 }
1351
1352
1353
1354
1355 var UnquotedKeySpecials = string([]rune{'#', ';', '\n', '\\', '{', '}', '[', ']', '\'', '"', '|', ':', '.', '-', '<', '>', '*', '&', '(', ')', '@', '&'})
1356 var UnquotedValueSpecials = string([]rune{'#', ';', '\n', '\\', '{', '}', '[', ']', '\'', '"', '|', '$', '@'})
1357
1358
1359
1360 func RawString(s string, inKey bool) String {
1361 if s == "" {
1362 return FlatDoubleQuotedString(s)
1363 }
1364
1365 if inKey {
1366 for i, r := range s {
1367 switch r {
1368 case '-':
1369 if i+1 < len(s) && s[i+1] != '-' {
1370 continue
1371 }
1372 }
1373 if strings.ContainsRune(UnquotedKeySpecials, r) {
1374 if !strings.ContainsRune(s, '"') {
1375 return FlatDoubleQuotedString(s)
1376 }
1377 if strings.ContainsRune(s, '\n') {
1378 return FlatDoubleQuotedString(s)
1379 }
1380 return &SingleQuotedString{Value: s}
1381 }
1382 }
1383 } else if s == "null" || strings.ContainsAny(s, UnquotedValueSpecials) {
1384 if !strings.ContainsRune(s, '"') && !strings.ContainsRune(s, '$') {
1385 return FlatDoubleQuotedString(s)
1386 }
1387 if strings.ContainsRune(s, '\n') {
1388 return FlatDoubleQuotedString(s)
1389 }
1390 return &SingleQuotedString{Value: s}
1391 }
1392
1393 if hasSurroundingWhitespace(s) {
1394 return FlatDoubleQuotedString(s)
1395 }
1396
1397 return FlatUnquotedString(s)
1398 }
1399
1400 func RawStringBox(s string, inKey bool) *StringBox {
1401 return MakeValueBox(RawString(s, inKey)).StringBox()
1402 }
1403
1404 func hasSurroundingWhitespace(s string) bool {
1405 r, _ := utf8.DecodeRuneInString(s)
1406 r2, _ := utf8.DecodeLastRuneInString(s)
1407 return unicode.IsSpace(r) || unicode.IsSpace(r2)
1408 }
1409
1410 func (s *Substitution) IDA() (ida []string) {
1411 for _, el := range s.Path {
1412 ida = append(ida, el.Unbox().ScalarString())
1413 }
1414 return ida
1415 }
1416
1417 func (i *Import) IDA() (ida []string) {
1418 for _, el := range i.Path[1:] {
1419 ida = append(ida, el.Unbox().ScalarString())
1420 }
1421 return ida
1422 }
1423
1424 func (i *Import) PathWithPre() string {
1425 if len(i.Path) == 0 {
1426 return ""
1427 }
1428 return path.Join(i.Pre, i.Path[0].Unbox().ScalarString())
1429 }
1430
View as plain text