1
0
mirror of https://github.com/golang/go synced 2024-09-24 19:30:12 -06:00

go/parser: better error message if = is seen instead of ==

Fixes #4519.

R=rsc
CC=golang-dev
https://golang.org/cl/7733044
This commit is contained in:
Robert Griesemer 2013-03-11 15:23:18 -07:00
parent a25c403b3a
commit 916f4cfa64
2 changed files with 38 additions and 8 deletions

View File

@ -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
}
// ----------------------------------------------------------------------------

View File

@ -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) {