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