github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/ast/printer/source_printer.go (about) 1 package printer 2 3 import ( 4 "io" 5 "strings" 6 "text/tabwriter" 7 8 "github.com/hirochachacha/plua/compiler/ast" 9 "github.com/hirochachacha/plua/compiler/token" 10 "github.com/hirochachacha/plua/internal/strconv" 11 "github.com/hirochachacha/plua/position" 12 ) 13 14 const ( 15 indent = " " 16 ) 17 18 type mode uint 19 20 const ( 21 noBlank mode = 1 << iota 22 escape 23 noParen 24 compact 25 insertSemi 26 ) 27 28 type printer struct { 29 w *tabwriter.Writer 30 depth int // indent depth 31 doIndent bool 32 formfeed bool 33 stmtEnd bool 34 lastPos position.Position 35 commentPos position.Position 36 cindex int 37 comments []*ast.CommentGroup 38 comment *ast.CommentGroup 39 err error 40 } 41 42 var initPos = position.Position{Line: 1} 43 44 func newPrinter(w io.Writer) *printer { 45 return &printer{ 46 w: tabwriter.NewWriter(w, 2, 2, 1, ' ', tabwriter.DiscardEmptyColumns|tabwriter.StripEscape), 47 lastPos: initPos, 48 } 49 } 50 51 // Nodes 52 53 func (p *printer) printNode(node ast.Node) { 54 switch node := node.(type) { 55 case *ast.BadExpr: 56 p.print(node.Pos(), "BadExpr", 0) 57 case *ast.Name: 58 p.printName(node, 0) 59 case *ast.Vararg: 60 p.printVararg(node, 0) 61 case *ast.BasicLit: 62 p.printBasicLit(node, 0) 63 case *ast.FuncLit: 64 p.printFuncLit(node, 0) 65 case *ast.TableLit: 66 p.printTableLit(node, 0) 67 case *ast.ParenExpr: 68 p.printParenExpr(node, 0) 69 case *ast.SelectorExpr: 70 p.printSelectorExpr(node, 0) 71 case *ast.IndexExpr: 72 p.printIndexExpr(node, 0) 73 case *ast.CallExpr: 74 p.printCallExpr(node, 0) 75 case *ast.UnaryExpr: 76 p.printUnaryExpr(node, 0) 77 case *ast.BinaryExpr: 78 p.printBinaryExpr(node, token.HighestPrec, 0) 79 case *ast.KeyValueExpr: 80 p.printKeyValueExpr(node, 0) 81 case *ast.BadStmt: 82 p.print(node.Pos(), "BadStmt", 0) 83 case *ast.EmptyStmt: 84 // skip this 85 case *ast.LocalAssignStmt: 86 p.printLocalAssignStmt(node) 87 case *ast.LocalFuncStmt: 88 p.printLocalFuncStmt(node) 89 case *ast.FuncStmt: 90 p.printFuncStmt(node) 91 case *ast.LabelStmt: 92 p.printLabelStmt(node) 93 case *ast.ExprStmt: 94 p.printExprStmt(node) 95 case *ast.AssignStmt: 96 p.printAssignStmt(node) 97 case *ast.GotoStmt: 98 p.printGotoStmt(node) 99 case *ast.BreakStmt: 100 p.printBreakStmt(node) 101 case *ast.IfStmt: 102 p.printIfStmt(node) 103 case *ast.DoStmt: 104 p.printDoStmt(node) 105 case *ast.WhileStmt: 106 p.printWhileStmt(node) 107 case *ast.RepeatStmt: 108 p.printRepeatStmt(node) 109 case *ast.ReturnStmt: 110 p.printReturnStmt(node) 111 case *ast.ForStmt: 112 p.printForStmt(node) 113 case *ast.ForEachStmt: 114 p.printForEachStmt(node) 115 case *ast.File: 116 p.printFile(node) 117 case *ast.Block: 118 p.printBlock(node) 119 case *ast.FuncBody: 120 p.printFuncBody(node) 121 case *ast.Comment: 122 case *ast.CommentGroup: 123 case *ast.ParamList: 124 p.printParams(node) 125 126 default: 127 panic("unreachable") 128 } 129 } 130 131 // Statements 132 133 func (p *printer) printStmt(stmt ast.Stmt) { 134 switch stmt := stmt.(type) { 135 case *ast.BadStmt: 136 p.print(stmt.Pos(), "BadStmt", 0) 137 case *ast.EmptyStmt: 138 // skip this 139 case *ast.LocalAssignStmt: 140 p.printLocalAssignStmt(stmt) 141 case *ast.LocalFuncStmt: 142 p.printLocalFuncStmt(stmt) 143 case *ast.FuncStmt: 144 p.printFuncStmt(stmt) 145 case *ast.LabelStmt: 146 p.printLabelStmt(stmt) 147 case *ast.ExprStmt: 148 p.printExprStmt(stmt) 149 case *ast.AssignStmt: 150 p.printAssignStmt(stmt) 151 case *ast.GotoStmt: 152 p.printGotoStmt(stmt) 153 case *ast.BreakStmt: 154 p.printBreakStmt(stmt) 155 case *ast.IfStmt: 156 p.printIfStmt(stmt) 157 case *ast.DoStmt: 158 p.printDoStmt(stmt) 159 case *ast.WhileStmt: 160 p.printWhileStmt(stmt) 161 case *ast.RepeatStmt: 162 p.printRepeatStmt(stmt) 163 case *ast.ReturnStmt: 164 p.printReturnStmt(stmt) 165 case *ast.ForStmt: 166 p.printForStmt(stmt) 167 case *ast.ForEachStmt: 168 p.printForEachStmt(stmt) 169 default: 170 panic("unreachable") 171 } 172 173 p.stmtEnd = true 174 } 175 176 func (p *printer) printLocalAssignStmt(stmt *ast.LocalAssignStmt) { 177 p.print(stmt.Local, "local", insertSemi) 178 p.printNames(stmt.LHS, 0) 179 if stmt.Equal.IsValid() { 180 p.print(stmt.Equal, "=", 0) 181 p.indentWith(stmt.Equal, stmt.End(), func() { 182 p.printExprs(stmt.RHS, noParen) 183 }) 184 } 185 } 186 187 func (p *printer) printLocalFuncStmt(stmt *ast.LocalFuncStmt) { 188 p.print(stmt.Local, "local", insertSemi) 189 p.print(stmt.Func, "function", 0) 190 p.printName(stmt.Name, 0) 191 p.printFuncBody(stmt.Body) 192 p.print(stmt.EndPos, "end", 0) 193 } 194 195 func (p *printer) printFuncStmt(stmt *ast.FuncStmt) { 196 p.print(stmt.Func, "function", insertSemi) 197 if len(stmt.PathList) > 0 { 198 if len(stmt.PathList) == 1 { 199 path := stmt.PathList[0] 200 p.print(path.Pos(), path.Name, 0) 201 } else { 202 path := stmt.PathList[0] 203 p.print(path.Pos(), path.Name+".", 0) 204 for _, path := range stmt.PathList[1 : len(stmt.PathList)-1] { 205 p.print(path.Pos(), path.Name+".", noBlank) 206 } 207 path = stmt.PathList[len(stmt.PathList)-1] 208 p.print(path.Pos(), path.Name, noBlank) 209 } 210 p.print(stmt.AccessPos, stmt.AccessTok.String(), noBlank) 211 p.printName(stmt.Name, noBlank) 212 } else { 213 p.printName(stmt.Name, 0) 214 } 215 p.printFuncBody(stmt.Body) 216 p.print(stmt.EndPos, "end", 0) 217 } 218 219 func (p *printer) printLabelStmt(stmt *ast.LabelStmt) { 220 p.print(stmt.Label, "::", insertSemi) 221 p.print(stmt.Name.Pos(), stmt.Name.Name, noBlank) 222 p.print(stmt.EndLabel, "::", noBlank) 223 } 224 225 func (p *printer) printExprStmt(stmt *ast.ExprStmt) { 226 p.printCallExpr(stmt.X, insertSemi) 227 } 228 229 func (p *printer) printAssignStmt(stmt *ast.AssignStmt) { 230 p.printExprs(stmt.LHS, noParen|insertSemi) 231 p.print(stmt.Equal, "=", 0) 232 p.indentWith(stmt.Equal, stmt.End(), func() { 233 p.printExprs(stmt.RHS, noParen) 234 }) 235 } 236 237 func (p *printer) printGotoStmt(stmt *ast.GotoStmt) { 238 p.print(stmt.Goto, "goto", insertSemi) 239 p.printName(stmt.Label, 0) 240 } 241 242 func (p *printer) printBreakStmt(stmt *ast.BreakStmt) { 243 p.print(stmt.Break, "break", insertSemi) 244 } 245 246 func (p *printer) printIfStmt(stmt *ast.IfStmt) { 247 p.print(stmt.If, "if", insertSemi) 248 p.printExpr(stmt.Cond, noParen) 249 p.print(stmt.Then, "then", 0) 250 p.printBlock(stmt.Body) 251 for _, e := range stmt.ElseIfList { 252 p.print(e.If, "elseif", 0) 253 p.printExpr(e.Cond, noParen) 254 p.print(e.Then, "then", 0) 255 p.printBlock(e.Body) 256 } 257 if stmt.ElseBody != nil { 258 p.print(stmt.Else, "else", 0) 259 p.printBlock(stmt.ElseBody) 260 } 261 p.print(stmt.EndPos, "end", 0) 262 } 263 264 func (p *printer) printDoStmt(stmt *ast.DoStmt) { 265 p.print(stmt.Do, "do", insertSemi) 266 p.printBlock(stmt.Body) 267 p.print(stmt.EndPos, "end", 0) 268 } 269 270 func (p *printer) printWhileStmt(stmt *ast.WhileStmt) { 271 p.print(stmt.While, "while", insertSemi) 272 p.printExpr(stmt.Cond, noParen) 273 p.print(stmt.Do, "do", 0) 274 p.printBlock(stmt.Body) 275 p.print(stmt.EndPos, "end", 0) 276 } 277 278 func (p *printer) printRepeatStmt(stmt *ast.RepeatStmt) { 279 p.print(stmt.Repeat, "repeat", insertSemi) 280 p.printBlock(stmt.Body) 281 p.print(stmt.Until, "until", 0) 282 p.printExpr(stmt.Cond, noParen) 283 } 284 285 func (p *printer) printReturnStmt(stmt *ast.ReturnStmt) { 286 p.print(stmt.Return, "return", insertSemi) 287 p.printExprs(stmt.Results, noParen) 288 } 289 290 func (p *printer) printForStmt(stmt *ast.ForStmt) { 291 p.print(stmt.For, "for", insertSemi) 292 p.printName(stmt.Name, 0) 293 p.print(stmt.Equal, "=", 0) 294 p.printExpr(stmt.Start, noParen) 295 p.print(p.lastPos, ",", noBlank) 296 if stmt.Step != nil { 297 p.printExpr(stmt.Finish, noParen) 298 p.print(p.lastPos, ",", noBlank) 299 p.printExpr(stmt.Step, noParen) 300 } else { 301 p.printExpr(stmt.Finish, noParen) 302 } 303 p.print(stmt.Do, "do", 0) 304 p.printBlock(stmt.Body) 305 p.print(stmt.EndPos, "end", 0) 306 } 307 308 func (p *printer) printForEachStmt(stmt *ast.ForEachStmt) { 309 p.print(stmt.For, "for", insertSemi) 310 p.printNames(stmt.Names, 0) 311 p.print(stmt.In, "in", 0) 312 p.printExprs(stmt.Exprs, noParen) 313 p.print(stmt.Do, "do", 0) 314 p.printBlock(stmt.Body) 315 p.print(stmt.EndPos, "end", 0) 316 } 317 318 // Expression 319 320 func (p *printer) printExpr(expr ast.Expr, mode mode) { 321 if mode&noParen != 0 { 322 for { // ((expr)) => expr 323 paren, ok := expr.(*ast.ParenExpr) 324 if !ok { 325 break 326 } 327 expr = paren.X 328 } 329 mode &^= noParen 330 } 331 332 switch expr := expr.(type) { 333 case *ast.BadExpr: 334 p.print(expr.Pos(), "BadExpr", mode) 335 case *ast.Name: 336 p.printName(expr, mode) 337 case *ast.Vararg: 338 p.printVararg(expr, mode) 339 case *ast.BasicLit: 340 p.printBasicLit(expr, mode) 341 case *ast.FuncLit: 342 p.printFuncLit(expr, mode) 343 case *ast.TableLit: 344 p.printTableLit(expr, mode) 345 case *ast.ParenExpr: 346 p.printParenExpr(expr, mode) 347 case *ast.SelectorExpr: 348 p.printSelectorExpr(expr, mode) 349 case *ast.IndexExpr: 350 p.printIndexExpr(expr, mode) 351 case *ast.CallExpr: 352 p.printCallExpr(expr, mode) 353 case *ast.UnaryExpr: 354 p.printUnaryExpr(expr, mode) 355 case *ast.BinaryExpr: 356 p.printBinaryExpr(expr, token.HighestPrec, mode) 357 case *ast.KeyValueExpr: 358 p.printKeyValueExpr(expr, mode) 359 default: 360 panic("unreachable") 361 } 362 } 363 364 func (p *printer) printName(expr *ast.Name, mode mode) { 365 p.print(expr.Pos(), expr.Name, mode) 366 } 367 368 func (p *printer) printVararg(expr *ast.Vararg, mode mode) { 369 p.print(expr.Ellipsis, "...", mode) 370 } 371 372 func (p *printer) printBasicLit(expr *ast.BasicLit, mode mode) { 373 if expr.Token.Type == token.STRING { 374 p.print(expr.Token.Pos, expr.Token.Lit, mode|escape) 375 } else { 376 p.print(expr.Token.Pos, expr.Token.Lit, mode) 377 } 378 } 379 380 func (p *printer) printFuncLit(expr *ast.FuncLit, mode mode) { 381 p.print(expr.Func, "function", mode) 382 p.printFuncBody(expr.Body) 383 p.print(expr.EndPos, "end", 0) 384 } 385 386 func (p *printer) printTableLit(expr *ast.TableLit, mode mode) { 387 p.print(expr.Lbrace, "{", mode) 388 p.indentWith(expr.Lbrace, expr.Rbrace, func() { 389 p.printExprs(expr.Fields, noBlank|noParen) 390 if len(expr.Fields) > 0 { 391 if expr.Rbrace.Line-p.lastPos.Line > 0 { 392 p.writeByte(',') 393 } 394 } 395 }) 396 p.print(expr.Rbrace, "}", noBlank) 397 } 398 399 func (p *printer) printParenExpr(expr *ast.ParenExpr, mode mode) { 400 p.print(expr.Lparen, "(", mode) 401 p.indentWith(expr.Lparen, expr.Rparen, func() { 402 p.printExpr(expr.X, noBlank|noParen|compact) 403 }) 404 p.print(expr.Rparen, ")", noBlank) 405 } 406 407 func (p *printer) printSelectorExpr(expr *ast.SelectorExpr, mode mode) { 408 p.printExpr(expr.X, mode) 409 p.print(expr.Period, ".", noBlank) 410 p.printName(expr.Sel, noBlank) 411 } 412 413 func (p *printer) printIndexExpr(expr *ast.IndexExpr, mode mode) { 414 p.printExpr(expr.X, mode) 415 p.print(expr.Lbrack, "[", noBlank) 416 p.indentWith(expr.Lbrack, expr.Rbrack, func() { 417 p.printExpr(expr.Index, noBlank|noParen|compact) 418 }) 419 p.print(expr.Rbrack, "]", noBlank) 420 } 421 422 func (p *printer) printCallExpr(expr *ast.CallExpr, mode mode) { 423 p.printExpr(expr.X, mode) 424 if expr.Colon != position.NoPos { 425 p.print(expr.Colon, ":", noBlank) 426 p.printName(expr.Name, noBlank) 427 } 428 if expr.Lparen != position.NoPos { 429 p.print(expr.Lparen, "(", noBlank) 430 p.indentWith(expr.Lparen, expr.Rparen, func() { 431 p.printExprs(expr.Args, noBlank|noParen) 432 }) 433 p.print(expr.Rparen, ")", noBlank) 434 } else { 435 p.printExprs(expr.Args, noParen) 436 } 437 } 438 439 func (p *printer) printUnaryExpr(expr *ast.UnaryExpr, mode mode) { 440 p.print(expr.OpPos, expr.Op.String(), mode) 441 switch x := expr.X.(type) { 442 case *ast.UnaryExpr: 443 // - - 6 => -(-6) 444 // not not true => not (not true) 445 if expr.Op != token.NOT { 446 p.print(x.Pos(), "(", noBlank) 447 } else { 448 p.print(x.Pos(), "(", 0) 449 } 450 p.printUnaryExpr(x, noBlank) 451 p.print(x.End(), ")", noBlank) 452 case *ast.BinaryExpr: 453 if expr.Op != token.NOT { 454 p.printBinaryExpr(x, token.HighestPrec, noBlank) 455 } else { 456 p.printBinaryExpr(x, token.HighestPrec, 0) 457 } 458 default: 459 if expr.Op != token.NOT { 460 p.printExpr(expr.X, noBlank) 461 } else { 462 p.printExpr(expr.X, 0) 463 } 464 } 465 } 466 467 func (p *printer) printBinaryExpr(expr *ast.BinaryExpr, prec1 int, mode mode) { 468 prec, _ := expr.Op.Precedence() 469 470 if (mode&compact != 0 || prec > prec1) && prec > 3 { // should cutoff? 471 // (1 + 8 * 9) => (1+8*9) 472 // 1 + 2 * 3 +4/5 +6 ^ 7 +8 => 1 + 2*3 + 4/5 + 6^7 + 8 473 474 if x, ok := expr.X.(*ast.BinaryExpr); ok { 475 p.printBinaryExpr(x, prec1, mode) 476 } else { 477 if x, ok := expr.X.(*ast.BasicLit); ok && (x.Token.Type == token.INT || x.Token.Type == token.FLOAT) && expr.Op == token.CONCAT { 478 // 2 .. 3 > "22" => "2"..3 > "22" 479 p.print(x.Token.Pos, strconv.Quote(x.Token.Lit), mode) 480 } else { 481 p.printExpr(expr.X, mode) 482 } 483 } 484 485 p.print(expr.OpPos, expr.Op.String(), noBlank) 486 487 switch y := expr.Y.(type) { 488 case *ast.UnaryExpr: 489 switch expr.Op.String() + y.Op.String() { 490 case "--", "~~": 491 // 1 - - 2 => 1-(-2) 492 // 1 ~ ~ 2 => 1~(~2) 493 p.print(y.Pos(), "(", noBlank) 494 p.printUnaryExpr(y, noBlank) 495 p.print(y.End(), ")", noBlank) 496 default: 497 p.printUnaryExpr(y, noBlank) 498 } 499 case *ast.BinaryExpr: 500 p.printBinaryExpr(y, prec1, noBlank) 501 default: 502 p.printExpr(expr.Y, noBlank) 503 } 504 } else { 505 if x, ok := expr.X.(*ast.BinaryExpr); ok { 506 p.printBinaryExpr(x, prec, mode) 507 } else { 508 p.printExpr(expr.X, mode) 509 } 510 511 p.print(expr.OpPos, expr.Op.String(), 0) 512 513 switch y := expr.Y.(type) { 514 case *ast.UnaryExpr: 515 switch expr.Op.String() + y.Op.String() { 516 case "--", "~~": 517 // 1 - - 2 => 1 - (-2) 518 // 1 ~ ~ 2 => 1 ~ (~2) 519 p.print(y.Pos(), "(", 0) 520 p.printUnaryExpr(y, noBlank) 521 p.print(y.End(), ")", noBlank) 522 default: 523 p.printUnaryExpr(y, 0) 524 } 525 case *ast.BinaryExpr: 526 p.printBinaryExpr(y, prec, 0) 527 default: 528 p.printExpr(expr.Y, 0) 529 } 530 } 531 } 532 533 func (p *printer) printKeyValueExpr(expr *ast.KeyValueExpr, mode mode) { 534 if expr.Lbrack != position.NoPos { 535 p.print(expr.Lbrack, "[", mode) 536 p.indentWith(expr.Lbrack, expr.Rbrack, func() { 537 p.printExpr(expr.Key, noBlank|noParen|compact) 538 }) 539 p.print(expr.Rbrack, "]", noBlank) 540 p.print(expr.Equal, "=", 0) 541 p.indentWith(expr.Equal, expr.End(), func() { 542 p.printExpr(expr.Value, noParen) 543 }) 544 } else { 545 p.printExpr(expr.Key, mode) 546 p.print(expr.Equal, "=", 0) 547 p.indentWith(expr.Equal, expr.End(), func() { 548 p.printExpr(expr.Value, noParen) 549 }) 550 } 551 } 552 553 func (p *printer) nextComment() { 554 if p.cindex == len(p.comments) { 555 p.comment = nil 556 p.commentPos = position.Position{Line: 1 << 30} 557 } else { 558 p.comment = p.comments[p.cindex] 559 p.commentPos = p.comment.Pos() 560 p.cindex++ 561 } 562 } 563 564 // Other 565 566 func replaceEscape(s string) string { 567 if i := strings.IndexByte(s, tabwriter.Escape); i != -1 { 568 bs := make([]byte, len(s)) 569 for i := range bs { 570 c := s[i] 571 if c == tabwriter.Escape { 572 bs[i] = 0x00 573 } else { 574 bs[i] = s[i] 575 } 576 } 577 return string(bs) 578 } 579 return s 580 } 581 582 func (p *printer) printFile(file *ast.File) { 583 if file.Shebang != "" { 584 p.writeByte(tabwriter.Escape) 585 p.writeString(replaceEscape(file.Shebang)) 586 p.writeByte(tabwriter.Escape) 587 } 588 589 p.comments = file.Comments 590 591 p.nextComment() 592 593 for _, stmt := range file.Chunk { 594 p.printStmt(stmt) 595 } 596 597 p.insertComment(file.End()) 598 } 599 600 func (p *printer) printFuncBody(body *ast.FuncBody) { 601 p.printParams(body.Params) 602 p.printBlock(body.Body) 603 } 604 605 func (p *printer) printParams(params *ast.ParamList) { 606 p.print(params.Lparen, "(", noBlank) 607 p.indentWith(params.Lparen, params.Rparen, func() { 608 p.printNames(params.List, noBlank) 609 if params.Ellipsis != position.NoPos { 610 if len(params.List) > 0 { 611 p.print(p.lastPos, ",", noBlank) 612 } 613 p.print(params.Ellipsis, "...", 0) 614 } 615 }) 616 p.print(params.Rparen, ")", noBlank) 617 } 618 619 func (p *printer) printBlock(block *ast.Block) { 620 p.indentWith(block.Opening, block.Closing, func() { 621 for _, stmt := range block.List { 622 p.printStmt(stmt) 623 } 624 }) 625 } 626 627 func (p *printer) printNames(names []*ast.Name, mode mode) { 628 if len(names) == 0 { 629 return 630 } 631 p.printName(names[0], mode) 632 for _, name := range names[1:] { 633 p.print(p.lastPos, ",", noBlank) 634 p.printName(name, 0) 635 } 636 } 637 638 func (p *printer) printExprs(exprs []ast.Expr, mode mode) { 639 switch len(exprs) { 640 case 0: 641 return 642 case 1: 643 p.printExpr(exprs[0], mode) 644 default: 645 p.printExpr(exprs[0], mode|compact) 646 for _, expr := range exprs[1:] { 647 p.print(p.lastPos, ",", noBlank) 648 p.printExpr(expr, noParen|compact) 649 } 650 } 651 } 652 653 func (p *printer) indentWith(pos, end position.Position, fn func()) { 654 if pos.Line == end.Line { 655 fn() 656 } else { 657 p.insertComment(pos) 658 659 p.formfeed = true 660 p.doIndent = true 661 662 depth := p.depth 663 664 fn() 665 666 p.insertComment(end) 667 668 p.depth = depth 669 670 p.doIndent = false 671 p.formfeed = true 672 } 673 } 674 675 func (p *printer) insertComment(pos position.Position) { 676 for p.commentPos.LessThan(pos) { 677 for i, c := range p.comment.List { 678 d := c.Pos().Line - p.lastPos.Line 679 680 switch { 681 case d == 0: 682 if p.lastPos != initPos { 683 p.writeByte('\t') 684 } 685 case d > 0: 686 if i == 0 { 687 p.writeByte('\f') 688 } else { 689 if p.formfeed { 690 p.writeByte('\f') 691 } else { 692 p.writeByte('\n') 693 } 694 } 695 if d > 1 { 696 p.writeByte('\f') 697 } 698 for i := 0; i < p.depth; i++ { 699 p.writeString(indent) 700 } 701 p.formfeed = false 702 default: 703 panic("unexpected") 704 } 705 706 p.writeByte(tabwriter.Escape) 707 text := replaceEscape(strings.TrimRight(c.Text, "\t\n\v\f\r ")) 708 for { 709 i := strings.IndexByte(text, '\n') 710 if i == -1 { 711 p.writeString(text) 712 713 break 714 } 715 716 p.writeString(trimRightCR(text[:i])) 717 p.writeByte('\n') 718 719 text = text[i+1:] 720 } 721 p.writeByte(tabwriter.Escape) 722 723 p.lastPos = c.End() 724 } 725 726 p.nextComment() 727 } 728 } 729 730 func (p *printer) print(pos position.Position, s string, mode mode) { 731 if p.doIndent { 732 if pos.Line-p.lastPos.Line > 0 { 733 p.depth++ 734 } 735 736 p.doIndent = false 737 } 738 739 p.insertComment(pos) 740 741 d := pos.Line - p.lastPos.Line 742 743 switch { 744 case d == 0: 745 if mode&noBlank == 0 { 746 if p.lastPos != initPos { 747 if p.stmtEnd && mode&insertSemi != 0 { 748 p.writeByte(';') 749 } 750 p.writeByte(' ') 751 } 752 } 753 case d > 0: 754 if p.formfeed { 755 p.writeByte('\f') 756 } else { 757 p.writeByte('\n') 758 } 759 if d > 1 { 760 p.writeByte('\f') 761 } 762 for i := 0; i < p.depth; i++ { 763 p.writeString(indent) 764 } 765 p.formfeed = false 766 default: 767 panic("unexpected") 768 } 769 770 if mode&escape != 0 { 771 p.writeByte(tabwriter.Escape) 772 p.writeString(strconv.Escape(s)) 773 p.writeByte(tabwriter.Escape) 774 } else { 775 p.writeString(s) 776 } 777 778 p.lastPos = pos.Offset(s) 779 780 p.stmtEnd = false 781 } 782 783 func (p *printer) writeByte(c byte) { 784 if p.err != nil { 785 return 786 } 787 _, p.err = p.w.Write([]byte{c}) 788 } 789 790 func (p *printer) writeString(s string) { 791 if p.err != nil { 792 return 793 } 794 _, p.err = p.w.Write([]byte(s)) 795 } 796 797 func trimRightCR(s string) string { 798 if len(s) > 0 && s[len(s)-1] == '\r' { 799 s = s[:len(s)-1] 800 } 801 return s 802 }