diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go index 2451116fdb..3e8f12100b 100644 --- a/src/pkg/go/printer/nodes.go +++ b/src/pkg/go/printer/nodes.go @@ -543,7 +543,7 @@ func walkBinary(e *ast.BinaryExpr) (has5, has6 bool, maxProblem int) { case *ast.UnaryExpr: switch e.Op.String() + r.Op.String() { - case "/*": + case "/*", "&&", "&^": maxProblem = 6 case "++", "--": if maxProblem < 5 { @@ -612,11 +612,14 @@ func reduceDepth(depth int) int { // 1) If there is a binary operator with a right side unary operand // that would clash without a space, the cutoff must be (in order): // -// &^ 7 // /* 7 +// && 7 +// &^ 7 // ++ 6 // -- 6 // +// (Comparison operators always have spaces around them.) +// // 2) If there is a mix of level 6 and level 5 operators, then the cutoff // is 6 (use spaces to distinguish precedence) in Normal mode // and 5 (never use spaces) in Compact mode. diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index b985f6ed3e..cdc8cf518d 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -746,6 +746,26 @@ func (p *printer) writeWhitespace(n int) { // ---------------------------------------------------------------------------- // Printing interface + +func mayCombine(prev token.Token, next byte) (b bool) { + switch prev { + case token.INT: + b = next == '.' // 1. + case token.ADD: + b = next == '+' // ++ + case token.SUB: + b = next == '-' // -- + case token.QUO: + b = next == '*' // /* + case token.LSS: + b = next == '-' || next == '<' // <- or << + case token.AND: + b = next == '&' || next == '^' // && or &^ + } + return +} + + // print prints a list of "items" (roughly corresponding to syntactic // tokens, but also including whitespace and formatting information). // It is the only print function that should be called directly from @@ -803,8 +823,13 @@ func (p *printer) print(args ...interface{}) { tok = x.Kind case token.Token: s := x.String() - if p.lastTok == token.INT && s[0] == '.' { - // separate int with blank from '.' so it doesn't become a float + if mayCombine(p.lastTok, s[0]) { + // the previous and the current token must be + // separated by a blank otherwise they combine + // into a different incorrect token sequence + // (except for token.INT followed by a '.' this + // should never happen because it is taken care + // of via binary expression formatting) if len(p.buffer) != 0 { p.internalError("whitespace buffer not empty") } diff --git a/src/pkg/go/printer/testdata/expressions.golden b/src/pkg/go/printer/testdata/expressions.golden index 02bae49b48..b5dac45a7b 100644 --- a/src/pkg/go/printer/testdata/expressions.golden +++ b/src/pkg/go/printer/testdata/expressions.golden @@ -194,6 +194,17 @@ func f(x int, args ...int) { _ = .42.x _ = 42e0.x _ = 42e0.x + + // a blank must remain between the binary operator and the 2nd operand + _ = x / *y + _ = x < -1 + _ = x < <-1 + _ = x + +1 + _ = x - -1 + _ = x & &x + _ = x & ^x + + _ = f(x / *y, x < -1, x < <-1, x + +1, x - -1, x & &x, x & ^x) } diff --git a/src/pkg/go/printer/testdata/expressions.input b/src/pkg/go/printer/testdata/expressions.input index 7d5889b064..3eb1629317 100644 --- a/src/pkg/go/printer/testdata/expressions.input +++ b/src/pkg/go/printer/testdata/expressions.input @@ -194,6 +194,17 @@ func f(x int, args ...int) { _ = .42.x _ = 42e0 .x _ = 42e0.x + + // a blank must remain between the binary operator and the 2nd operand + _ = x/ *y + _ = x< -1 + _ = x< <-1 + _ = x+ +1 + _ = x- -1 + _ = x& &x + _ = x& ^x + + _ = f(x/ *y, x< -1, x< <-1, x+ +1, x- -1, x& &x, x& ^x) } diff --git a/src/pkg/go/printer/testdata/expressions.raw b/src/pkg/go/printer/testdata/expressions.raw index 9e83892e87..e571d08284 100644 --- a/src/pkg/go/printer/testdata/expressions.raw +++ b/src/pkg/go/printer/testdata/expressions.raw @@ -194,6 +194,17 @@ func f(x int, args ...int) { _ = .42.x _ = 42e0.x _ = 42e0.x + + // a blank must remain between the binary operator and the 2nd operand + _ = x / *y + _ = x < -1 + _ = x < <-1 + _ = x + +1 + _ = x - -1 + _ = x & &x + _ = x & ^x + + _ = f(x / *y, x < -1, x < <-1, x + +1, x - -1, x & &x, x & ^x) }