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