mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal/parser: improved a couple of error messages
The new syntax tree introduced with 1.8 represents send statements (ch <- x) as statements; the old syntax tree represented them as expressions (and parsed them as such) but complained if they were used in expression context. As a consequence, some of the errors that in the past were of the form "ch <- x used as value" now look like "unexpected <- ..." because a "<-" is not valid according to Go syntax in those situations. Accept the new error message. Also: Fine-tune handling of misformed for loop headers. Also: Minor cleanups/better comments. Fixes #17590. Change-Id: Ia541dea1f2f015c1b21f5b3ae44aacdec60a8aba Reviewed-on: https://go-review.googlesource.com/37386 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
2fa09a20e5
commit
f8ae30c4a2
3 changed files with 16 additions and 21 deletions
|
|
@ -663,7 +663,7 @@ func (p *parser) operand(keep_parens bool) Expr {
|
||||||
pos := p.pos()
|
pos := p.pos()
|
||||||
p.next()
|
p.next()
|
||||||
p.xnest++
|
p.xnest++
|
||||||
x := p.expr() // expr_or_type
|
x := p.expr()
|
||||||
p.xnest--
|
p.xnest--
|
||||||
p.want(_Rparen)
|
p.want(_Rparen)
|
||||||
|
|
||||||
|
|
@ -719,12 +719,6 @@ func (p *parser) operand(keep_parens bool) Expr {
|
||||||
case _Lbrack, _Chan, _Map, _Struct, _Interface:
|
case _Lbrack, _Chan, _Map, _Struct, _Interface:
|
||||||
return p.type_() // othertype
|
return p.type_() // othertype
|
||||||
|
|
||||||
case _Lbrace:
|
|
||||||
// common case: p.header is missing simpleStmt before { in if, for, switch
|
|
||||||
p.syntax_error("missing operand")
|
|
||||||
// '{' will be consumed in pexpr - no need to consume it here
|
|
||||||
return nil
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
p.syntax_error("expecting expression")
|
p.syntax_error("expecting expression")
|
||||||
p.advance()
|
p.advance()
|
||||||
|
|
@ -850,12 +844,12 @@ loop:
|
||||||
// operand may have returned a parenthesized complit
|
// operand may have returned a parenthesized complit
|
||||||
// type; accept it but complain if we have a complit
|
// type; accept it but complain if we have a complit
|
||||||
t := unparen(x)
|
t := unparen(x)
|
||||||
// determine if '{' belongs to a complit or a compound_stmt
|
// determine if '{' belongs to a composite literal or a block statement
|
||||||
complit_ok := false
|
complit_ok := false
|
||||||
switch t.(type) {
|
switch t.(type) {
|
||||||
case *Name, *SelectorExpr:
|
case *Name, *SelectorExpr:
|
||||||
if p.xnest >= 0 {
|
if p.xnest >= 0 {
|
||||||
// x is considered a comptype
|
// x is considered a composite literal type
|
||||||
complit_ok = true
|
complit_ok = true
|
||||||
}
|
}
|
||||||
case *ArrayType, *SliceType, *StructType, *MapType:
|
case *ArrayType, *SliceType, *StructType, *MapType:
|
||||||
|
|
@ -1692,6 +1686,7 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// p.tok != _Lbrace
|
||||||
|
|
||||||
outer := p.xnest
|
outer := p.xnest
|
||||||
p.xnest = -1
|
p.xnest = -1
|
||||||
|
|
@ -1712,7 +1707,7 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
|
||||||
var condStmt SimpleStmt
|
var condStmt SimpleStmt
|
||||||
var semi struct {
|
var semi struct {
|
||||||
pos src.Pos
|
pos src.Pos
|
||||||
lit string
|
lit string // valid if pos.IsKnown()
|
||||||
}
|
}
|
||||||
if p.tok == _Semi {
|
if p.tok == _Semi {
|
||||||
semi.pos = p.pos()
|
semi.pos = p.pos()
|
||||||
|
|
@ -1720,6 +1715,10 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
|
||||||
p.next()
|
p.next()
|
||||||
if keyword == _For {
|
if keyword == _For {
|
||||||
if p.tok != _Semi {
|
if p.tok != _Semi {
|
||||||
|
if p.tok == _Lbrace {
|
||||||
|
p.syntax_error("expecting for loop condition")
|
||||||
|
goto done
|
||||||
|
}
|
||||||
condStmt = p.simpleStmt(nil, false)
|
condStmt = p.simpleStmt(nil, false)
|
||||||
}
|
}
|
||||||
p.want(_Semi)
|
p.want(_Semi)
|
||||||
|
|
@ -1734,10 +1733,11 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
|
||||||
init = nil
|
init = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
// unpack condStmt
|
// unpack condStmt
|
||||||
switch s := condStmt.(type) {
|
switch s := condStmt.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
if keyword == _If {
|
if keyword == _If && semi.pos.IsKnown() {
|
||||||
if semi.lit != "semicolon" {
|
if semi.lit != "semicolon" {
|
||||||
p.syntax_error_at(semi.pos, fmt.Sprintf("unexpected %s, expecting { after if clause", semi.lit))
|
p.syntax_error_at(semi.pos, fmt.Sprintf("unexpected %s, expecting { after if clause", semi.lit))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2037,7 +2037,7 @@ func (p *parser) call(fun Expr) *CallExpr {
|
||||||
p.xnest++
|
p.xnest++
|
||||||
|
|
||||||
for p.tok != _EOF && p.tok != _Rparen {
|
for p.tok != _EOF && p.tok != _Rparen {
|
||||||
c.ArgList = append(c.ArgList, p.expr()) // expr_or_type
|
c.ArgList = append(c.ArgList, p.expr())
|
||||||
c.HasDots = p.got(_DotDotDot)
|
c.HasDots = p.got(_DotDotDot)
|
||||||
if !p.ocomma(_Rparen) || c.HasDots {
|
if !p.ocomma(_Rparen) || c.HasDots {
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ var c chan int
|
||||||
var v int
|
var v int
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if c <- v { // ERROR "used as value|missing condition|invalid condition"
|
if c <- v { // ERROR "used as value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = c <- v // ERROR "used as value|unexpected <-"
|
var _ = c <- v // ERROR "unexpected <-"
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,9 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// TODO(mdempsky): Update error expectations for new parser.
|
|
||||||
// The new parser emits an extra "missing { after for clause" error.
|
|
||||||
// The old parser is supposed to emit this too, but it panics first
|
|
||||||
// due to a nil pointer dereference.
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
for x // GCCGO_ERROR "undefined"
|
for x // GCCGO_ERROR "undefined"
|
||||||
{ // ERROR "expecting .*{.* after for clause|missing operand"
|
{ // ERROR "unexpected {, expecting for loop condition"
|
||||||
z // ERROR "undefined|expecting { after for clause"
|
z
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue