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 ...interface{}) {
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 interface{} = _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 p.printDecl(n.DeclList)
529
530 case *EmptyStmt:
531
532
533 case *LabeledStmt:
534 p.print(outdent, n.Label, _Colon, indent, newline, n.Stmt)
535
536 case *ExprStmt:
537 p.print(n.X)
538
539 case *SendStmt:
540 p.print(n.Chan, blank, _Arrow, blank, n.Value)
541
542 case *AssignStmt:
543 p.print(n.Lhs)
544 if n.Rhs == nil {
545
546
547 p.print(n.Op, n.Op)
548 } else {
549 p.print(blank, n.Op, _Assign, blank)
550 p.print(n.Rhs)
551 }
552
553 case *CallStmt:
554 p.print(n.Tok, blank, n.Call)
555
556 case *ReturnStmt:
557 p.print(_Return)
558 if n.Results != nil {
559 p.print(blank, n.Results)
560 }
561
562 case *BranchStmt:
563 p.print(n.Tok)
564 if n.Label != nil {
565 p.print(blank, n.Label)
566 }
567
568 case *BlockStmt:
569 p.print(_Lbrace)
570 if len(n.List) > 0 {
571 p.print(newline, indent)
572 p.printStmtList(n.List, true)
573 p.print(outdent, newline)
574 }
575 p.print(_Rbrace)
576
577 case *IfStmt:
578 p.print(_If, blank)
579 if n.Init != nil {
580 p.print(n.Init, _Semi, blank)
581 }
582 p.print(n.Cond, blank, n.Then)
583 if n.Else != nil {
584 p.print(blank, _Else, blank, n.Else)
585 }
586
587 case *SwitchStmt:
588 p.print(_Switch, blank)
589 if n.Init != nil {
590 p.print(n.Init, _Semi, blank)
591 }
592 if n.Tag != nil {
593 p.print(n.Tag, blank)
594 }
595 p.printSwitchBody(n.Body)
596
597 case *SelectStmt:
598 p.print(_Select, blank)
599 p.printSelectBody(n.Body)
600
601 case *RangeClause:
602 if n.Lhs != nil {
603 tok := _Assign
604 if n.Def {
605 tok = _Define
606 }
607 p.print(n.Lhs, blank, tok, blank)
608 }
609 p.print(_Range, blank, n.X)
610
611 case *ForStmt:
612 p.print(_For, blank)
613 if n.Init == nil && n.Post == nil {
614 if n.Cond != nil {
615 p.print(n.Cond, blank)
616 }
617 } else {
618 if n.Init != nil {
619 p.print(n.Init)
620
621 if _, ok := n.Init.(*RangeClause); ok {
622 p.print(blank, n.Body)
623 break
624 }
625 }
626 p.print(_Semi, blank)
627 if n.Cond != nil {
628 p.print(n.Cond)
629 }
630 p.print(_Semi, blank)
631 if n.Post != nil {
632 p.print(n.Post, blank)
633 }
634 }
635 p.print(n.Body)
636
637 case *ImportDecl:
638 if n.Group == nil {
639 p.print(_Import, blank)
640 }
641 if n.LocalPkgName != nil {
642 p.print(n.LocalPkgName, blank)
643 }
644 p.print(n.Path)
645
646 case *ConstDecl:
647 if n.Group == nil {
648 p.print(_Const, blank)
649 }
650 p.printNameList(n.NameList)
651 if n.Type != nil {
652 p.print(blank, n.Type)
653 }
654 if n.Values != nil {
655 p.print(blank, _Assign, blank, n.Values)
656 }
657
658 case *TypeDecl:
659 if n.Group == nil {
660 p.print(_Type, blank)
661 }
662 p.print(n.Name)
663 if n.TParamList != nil {
664 p.printParameterList(n.TParamList, _Type)
665 }
666 p.print(blank)
667 if n.Alias {
668 p.print(_Assign, blank)
669 }
670 p.print(n.Type)
671
672 case *VarDecl:
673 if n.Group == nil {
674 p.print(_Var, blank)
675 }
676 p.printNameList(n.NameList)
677 if n.Type != nil {
678 p.print(blank, n.Type)
679 }
680 if n.Values != nil {
681 p.print(blank, _Assign, blank, n.Values)
682 }
683
684 case *FuncDecl:
685 p.print(_Func, blank)
686 if r := n.Recv; r != nil {
687 p.print(_Lparen)
688 if r.Name != nil {
689 p.print(r.Name, blank)
690 }
691 p.printNode(r.Type)
692 p.print(_Rparen, blank)
693 }
694 p.print(n.Name)
695 if n.TParamList != nil {
696 p.printParameterList(n.TParamList, _Func)
697 }
698 p.printSignature(n.Type)
699 if n.Body != nil {
700 p.print(blank, n.Body)
701 }
702
703 case *printGroup:
704 p.print(n.Tok, blank, _Lparen)
705 if len(n.Decls) > 0 {
706 p.print(newline, indent)
707 for _, d := range n.Decls {
708 p.printNode(d)
709 p.print(_Semi, newline)
710 }
711 p.print(outdent)
712 }
713 p.print(_Rparen)
714
715
716 case *File:
717 p.print(_Package, blank, n.PkgName)
718 if len(n.DeclList) > 0 {
719 p.print(_Semi, newline, newline)
720 p.printDeclList(n.DeclList)
721 }
722
723 default:
724 panic(fmt.Sprintf("syntax.Iterate: unexpected node type %T", n))
725 }
726 }
727
728 func (p *printer) printFields(fields []*Field, tags []*BasicLit, i, j int) {
729 if i+1 == j && fields[i].Name == nil {
730
731 p.printNode(fields[i].Type)
732 } else {
733 for k, f := range fields[i:j] {
734 if k > 0 {
735 p.print(_Comma, blank)
736 }
737 p.printNode(f.Name)
738 }
739 p.print(blank)
740 p.printNode(fields[i].Type)
741 }
742 if i < len(tags) && tags[i] != nil {
743 p.print(blank)
744 p.printNode(tags[i])
745 }
746 }
747
748 func (p *printer) printFieldList(fields []*Field, tags []*BasicLit, sep token) {
749 i0 := 0
750 var typ Expr
751 for i, f := range fields {
752 if f.Name == nil || f.Type != typ {
753 if i0 < i {
754 p.printFields(fields, tags, i0, i)
755 p.print(sep, newline)
756 i0 = i
757 }
758 typ = f.Type
759 }
760 }
761 p.printFields(fields, tags, i0, len(fields))
762 }
763
764 func (p *printer) printMethodList(methods []*Field) {
765 for i, m := range methods {
766 if i > 0 {
767 p.print(_Semi, newline)
768 }
769 if m.Name != nil {
770 p.printNode(m.Name)
771 p.printSignature(m.Type.(*FuncType))
772 } else {
773 p.printNode(m.Type)
774 }
775 }
776 }
777
778 func (p *printer) printNameList(list []*Name) {
779 for i, x := range list {
780 if i > 0 {
781 p.print(_Comma, blank)
782 }
783 p.printNode(x)
784 }
785 }
786
787 func (p *printer) printExprList(list []Expr) {
788 for i, x := range list {
789 if i > 0 {
790 p.print(_Comma, blank)
791 }
792 p.printNode(x)
793 }
794 }
795
796 func (p *printer) printExprLines(list []Expr) {
797 if len(list) > 0 {
798 p.print(newline, indent)
799 for _, x := range list {
800 p.print(x, _Comma, newline)
801 }
802 p.print(outdent)
803 }
804 }
805
806 func groupFor(d Decl) (token, *Group) {
807 switch d := d.(type) {
808 case *ImportDecl:
809 return _Import, d.Group
810 case *ConstDecl:
811 return _Const, d.Group
812 case *TypeDecl:
813 return _Type, d.Group
814 case *VarDecl:
815 return _Var, d.Group
816 case *FuncDecl:
817 return _Func, nil
818 default:
819 panic("unreachable")
820 }
821 }
822
823 type printGroup struct {
824 node
825 Tok token
826 Decls []Decl
827 }
828
829 func (p *printer) printDecl(list []Decl) {
830 tok, group := groupFor(list[0])
831
832 if group == nil {
833 if len(list) != 1 {
834 panic("unreachable")
835 }
836 p.printNode(list[0])
837 return
838 }
839
840
841
842
843
844
845
846
847
848
849
850
851 var pg printGroup
852
853 pg.Tok = tok
854 pg.Decls = list
855 p.printNode(&pg)
856 }
857
858 func (p *printer) printDeclList(list []Decl) {
859 i0 := 0
860 var tok token
861 var group *Group
862 for i, x := range list {
863 if s, g := groupFor(x); g == nil || g != group {
864 if i0 < i {
865 p.printDecl(list[i0:i])
866 p.print(_Semi, newline)
867
868
869 if g != group || s != tok || s == _Func {
870 p.print(newline)
871 }
872 i0 = i
873 }
874 tok, group = s, g
875 }
876 }
877 p.printDecl(list[i0:])
878 }
879
880 func (p *printer) printSignature(sig *FuncType) {
881 p.printParameterList(sig.ParamList, 0)
882 if list := sig.ResultList; list != nil {
883 p.print(blank)
884 if len(list) == 1 && list[0].Name == nil {
885 p.printNode(list[0].Type)
886 } else {
887 p.printParameterList(list, 0)
888 }
889 }
890 }
891
892
893
894
895 func (p *printer) printParameterList(list []*Field, tok token) {
896 open, close := _Lparen, _Rparen
897 if tok != 0 {
898 open, close = _Lbrack, _Rbrack
899 }
900 p.print(open)
901 for i, f := range list {
902 if i > 0 {
903 p.print(_Comma, blank)
904 }
905 if f.Name != nil {
906 p.printNode(f.Name)
907 if i+1 < len(list) {
908 f1 := list[i+1]
909 if f1.Name != nil && f1.Type == f.Type {
910 continue
911 }
912 }
913 p.print(blank)
914 }
915 p.printNode(f.Type)
916 }
917
918
919
920
921 if tok == _Type && len(list) == 1 && combinesWithName(list[0].Type) {
922 p.print(_Comma)
923 }
924 p.print(close)
925 }
926
927
928
929
930
931
932 func combinesWithName(x Expr) bool {
933 switch x := x.(type) {
934 case *Operation:
935 if x.Y == nil {
936
937 return x.Op == Mul && !isTypeElem(x.X)
938 }
939
940 return combinesWithName(x.X) && !isTypeElem(x.Y)
941 case *ParenExpr:
942
943
944
945
946
947
948 return !isTypeElem(x.X)
949 }
950 return false
951 }
952
953 func (p *printer) printStmtList(list []Stmt, braces bool) {
954 for i, x := range list {
955 p.print(x, _Semi)
956 if i+1 < len(list) {
957 p.print(newline)
958 } else if braces {
959
960
961
962 if _, ok := x.(*EmptyStmt); ok {
963 p.print(x, _Semi)
964 }
965 }
966 }
967 }
968
969 func (p *printer) printSwitchBody(list []*CaseClause) {
970 p.print(_Lbrace)
971 if len(list) > 0 {
972 p.print(newline)
973 for i, c := range list {
974 p.printCaseClause(c, i+1 == len(list))
975 p.print(newline)
976 }
977 }
978 p.print(_Rbrace)
979 }
980
981 func (p *printer) printSelectBody(list []*CommClause) {
982 p.print(_Lbrace)
983 if len(list) > 0 {
984 p.print(newline)
985 for i, c := range list {
986 p.printCommClause(c, i+1 == len(list))
987 p.print(newline)
988 }
989 }
990 p.print(_Rbrace)
991 }
992
993 func (p *printer) printCaseClause(c *CaseClause, braces bool) {
994 if c.Cases != nil {
995 p.print(_Case, blank, c.Cases)
996 } else {
997 p.print(_Default)
998 }
999 p.print(_Colon)
1000 if len(c.Body) > 0 {
1001 p.print(newline, indent)
1002 p.printStmtList(c.Body, braces)
1003 p.print(outdent)
1004 }
1005 }
1006
1007 func (p *printer) printCommClause(c *CommClause, braces bool) {
1008 if c.Comm != nil {
1009 p.print(_Case, blank)
1010 p.print(c.Comm)
1011 } else {
1012 p.print(_Default)
1013 }
1014 p.print(_Colon)
1015 if len(c.Body) > 0 {
1016 p.print(newline, indent)
1017 p.printStmtList(c.Body, braces)
1018 p.print(outdent)
1019 }
1020 }
1021
View as plain text