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