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 lineComment(text string) bool {
142 return strings.HasPrefix(text, "//")
143 }
144
145 func (p *printer) addWhitespace(kind ctrlSymbol, text string) {
146 p.pending = append(p.pending, whitespace{p.lastTok, kind })
147 switch kind {
148 case semi:
149 p.lastTok = _Semi
150 case newline:
151 p.lastTok = 0
152
153 }
154 }
155
156 func (p *printer) flush(next token) {
157
158 sawNewline := next == _EOF
159 sawParen := next == _Rparen || next == _Rbrace
160 for i := len(p.pending) - 1; i >= 0; i-- {
161 switch p.pending[i].kind {
162 case semi:
163 k := semi
164 if sawParen {
165 sawParen = false
166 k = none
167 } else if sawNewline && impliesSemi(p.pending[i].last) {
168 sawNewline = false
169 k = none
170 }
171 p.pending[i].kind = k
172 case newline:
173 sawNewline = true
174 case blank, indent, outdent:
175
176
177
178
179
180
181
182
183
184 default:
185 panic("unreachable")
186 }
187 }
188
189
190 prev := none
191 for i := range p.pending {
192 switch p.pending[i].kind {
193 case none:
194
195 case semi:
196 p.writeString(";")
197 p.nlcount = 0
198 prev = semi
199 case blank:
200 if prev != blank {
201
202 p.writeBytes(blankByte)
203 p.nlcount = 0
204 prev = blank
205 }
206 case newline:
207 const maxEmptyLines = 1
208 if p.nlcount <= maxEmptyLines {
209 p.write(newlineByte)
210 p.nlcount++
211 prev = newline
212 }
213 case indent:
214 p.indent++
215 case outdent:
216 p.indent--
217 if p.indent < 0 {
218 panic("negative indentation")
219 }
220
221
222
223
224
225
226
227 default:
228 panic("unreachable")
229 }
230 }
231
232 p.pending = p.pending[:0]
233 }
234
235 func mayCombine(prev token, next byte) (b bool) {
236 return
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 }
253
254 func (p *printer) print(args ...interface{}) {
255 for i := 0; i < len(args); i++ {
256 switch x := args[i].(type) {
257 case nil:
258
259
260 case Node:
261 p.printNode(x)
262
263 case token:
264
265
266 var s string
267 if x == _Name {
268 i++
269 if i >= len(args) {
270 panic("missing string argument after _Name")
271 }
272 s = args[i].(string)
273 } else {
274 s = x.String()
275 }
276
277
278
279 if mayCombine(p.lastTok, s[0]) {
280 panic("adjacent tokens combine without whitespace")
281 }
282
283 if x == _Semi {
284
285 p.addWhitespace(semi, "")
286 } else {
287 p.flush(x)
288 p.writeString(s)
289 p.nlcount = 0
290 p.lastTok = x
291 }
292
293 case Operator:
294 if x != 0 {
295 p.flush(_Operator)
296 p.writeString(x.String())
297 }
298
299 case ctrlSymbol:
300 switch x {
301 case none, semi :
302 panic("unreachable")
303 case newline:
304
305 if !p.linebreaks {
306 x = blank
307 }
308 }
309 p.addWhitespace(x, "")
310
311
312
313
314 default:
315 panic(fmt.Sprintf("unexpected argument %v (%T)", x, x))
316 }
317 }
318 }
319
320 func (p *printer) printNode(n Node) {
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338 p.printRawNode(n)
339
340
341
342
343
344
345
346
347
348
349
350
351 }
352
353 func (p *printer) printRawNode(n Node) {
354 switch n := n.(type) {
355 case nil:
356
357
358
359 case *BadExpr:
360 p.print(_Name, "<bad expr>")
361
362 case *Name:
363 p.print(_Name, n.Value)
364
365 case *BasicLit:
366 p.print(_Name, n.Value)
367
368 case *FuncLit:
369 p.print(n.Type, blank)
370 if n.Body != nil {
371 if p.form == ShortForm {
372 p.print(_Lbrace)
373 if len(n.Body.List) > 0 {
374 p.print(_Name, "…")
375 }
376 p.print(_Rbrace)
377 } else {
378 p.print(n.Body)
379 }
380 }
381
382 case *CompositeLit:
383 if n.Type != nil {
384 p.print(n.Type)
385 }
386 p.print(_Lbrace)
387 if p.form == ShortForm {
388 if len(n.ElemList) > 0 {
389 p.print(_Name, "…")
390 }
391 } else {
392 if n.NKeys > 0 && n.NKeys == len(n.ElemList) {
393 p.printExprLines(n.ElemList)
394 } else {
395 p.printExprList(n.ElemList)
396 }
397 }
398 p.print(_Rbrace)
399
400 case *ParenExpr:
401 p.print(_Lparen, n.X, _Rparen)
402
403 case *SelectorExpr:
404 p.print(n.X, _Dot, n.Sel)
405
406 case *IndexExpr:
407 p.print(n.X, _Lbrack, n.Index, _Rbrack)
408
409 case *SliceExpr:
410 p.print(n.X, _Lbrack)
411 if i := n.Index[0]; i != nil {
412 p.printNode(i)
413 }
414 p.print(_Colon)
415 if j := n.Index[1]; j != nil {
416 p.printNode(j)
417 }
418 if k := n.Index[2]; k != nil {
419 p.print(_Colon, k)
420 }
421 p.print(_Rbrack)
422
423 case *AssertExpr:
424 p.print(n.X, _Dot, _Lparen, n.Type, _Rparen)
425
426 case *TypeSwitchGuard:
427 if n.Lhs != nil {
428 p.print(n.Lhs, blank, _Define, blank)
429 }
430 p.print(n.X, _Dot, _Lparen, _Type, _Rparen)
431
432 case *CallExpr:
433 p.print(n.Fun, _Lparen)
434 p.printExprList(n.ArgList)
435 if n.HasDots {
436 p.print(_DotDotDot)
437 }
438 p.print(_Rparen)
439
440 case *Operation:
441 if n.Y == nil {
442
443 p.print(n.Op)
444
445
446
447 p.print(n.X)
448 } else {
449
450
451
452 p.print(n.X, blank, n.Op, blank, n.Y)
453 }
454
455 case *KeyValueExpr:
456 p.print(n.Key, _Colon, blank, n.Value)
457
458 case *ListExpr:
459 p.printExprList(n.ElemList)
460
461 case *ArrayType:
462 var len interface{} = _DotDotDot
463 if n.Len != nil {
464 len = n.Len
465 }
466 p.print(_Lbrack, len, _Rbrack, n.Elem)
467
468 case *SliceType:
469 p.print(_Lbrack, _Rbrack, n.Elem)
470
471 case *DotsType:
472 p.print(_DotDotDot, n.Elem)
473
474 case *StructType:
475 p.print(_Struct)
476 if len(n.FieldList) > 0 && p.linebreaks {
477 p.print(blank)
478 }
479 p.print(_Lbrace)
480 if len(n.FieldList) > 0 {
481 if p.linebreaks {
482 p.print(newline, indent)
483 p.printFieldList(n.FieldList, n.TagList, _Semi)
484 p.print(outdent, newline)
485 } else {
486 p.printFieldList(n.FieldList, n.TagList, _Semi)
487 }
488 }
489 p.print(_Rbrace)
490
491 case *FuncType:
492 p.print(_Func)
493 p.printSignature(n)
494
495 case *InterfaceType:
496 p.print(_Interface)
497 if p.linebreaks && len(n.MethodList) > 1 {
498 p.print(blank)
499 p.print(_Lbrace)
500 p.print(newline, indent)
501 p.printMethodList(n.MethodList)
502 p.print(outdent, newline)
503 } else {
504 p.print(_Lbrace)
505 p.printMethodList(n.MethodList)
506 }
507 p.print(_Rbrace)
508
509 case *MapType:
510 p.print(_Map, _Lbrack, n.Key, _Rbrack, n.Value)
511
512 case *ChanType:
513 if n.Dir == RecvOnly {
514 p.print(_Arrow)
515 }
516 p.print(_Chan)
517 if n.Dir == SendOnly {
518 p.print(_Arrow)
519 }
520 p.print(blank)
521 if e, _ := n.Elem.(*ChanType); n.Dir == 0 && e != nil && e.Dir == RecvOnly {
522
523 p.print(_Lparen)
524 p.print(n.Elem)
525 p.print(_Rparen)
526 } else {
527 p.print(n.Elem)
528 }
529
530
531 case *DeclStmt:
532 p.printDecl(n.DeclList)
533
534 case *EmptyStmt:
535
536
537 case *LabeledStmt:
538 p.print(outdent, n.Label, _Colon, indent, newline, n.Stmt)
539
540 case *ExprStmt:
541 p.print(n.X)
542
543 case *SendStmt:
544 p.print(n.Chan, blank, _Arrow, blank, n.Value)
545
546 case *AssignStmt:
547 p.print(n.Lhs)
548 if n.Rhs == nil {
549
550
551 p.print(n.Op, n.Op)
552 } else {
553 p.print(blank, n.Op, _Assign, blank)
554 p.print(n.Rhs)
555 }
556
557 case *CallStmt:
558 p.print(n.Tok, blank, n.Call)
559
560 case *ReturnStmt:
561 p.print(_Return)
562 if n.Results != nil {
563 p.print(blank, n.Results)
564 }
565
566 case *BranchStmt:
567 p.print(n.Tok)
568 if n.Label != nil {
569 p.print(blank, n.Label)
570 }
571
572 case *BlockStmt:
573 p.print(_Lbrace)
574 if len(n.List) > 0 {
575 p.print(newline, indent)
576 p.printStmtList(n.List, true)
577 p.print(outdent, newline)
578 }
579 p.print(_Rbrace)
580
581 case *IfStmt:
582 p.print(_If, blank)
583 if n.Init != nil {
584 p.print(n.Init, _Semi, blank)
585 }
586 p.print(n.Cond, blank, n.Then)
587 if n.Else != nil {
588 p.print(blank, _Else, blank, n.Else)
589 }
590
591 case *SwitchStmt:
592 p.print(_Switch, blank)
593 if n.Init != nil {
594 p.print(n.Init, _Semi, blank)
595 }
596 if n.Tag != nil {
597 p.print(n.Tag, blank)
598 }
599 p.printSwitchBody(n.Body)
600
601 case *SelectStmt:
602 p.print(_Select, blank)
603 p.printSelectBody(n.Body)
604
605 case *RangeClause:
606 if n.Lhs != nil {
607 tok := _Assign
608 if n.Def {
609 tok = _Define
610 }
611 p.print(n.Lhs, blank, tok, blank)
612 }
613 p.print(_Range, blank, n.X)
614
615 case *ForStmt:
616 p.print(_For, blank)
617 if n.Init == nil && n.Post == nil {
618 if n.Cond != nil {
619 p.print(n.Cond, blank)
620 }
621 } else {
622 if n.Init != nil {
623 p.print(n.Init)
624
625 if _, ok := n.Init.(*RangeClause); ok {
626 p.print(blank, n.Body)
627 break
628 }
629 }
630 p.print(_Semi, blank)
631 if n.Cond != nil {
632 p.print(n.Cond)
633 }
634 p.print(_Semi, blank)
635 if n.Post != nil {
636 p.print(n.Post, blank)
637 }
638 }
639 p.print(n.Body)
640
641 case *ImportDecl:
642 if n.Group == nil {
643 p.print(_Import, blank)
644 }
645 if n.LocalPkgName != nil {
646 p.print(n.LocalPkgName, blank)
647 }
648 p.print(n.Path)
649
650 case *ConstDecl:
651 if n.Group == nil {
652 p.print(_Const, blank)
653 }
654 p.printNameList(n.NameList)
655 if n.Type != nil {
656 p.print(blank, n.Type)
657 }
658 if n.Values != nil {
659 p.print(blank, _Assign, blank, n.Values)
660 }
661
662 case *TypeDecl:
663 if n.Group == nil {
664 p.print(_Type, blank)
665 }
666 p.print(n.Name)
667 if n.TParamList != nil {
668 p.printParameterList(n.TParamList, _Type)
669 }
670 p.print(blank)
671 if n.Alias {
672 p.print(_Assign, blank)
673 }
674 p.print(n.Type)
675
676 case *VarDecl:
677 if n.Group == nil {
678 p.print(_Var, blank)
679 }
680 p.printNameList(n.NameList)
681 if n.Type != nil {
682 p.print(blank, n.Type)
683 }
684 if n.Values != nil {
685 p.print(blank, _Assign, blank, n.Values)
686 }
687
688 case *FuncDecl:
689 p.print(_Func, blank)
690 if r := n.Recv; r != nil {
691 p.print(_Lparen)
692 if r.Name != nil {
693 p.print(r.Name, blank)
694 }
695 p.printNode(r.Type)
696 p.print(_Rparen, blank)
697 }
698 p.print(n.Name)
699 if n.TParamList != nil {
700 p.printParameterList(n.TParamList, _Func)
701 }
702 p.printSignature(n.Type)
703 if n.Body != nil {
704 p.print(blank, n.Body)
705 }
706
707 case *printGroup:
708 p.print(n.Tok, blank, _Lparen)
709 if len(n.Decls) > 0 {
710 p.print(newline, indent)
711 for _, d := range n.Decls {
712 p.printNode(d)
713 p.print(_Semi, newline)
714 }
715 p.print(outdent)
716 }
717 p.print(_Rparen)
718
719
720 case *File:
721 p.print(_Package, blank, n.PkgName)
722 if len(n.DeclList) > 0 {
723 p.print(_Semi, newline, newline)
724 p.printDeclList(n.DeclList)
725 }
726
727 default:
728 panic(fmt.Sprintf("syntax.Iterate: unexpected node type %T", n))
729 }
730 }
731
732 func (p *printer) printFields(fields []*Field, tags []*BasicLit, i, j int) {
733 if i+1 == j && fields[i].Name == nil {
734
735 p.printNode(fields[i].Type)
736 } else {
737 for k, f := range fields[i:j] {
738 if k > 0 {
739 p.print(_Comma, blank)
740 }
741 p.printNode(f.Name)
742 }
743 p.print(blank)
744 p.printNode(fields[i].Type)
745 }
746 if i < len(tags) && tags[i] != nil {
747 p.print(blank)
748 p.printNode(tags[i])
749 }
750 }
751
752 func (p *printer) printFieldList(fields []*Field, tags []*BasicLit, sep token) {
753 i0 := 0
754 var typ Expr
755 for i, f := range fields {
756 if f.Name == nil || f.Type != typ {
757 if i0 < i {
758 p.printFields(fields, tags, i0, i)
759 p.print(sep, newline)
760 i0 = i
761 }
762 typ = f.Type
763 }
764 }
765 p.printFields(fields, tags, i0, len(fields))
766 }
767
768 func (p *printer) printMethodList(methods []*Field) {
769 for i, m := range methods {
770 if i > 0 {
771 p.print(_Semi, newline)
772 }
773 if m.Name != nil {
774 p.printNode(m.Name)
775 p.printSignature(m.Type.(*FuncType))
776 } else {
777 p.printNode(m.Type)
778 }
779 }
780 }
781
782 func (p *printer) printNameList(list []*Name) {
783 for i, x := range list {
784 if i > 0 {
785 p.print(_Comma, blank)
786 }
787 p.printNode(x)
788 }
789 }
790
791 func (p *printer) printExprList(list []Expr) {
792 for i, x := range list {
793 if i > 0 {
794 p.print(_Comma, blank)
795 }
796 p.printNode(x)
797 }
798 }
799
800 func (p *printer) printExprLines(list []Expr) {
801 if len(list) > 0 {
802 p.print(newline, indent)
803 for _, x := range list {
804 p.print(x, _Comma, newline)
805 }
806 p.print(outdent)
807 }
808 }
809
810 func groupFor(d Decl) (token, *Group) {
811 switch d := d.(type) {
812 case *ImportDecl:
813 return _Import, d.Group
814 case *ConstDecl:
815 return _Const, d.Group
816 case *TypeDecl:
817 return _Type, d.Group
818 case *VarDecl:
819 return _Var, d.Group
820 case *FuncDecl:
821 return _Func, nil
822 default:
823 panic("unreachable")
824 }
825 }
826
827 type printGroup struct {
828 node
829 Tok token
830 Decls []Decl
831 }
832
833 func (p *printer) printDecl(list []Decl) {
834 tok, group := groupFor(list[0])
835
836 if group == nil {
837 if len(list) != 1 {
838 panic("unreachable")
839 }
840 p.printNode(list[0])
841 return
842 }
843
844
845
846
847
848
849
850
851
852
853
854
855 var pg printGroup
856
857 pg.Tok = tok
858 pg.Decls = list
859 p.printNode(&pg)
860 }
861
862 func (p *printer) printDeclList(list []Decl) {
863 i0 := 0
864 var tok token
865 var group *Group
866 for i, x := range list {
867 if s, g := groupFor(x); g == nil || g != group {
868 if i0 < i {
869 p.printDecl(list[i0:i])
870 p.print(_Semi, newline)
871
872
873 if g != group || s != tok || s == _Func {
874 p.print(newline)
875 }
876 i0 = i
877 }
878 tok, group = s, g
879 }
880 }
881 p.printDecl(list[i0:])
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(Unparen(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 panic("unexpected parenthesized expression")
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