1
2
3
4
5
6
7 package syntax
8
9 import (
10 "fmt"
11 "io"
12 "strings"
13 )
14
15
16 type Form uint
17
18 const (
19 _ Form = iota
20 LineForm
21 ShortForm
22 )
23
24
25
26 func Fprint(w io.Writer, x Node, form Form) (n int, err error) {
27 p := printer{
28 output: w,
29 form: form,
30 linebreaks: form == 0,
31 }
32
33 defer func() {
34 n = p.written
35 if e := recover(); e != nil {
36 err = e.(writeError).err
37 }
38 }()
39
40 p.print(x)
41 p.flush(_EOF)
42
43 return
44 }
45
46
47
48 func String(n Node) string {
49 var buf strings.Builder
50 _, err := Fprint(&buf, n, ShortForm)
51 if err != nil {
52 fmt.Fprintf(&buf, "<<< ERROR: %s", err)
53 }
54 return buf.String()
55 }
56
57 type ctrlSymbol int
58
59 const (
60 none ctrlSymbol = iota
61 semi
62 blank
63 newline
64 indent
65 outdent
66
67
68 )
69
70 type whitespace struct {
71 last token
72 kind ctrlSymbol
73
74 }
75
76 type printer struct {
77 output io.Writer
78 written int
79 form Form
80 linebreaks bool
81
82 indent int
83 nlcount int
84
85 pending []whitespace
86 lastTok token
87 }
88
89
90
91 func (p *printer) write(data []byte) {
92 n, err := p.output.Write(data)
93 p.written += n
94 if err != nil {
95 panic(writeError{err})
96 }
97 }
98
99 var (
100 tabBytes = []byte("\t\t\t\t\t\t\t\t")
101 newlineByte = []byte("\n")
102 blankByte = []byte(" ")
103 )
104
105 func (p *printer) writeBytes(data []byte) {
106 if len(data) == 0 {
107 panic("expected non-empty []byte")
108 }
109 if p.nlcount > 0 && p.indent > 0 {
110
111 n := p.indent
112 for n > len(tabBytes) {
113 p.write(tabBytes)
114 n -= len(tabBytes)
115 }
116 p.write(tabBytes[:n])
117 }
118 p.write(data)
119 p.nlcount = 0
120 }
121
122 func (p *printer) writeString(s string) {
123 p.writeBytes([]byte(s))
124 }
125
126
127
128
129 func impliesSemi(tok token) bool {
130 switch tok {
131 case _Name,
132 _Break, _Continue, _Fallthrough, _Return,
133 _Rparen, _Rbrack, _Rbrace:
134 return true
135 }
136 return false
137 }
138
139
140
141 func (p *printer) addWhitespace(kind ctrlSymbol, text string) {
142 p.pending = append(p.pending, whitespace{p.lastTok, kind })
143 switch kind {
144 case semi:
145 p.lastTok = _Semi
146 case newline:
147 p.lastTok = 0
148
149 }
150 }
151
152 func (p *printer) flush(next token) {
153
154 sawNewline := next == _EOF
155 sawParen := next == _Rparen || next == _Rbrace
156 for i := len(p.pending) - 1; i >= 0; i-- {
157 switch p.pending[i].kind {
158 case semi:
159 k := semi
160 if sawParen {
161 sawParen = false
162 k = none
163 } else if sawNewline && impliesSemi(p.pending[i].last) {
164 sawNewline = false
165 k = none
166 }
167 p.pending[i].kind = k
168 case newline:
169 sawNewline = true
170 case blank, indent, outdent:
171
172
173
174
175
176
177
178
179
180 default:
181 panic("unreachable")
182 }
183 }
184
185
186 prev := none
187 for i := range p.pending {
188 switch p.pending[i].kind {
189 case none:
190
191 case semi:
192 p.writeString(";")
193 p.nlcount = 0
194 prev = semi
195 case blank:
196 if prev != blank {
197
198 p.writeBytes(blankByte)
199 p.nlcount = 0
200 prev = blank
201 }
202 case newline:
203 const maxEmptyLines = 1
204 if p.nlcount <= maxEmptyLines {
205 p.write(newlineByte)
206 p.nlcount++
207 prev = newline
208 }
209 case indent:
210 p.indent++
211 case outdent:
212 p.indent--
213 if p.indent < 0 {
214 panic("negative indentation")
215 }
216
217
218
219
220
221
222
223 default:
224 panic("unreachable")
225 }
226 }
227
228 p.pending = p.pending[:0]
229 }
230
231 func mayCombine(prev token, next byte) (b bool) {
232 return
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 }
249
250 func (p *printer) print(args ...any) {
251 for i := 0; i < len(args); i++ {
252 switch x := args[i].(type) {
253 case nil:
254
255
256 case Node:
257 p.printNode(x)
258
259 case token:
260
261
262 var s string
263 if x == _Name {
264 i++
265 if i >= len(args) {
266 panic("missing string argument after _Name")
267 }
268 s = args[i].(string)
269 } else {
270 s = x.String()
271 }
272
273
274
275 if mayCombine(p.lastTok, s[0]) {
276 panic("adjacent tokens combine without whitespace")
277 }
278
279 if x == _Semi {
280
281 p.addWhitespace(semi, "")
282 } else {
283 p.flush(x)
284 p.writeString(s)
285 p.nlcount = 0
286 p.lastTok = x
287 }
288
289 case Operator:
290 if x != 0 {
291 p.flush(_Operator)
292 p.writeString(x.String())
293 }
294
295 case ctrlSymbol:
296 switch x {
297 case none, semi :
298 panic("unreachable")
299 case newline:
300
301 if !p.linebreaks {
302 x = blank
303 }
304 }
305 p.addWhitespace(x, "")
306
307
308
309
310 default:
311 panic(fmt.Sprintf("unexpected argument %v (%T)", x, x))
312 }
313 }
314 }
315
316 func (p *printer) printNode(n Node) {
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334 p.printRawNode(n)
335
336
337
338
339
340
341
342
343
344
345
346
347 }
348
349 func (p *printer) printRawNode(n Node) {
350 switch n := n.(type) {
351 case nil:
352
353
354
355 case *BadExpr:
356 p.print(_Name, "<bad expr>")
357
358 case *Name:
359 p.print(_Name, n.Value)
360
361 case *BasicLit:
362 p.print(_Name, n.Value)
363
364 case *FuncLit:
365 p.print(n.Type, blank)
366 if n.Body != nil {
367 if p.form == ShortForm {
368 p.print(_Lbrace)
369 if len(n.Body.List) > 0 {
370 p.print(_Name, "…")
371 }
372 p.print(_Rbrace)
373 } else {
374 p.print(n.Body)
375 }
376 }
377
378 case *CompositeLit:
379 if n.Type != nil {
380 p.print(n.Type)
381 }
382 p.print(_Lbrace)
383 if p.form == ShortForm {
384 if len(n.ElemList) > 0 {
385 p.print(_Name, "…")
386 }
387 } else {
388 if n.NKeys > 0 && n.NKeys == len(n.ElemList) {
389 p.printExprLines(n.ElemList)
390 } else {
391 p.printExprList(n.ElemList)
392 }
393 }
394 p.print(_Rbrace)
395
396 case *ParenExpr:
397 p.print(_Lparen, n.X, _Rparen)
398
399 case *SelectorExpr:
400 p.print(n.X, _Dot, n.Sel)
401
402 case *IndexExpr:
403 p.print(n.X, _Lbrack, n.Index, _Rbrack)
404
405 case *SliceExpr:
406 p.print(n.X, _Lbrack)
407 if i := n.Index[0]; i != nil {
408 p.printNode(i)
409 }
410 p.print(_Colon)
411 if j := n.Index[1]; j != nil {
412 p.printNode(j)
413 }
414 if k := n.Index[2]; k != nil {
415 p.print(_Colon, k)
416 }
417 p.print(_Rbrack)
418
419 case *AssertExpr:
420 p.print(n.X, _Dot, _Lparen, n.Type, _Rparen)
421
422 case *TypeSwitchGuard:
423 if n.Lhs != nil {
424 p.print(n.Lhs, blank, _Define, blank)
425 }
426 p.print(n.X, _Dot, _Lparen, _Type, _Rparen)
427
428 case *CallExpr:
429 p.print(n.Fun, _Lparen)
430 p.printExprList(n.ArgList)
431 if n.HasDots {
432 p.print(_DotDotDot)
433 }
434 p.print(_Rparen)
435
436 case *Operation:
437 if n.Y == nil {
438
439 p.print(n.Op)
440
441
442
443 p.print(n.X)
444 } else {
445
446
447
448 p.print(n.X, blank, n.Op, blank, n.Y)
449 }
450
451 case *KeyValueExpr:
452 p.print(n.Key, _Colon, blank, n.Value)
453
454 case *ListExpr:
455 p.printExprList(n.ElemList)
456
457 case *ArrayType:
458 var len any = _DotDotDot
459 if n.Len != nil {
460 len = n.Len
461 }
462 p.print(_Lbrack, len, _Rbrack, n.Elem)
463
464 case *SliceType:
465 p.print(_Lbrack, _Rbrack, n.Elem)
466
467 case *DotsType:
468 p.print(_DotDotDot, n.Elem)
469
470 case *StructType:
471 p.print(_Struct)
472 if len(n.FieldList) > 0 && p.linebreaks {
473 p.print(blank)
474 }
475 p.print(_Lbrace)
476 if len(n.FieldList) > 0 {
477 if p.linebreaks {
478 p.print(newline, indent)
479 p.printFieldList(n.FieldList, n.TagList, _Semi)
480 p.print(outdent, newline)
481 } else {
482 p.printFieldList(n.FieldList, n.TagList, _Semi)
483 }
484 }
485 p.print(_Rbrace)
486
487 case *FuncType:
488 p.print(_Func)
489 p.printSignature(n)
490
491 case *InterfaceType:
492 p.print(_Interface)
493 if p.linebreaks && len(n.MethodList) > 1 {
494 p.print(blank)
495 p.print(_Lbrace)
496 p.print(newline, indent)
497 p.printMethodList(n.MethodList)
498 p.print(outdent, newline)
499 } else {
500 p.print(_Lbrace)
501 p.printMethodList(n.MethodList)
502 }
503 p.print(_Rbrace)
504
505 case *MapType:
506 p.print(_Map, _Lbrack, n.Key, _Rbrack, n.Value)
507
508 case *ChanType:
509 if n.Dir == RecvOnly {
510 p.print(_Arrow)
511 }
512 p.print(_Chan)
513 if n.Dir == SendOnly {
514 p.print(_Arrow)
515 }
516 p.print(blank)
517 if e, _ := n.Elem.(*ChanType); n.Dir == 0 && e != nil && e.Dir == RecvOnly {
518
519 p.print(_Lparen)
520 p.print(n.Elem)
521 p.print(_Rparen)
522 } else {
523 p.print(n.Elem)
524 }
525
526
527 case *DeclStmt:
528 if len(n.DeclList) > 0 {
529 p.printDecl(n.DeclList)
530 }
531
532 case *EmptyStmt:
533
534
535 case *LabeledStmt:
536 p.print(outdent, n.Label, _Colon, indent, newline, n.Stmt)
537
538 case *ExprStmt:
539 p.print(n.X)
540
541 case *SendStmt:
542 p.print(n.Chan, blank, _Arrow, blank, n.Value)
543
544 case *AssignStmt:
545 p.print(n.Lhs)
546 if n.Rhs == nil {
547
548
549 p.print(n.Op, n.Op)
550 } else {
551 p.print(blank, n.Op, _Assign, blank)
552 p.print(n.Rhs)
553 }
554
555 case *CallStmt:
556 p.print(n.Tok, blank, n.Call)
557
558 case *ReturnStmt:
559 p.print(_Return)
560 if n.Results != nil {
561 p.print(blank, n.Results)
562 }
563
564 case *BranchStmt:
565 p.print(n.Tok)
566 if n.Label != nil {
567 p.print(blank, n.Label)
568 }
569
570 case *BlockStmt:
571 p.print(_Lbrace)
572 if len(n.List) > 0 {
573 p.print(newline, indent)
574 p.printStmtList(n.List, true)
575 p.print(outdent, newline)
576 }
577 p.print(_Rbrace)
578
579 case *IfStmt:
580 p.print(_If, blank)
581 if n.Init != nil {
582 p.print(n.Init, _Semi, blank)
583 }
584 p.print(n.Cond, blank, n.Then)
585 if n.Else != nil {
586 p.print(blank, _Else, blank, n.Else)
587 }
588
589 case *SwitchStmt:
590 p.print(_Switch, blank)
591 if n.Init != nil {
592 p.print(n.Init, _Semi, blank)
593 }
594 if n.Tag != nil {
595 p.print(n.Tag, blank)
596 }
597 p.printSwitchBody(n.Body)
598
599 case *SelectStmt:
600 p.print(_Select, blank)
601 p.printSelectBody(n.Body)
602
603 case *RangeClause:
604 if n.Lhs != nil {
605 tok := _Assign
606 if n.Def {
607 tok = _Define
608 }
609 p.print(n.Lhs, blank, tok, blank)
610 }
611 p.print(_Range, blank, n.X)
612
613 case *ForStmt:
614 p.print(_For, blank)
615 if n.Init == nil && n.Post == nil {
616 if n.Cond != nil {
617 p.print(n.Cond, blank)
618 }
619 } else {
620 if n.Init != nil {
621 p.print(n.Init)
622
623 if _, ok := n.Init.(*RangeClause); ok {
624 p.print(blank, n.Body)
625 break
626 }
627 }
628 p.print(_Semi, blank)
629 if n.Cond != nil {
630 p.print(n.Cond)
631 }
632 p.print(_Semi, blank)
633 if n.Post != nil {
634 p.print(n.Post, blank)
635 }
636 }
637 p.print(n.Body)
638
639 case *ImportDecl:
640 if n.Group == nil {
641 p.print(_Import, blank)
642 }
643 if n.LocalPkgName != nil {
644 p.print(n.LocalPkgName, blank)
645 }
646 p.print(n.Path)
647
648 case *ConstDecl:
649 if n.Group == nil {
650 p.print(_Const, blank)
651 }
652 p.printNameList(n.NameList)
653 if n.Type != nil {
654 p.print(blank, n.Type)
655 }
656 if n.Values != nil {
657 p.print(blank, _Assign, blank, n.Values)
658 }
659
660 case *TypeDecl:
661 if n.Group == nil {
662 p.print(_Type, blank)
663 }
664 p.print(n.Name)
665 if n.TParamList != nil {
666 p.printParameterList(n.TParamList, _Type)
667 }
668 p.print(blank)
669 if n.Alias {
670 p.print(_Assign, blank)
671 }
672 p.print(n.Type)
673
674 case *VarDecl:
675 if n.Group == nil {
676 p.print(_Var, blank)
677 }
678 p.printNameList(n.NameList)
679 if n.Type != nil {
680 p.print(blank, n.Type)
681 }
682 if n.Values != nil {
683 p.print(blank, _Assign, blank, n.Values)
684 }
685
686 case *FuncDecl:
687 p.print(_Func, blank)
688 if r := n.Recv; r != nil {
689 p.print(_Lparen)
690 if r.Name != nil {
691 p.print(r.Name, blank)
692 }
693 p.printNode(r.Type)
694 p.print(_Rparen, blank)
695 }
696 p.print(n.Name)
697 if n.TParamList != nil {
698 p.printParameterList(n.TParamList, _Func)
699 }
700 p.printSignature(n.Type)
701 if n.Body != nil {
702 p.print(blank, n.Body)
703 }
704
705 case *printGroup:
706 p.print(n.Tok, blank, _Lparen)
707 if len(n.Decls) > 0 {
708 p.print(newline, indent)
709 for _, d := range n.Decls {
710 p.printNode(d)
711 p.print(_Semi, newline)
712 }
713 p.print(outdent)
714 }
715 p.print(_Rparen)
716
717
718 case *File:
719 p.print(_Package, blank, n.PkgName)
720 if len(n.DeclList) > 0 {
721 p.print(_Semi, newline, newline)
722 p.printDeclList(n.DeclList)
723 }
724
725 default:
726 panic(fmt.Sprintf("syntax.Iterate: unexpected node type %T", n))
727 }
728 }
729
730 func (p *printer) printFields(fields []*Field, tags []*BasicLit, i, j int) {
731 if i+1 == j && fields[i].Name == nil {
732
733 p.printNode(fields[i].Type)
734 } else {
735 for k, f := range fields[i:j] {
736 if k > 0 {
737 p.print(_Comma, blank)
738 }
739 p.printNode(f.Name)
740 }
741 p.print(blank)
742 p.printNode(fields[i].Type)
743 }
744 if i < len(tags) && tags[i] != nil {
745 p.print(blank)
746 p.printNode(tags[i])
747 }
748 }
749
750 func (p *printer) printFieldList(fields []*Field, tags []*BasicLit, sep token) {
751 i0 := 0
752 var typ Expr
753 for i, f := range fields {
754 if f.Name == nil || f.Type != typ {
755 if i0 < i {
756 p.printFields(fields, tags, i0, i)
757 p.print(sep, newline)
758 i0 = i
759 }
760 typ = f.Type
761 }
762 }
763 p.printFields(fields, tags, i0, len(fields))
764 }
765
766 func (p *printer) printMethodList(methods []*Field) {
767 for i, m := range methods {
768 if i > 0 {
769 p.print(_Semi, newline)
770 }
771 if m.Name != nil {
772 p.printNode(m.Name)
773 p.printSignature(m.Type.(*FuncType))
774 } else {
775 p.printNode(m.Type)
776 }
777 }
778 }
779
780 func (p *printer) printNameList(list []*Name) {
781 for i, x := range list {
782 if i > 0 {
783 p.print(_Comma, blank)
784 }
785 p.printNode(x)
786 }
787 }
788
789 func (p *printer) printExprList(list []Expr) {
790 for i, x := range list {
791 if i > 0 {
792 p.print(_Comma, blank)
793 }
794 p.printNode(x)
795 }
796 }
797
798 func (p *printer) printExprLines(list []Expr) {
799 if len(list) > 0 {
800 p.print(newline, indent)
801 for _, x := range list {
802 p.print(x, _Comma, newline)
803 }
804 p.print(outdent)
805 }
806 }
807
808 func groupFor(d Decl) (token, *Group) {
809 switch d := d.(type) {
810 case *ImportDecl:
811 return _Import, d.Group
812 case *ConstDecl:
813 return _Const, d.Group
814 case *TypeDecl:
815 return _Type, d.Group
816 case *VarDecl:
817 return _Var, d.Group
818 case *FuncDecl:
819 return _Func, nil
820 default:
821 panic("unreachable")
822 }
823 }
824
825 type printGroup struct {
826 node
827 Tok token
828 Decls []Decl
829 }
830
831 func (p *printer) printDecl(list []Decl) {
832 tok, group := groupFor(list[0])
833
834 if group == nil {
835 if len(list) != 1 {
836 panic("unreachable")
837 }
838 p.printNode(list[0])
839 return
840 }
841
842
843
844
845
846
847
848
849
850
851
852
853 var pg printGroup
854
855 pg.Tok = tok
856 pg.Decls = list
857 p.printNode(&pg)
858 }
859
860 func (p *printer) printDeclList(list []Decl) {
861 i0 := 0
862 var tok token
863 var group *Group
864 for i, x := range list {
865 if s, g := groupFor(x); g == nil || g != group {
866 if i0 < i {
867 p.printDecl(list[i0:i])
868 p.print(_Semi, newline)
869
870
871 if g != group || s != tok || s == _Func {
872 p.print(newline)
873 }
874 i0 = i
875 }
876 tok, group = s, g
877 }
878 }
879 if i0 < len(list) {
880 p.printDecl(list[i0:])
881 }
882 }
883
884 func (p *printer) printSignature(sig *FuncType) {
885 p.printParameterList(sig.ParamList, 0)
886 if list := sig.ResultList; list != nil {
887 p.print(blank)
888 if len(list) == 1 && list[0].Name == nil {
889 p.printNode(list[0].Type)
890 } else {
891 p.printParameterList(list, 0)
892 }
893 }
894 }
895
896
897
898
899 func (p *printer) printParameterList(list []*Field, tok token) {
900 open, close := _Lparen, _Rparen
901 if tok != 0 {
902 open, close = _Lbrack, _Rbrack
903 }
904 p.print(open)
905 for i, f := range list {
906 if i > 0 {
907 p.print(_Comma, blank)
908 }
909 if f.Name != nil {
910 p.printNode(f.Name)
911 if i+1 < len(list) {
912 f1 := list[i+1]
913 if f1.Name != nil && f1.Type == f.Type {
914 continue
915 }
916 }
917 p.print(blank)
918 }
919 p.printNode(f.Type)
920 }
921
922
923
924
925 if tok == _Type && len(list) == 1 && combinesWithName(list[0].Type) {
926 p.print(_Comma)
927 }
928 p.print(close)
929 }
930
931
932
933
934
935
936 func combinesWithName(x Expr) bool {
937 switch x := x.(type) {
938 case *Operation:
939 if x.Y == nil {
940
941 return x.Op == Mul && !isTypeElem(x.X)
942 }
943
944 return combinesWithName(x.X) && !isTypeElem(x.Y)
945 case *ParenExpr:
946
947
948
949
950
951
952 return !isTypeElem(x.X)
953 }
954 return false
955 }
956
957 func (p *printer) printStmtList(list []Stmt, braces bool) {
958 for i, x := range list {
959 p.print(x, _Semi)
960 if i+1 < len(list) {
961 p.print(newline)
962 } else if braces {
963
964
965
966 if _, ok := x.(*EmptyStmt); ok {
967 p.print(x, _Semi)
968 }
969 }
970 }
971 }
972
973 func (p *printer) printSwitchBody(list []*CaseClause) {
974 p.print(_Lbrace)
975 if len(list) > 0 {
976 p.print(newline)
977 for i, c := range list {
978 p.printCaseClause(c, i+1 == len(list))
979 p.print(newline)
980 }
981 }
982 p.print(_Rbrace)
983 }
984
985 func (p *printer) printSelectBody(list []*CommClause) {
986 p.print(_Lbrace)
987 if len(list) > 0 {
988 p.print(newline)
989 for i, c := range list {
990 p.printCommClause(c, i+1 == len(list))
991 p.print(newline)
992 }
993 }
994 p.print(_Rbrace)
995 }
996
997 func (p *printer) printCaseClause(c *CaseClause, braces bool) {
998 if c.Cases != nil {
999 p.print(_Case, blank, c.Cases)
1000 } else {
1001 p.print(_Default)
1002 }
1003 p.print(_Colon)
1004 if len(c.Body) > 0 {
1005 p.print(newline, indent)
1006 p.printStmtList(c.Body, braces)
1007 p.print(outdent)
1008 }
1009 }
1010
1011 func (p *printer) printCommClause(c *CommClause, braces bool) {
1012 if c.Comm != nil {
1013 p.print(_Case, blank)
1014 p.print(c.Comm)
1015 } else {
1016 p.print(_Default)
1017 }
1018 p.print(_Colon)
1019 if len(c.Body) > 0 {
1020 p.print(newline, indent)
1021 p.printStmtList(c.Body, braces)
1022 p.print(outdent)
1023 }
1024 }
1025
View as plain text