]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: use correct precedence when parsing range clauses
authorRobert Griesemer <gri@golang.org>
Tue, 16 Aug 2011 22:19:23 +0000 (15:19 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 16 Aug 2011 22:19:23 +0000 (15:19 -0700)
Fixes #2156.

R=rsc
CC=golang-dev
https://golang.org/cl/4899046

src/pkg/go/parser/parser.go
src/pkg/go/parser/parser_test.go

index 618a15076507fb0939af5baf0fd917a2acfde4b8..3224ffe5599d9335543d17dd14b90fd13a1d8fc6 100644 (file)
@@ -1154,11 +1154,6 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
        case *ast.CallExpr:
        case *ast.StarExpr:
        case *ast.UnaryExpr:
-               if t.Op == token.RANGE {
-                       // the range operator is only allowed at the top of a for statement
-                       p.errorExpected(x.Pos(), "expression")
-                       x = &ast.BadExpr{x.Pos(), x.End()}
-               }
        case *ast.BinaryExpr:
        default:
                // all other nodes are not proper expressions
@@ -1223,11 +1218,6 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
        case *ast.ParenExpr:
                panic("unreachable")
        case *ast.UnaryExpr:
-               if t.Op == token.RANGE {
-                       // the range operator is only allowed at the top of a for statement
-                       p.errorExpected(x.Pos(), "expression")
-                       x = &ast.BadExpr{x.Pos(), x.End()}
-               }
        case *ast.ArrayType:
                if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis {
                        p.error(len.Pos(), "expected array length, found '...'")
@@ -1300,7 +1290,7 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
        }
 
        switch p.tok {
-       case token.ADD, token.SUB, token.NOT, token.XOR, token.AND, token.RANGE:
+       case token.ADD, token.SUB, token.NOT, token.XOR, token.AND:
                pos, op := p.pos, p.tok
                p.next()
                x := p.parseUnaryExpr(false)
@@ -1384,10 +1374,17 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
                token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
                token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN,
                token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN, token.AND_NOT_ASSIGN:
-               // assignment statement
+               // assignment statement, possibly part of a range clause
                pos, tok := p.pos, p.tok
                p.next()
-               y := p.parseRhsList()
+               var y []ast.Expr
+               if p.tok == token.RANGE && (tok == token.DEFINE || tok == token.ASSIGN) {
+                       pos := p.pos
+                       p.next()
+                       y = []ast.Expr{&ast.UnaryExpr{pos, token.RANGE, p.parseRhs()}}
+               } else {
+                       y = p.parseRhsList()
+               }
                return &ast.AssignStmt{x, pos, tok, y}
        }
 
@@ -1797,7 +1794,7 @@ func (p *parser) parseForStmt() ast.Stmt {
                }
                if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE {
                        // rhs is range expression
-                       // (any short variable declaration was handled by parseSimpleStat above)
+                       // (any short variable declaration was handled by parseSimpleStmt above)
                        return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body}
                }
                p.errorExpected(s2.Pos(), "range clause")
index 8269db839b521cc174c2749a5d987b4c9574fb71..72c82c37940fc0a96e031e405431370437c565dc 100644 (file)
@@ -51,6 +51,7 @@ var validPrograms = []interface{}{
        `package p; func f() { select { case x := (<-c): } };`,
        `package p; func f() { if ; true {} };`,
        `package p; func f() { switch ; {} };`,
+       `package p; func f() { for _ = range "foo" + "bar" {} };`,
 }
 
 func TestParseValidPrograms(t *testing.T) {