diff options
author | Michael Stapelberg <michael@stapelberg.de> | 2013-03-23 11:28:53 +0100 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2013-03-23 11:28:53 +0100 |
commit | b39e15dde5ec7b96c15da9faf4ab5892501c1aae (patch) | |
tree | 718cede1f6ca97d082c6c40b7dc3f4f6148253c0 /src/pkg/go/parser | |
parent | 04b08da9af0c450d645ab7389d1467308cfc2db8 (diff) | |
download | golang-upstream/1.1_hg20130323.tar.gz |
Imported Upstream version 1.1~hg20130323upstream/1.1_hg20130323
Diffstat (limited to 'src/pkg/go/parser')
-rw-r--r-- | src/pkg/go/parser/error_test.go | 2 | ||||
-rw-r--r-- | src/pkg/go/parser/parser.go | 55 | ||||
-rw-r--r-- | src/pkg/go/parser/short_test.go | 3 |
3 files changed, 44 insertions, 16 deletions
diff --git a/src/pkg/go/parser/error_test.go b/src/pkg/go/parser/error_test.go index b59fda11a..d4d4f909d 100644 --- a/src/pkg/go/parser/error_test.go +++ b/src/pkg/go/parser/error_test.go @@ -89,8 +89,6 @@ func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]str prev = pos } } - - panic("unreachable") } // compareErrors compares the map of expected error messages with the list diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index a021a5abe..f4a690a6f 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -48,7 +48,8 @@ type parser struct { syncCnt int // number of calls to syncXXX without progress // Non-syntactic parser control - exprLev int // < 0: in control clause, >= 0: in expression + exprLev int // < 0: in control clause, >= 0: in expression + inRhs bool // if set, the parser is parsing a rhs expression // Ordinary identifier scopes pkgScope *ast.Scope // pkgScope.Outer == nil @@ -539,6 +540,8 @@ func (p *parser) parseExprList(lhs bool) (list []ast.Expr) { } func (p *parser) parseLhsList() []ast.Expr { + old := p.inRhs + p.inRhs = false list := p.parseExprList(true) switch p.tok { case token.DEFINE: @@ -560,11 +563,16 @@ func (p *parser) parseLhsList() []ast.Expr { p.resolve(x) } } + p.inRhs = old return list } func (p *parser) parseRhsList() []ast.Expr { - return p.parseExprList(false) + old := p.inRhs + p.inRhs = true + list := p.parseExprList(false) + p.inRhs = old + return list } // ---------------------------------------------------------------------------- @@ -1505,6 +1513,14 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr { return p.parsePrimaryExpr(lhs) } +func (p *parser) tokPrec() (token.Token, int) { + tok := p.tok + if p.inRhs && tok == token.ASSIGN { + tok = token.EQL + } + return tok, tok.Precedence() +} + // If lhs is set and the result is an identifier, it is not resolved. func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr { if p.trace { @@ -1512,10 +1528,13 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr { } x := p.parseUnaryExpr(lhs) - for prec := p.tok.Precedence(); prec >= prec1; prec-- { - for p.tok.Precedence() == prec { - pos, op := p.pos, p.tok - p.next() + for _, prec := p.tokPrec(); prec >= prec1; prec-- { + for { + op, oprec := p.tokPrec() + if oprec != prec { + break + } + pos := p.expect(op) if lhs { p.resolve(x) lhs = false @@ -1541,11 +1560,19 @@ func (p *parser) parseExpr(lhs bool) ast.Expr { } func (p *parser) parseRhs() ast.Expr { - return p.checkExpr(p.parseExpr(false)) + old := p.inRhs + p.inRhs = true + x := p.checkExpr(p.parseExpr(false)) + p.inRhs = old + return x } func (p *parser) parseRhsOrType() ast.Expr { - return p.checkExprOrType(p.parseExpr(false)) + old := p.inRhs + p.inRhs = true + x := p.checkExprOrType(p.parseExpr(false)) + p.inRhs = old + return x } // ---------------------------------------------------------------------------- @@ -2091,7 +2118,7 @@ func (p *parser) parseStmt() (s ast.Stmt) { // ---------------------------------------------------------------------------- // Declarations -type parseSpecFunction func(p *parser, doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec +type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec func isValidImport(lit string) bool { const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" @@ -2210,12 +2237,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen lparen = p.pos p.next() for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ { - list = append(list, f(p, p.leadComment, keyword, iota)) + list = append(list, f(p.leadComment, keyword, iota)) } rparen = p.expect(token.RPAREN) p.expectSemi() } else { - list = append(list, f(p, nil, keyword, 0)) + list = append(list, f(nil, keyword, 0)) } return &ast.GenDecl{ @@ -2316,10 +2343,10 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl { var f parseSpecFunction switch p.tok { case token.CONST, token.VAR: - f = (*parser).parseValueSpec + f = p.parseValueSpec case token.TYPE: - f = (*parser).parseTypeSpec + f = p.parseTypeSpec case token.FUNC: return p.parseFuncDecl() @@ -2371,7 +2398,7 @@ func (p *parser) parseFile() *ast.File { if p.mode&PackageClauseOnly == 0 { // import decls for p.tok == token.IMPORT { - decls = append(decls, p.parseGenDecl(token.IMPORT, (*parser).parseImportSpec)) + decls = append(decls, p.parseGenDecl(token.IMPORT, p.parseImportSpec)) } if p.mode&ImportsOnly == 0 { diff --git a/src/pkg/go/parser/short_test.go b/src/pkg/go/parser/short_test.go index c62f7e050..62277c0d2 100644 --- a/src/pkg/go/parser/short_test.go +++ b/src/pkg/go/parser/short_test.go @@ -71,6 +71,9 @@ var invalids = []string{ `package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`, `package p; func f() { _ = (<-chan<-chan<-chan<-chan<-chan<- /* ERROR "expected channel type" */ int)(nil) };`, `package p; func f() { var t []int; t /* ERROR "expected identifier on left side of :=" */ [0] := 0 };`, + `package p; func f() { if x := g(); x = /* ERROR "expected '=='" */ 0 {}};`, + `package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`, + `package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`, } func TestInvalid(t *testing.T) { |