diff options
author | Robert Griesemer <gri@golang.org> | 2011-08-16 15:19:23 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2011-08-16 15:19:23 -0700 |
commit | 182cf988e95938e62d67f841d72b2abb73da5d0c (patch) | |
tree | e01514245c1c98b79ab8c6462eff766e40499962 | |
parent | 9801c8e886441460027c5b9a69382f26f3a86b4c (diff) | |
download | go-182cf988e95938e62d67f841d72b2abb73da5d0c.tar.gz go-182cf988e95938e62d67f841d72b2abb73da5d0c.zip |
go/parser: use correct precedence when parsing range clauses
Fixes #2156.
R=rsc
CC=golang-dev
https://golang.org/cl/4899046
-rw-r--r-- | src/pkg/go/parser/parser.go | 25 | ||||
-rw-r--r-- | src/pkg/go/parser/parser_test.go | 1 |
2 files changed, 12 insertions, 14 deletions
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index 618a150765..3224ffe559 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -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") diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go index 8269db839b..72c82c3794 100644 --- a/src/pkg/go/parser/parser_test.go +++ b/src/pkg/go/parser/parser_test.go @@ -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) { |