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:
Robert Griesemer 2017-02-22 13:43:23 -08:00
parent 2fa09a20e5
commit f8ae30c4a2
3 changed files with 16 additions and 21 deletions

View file

@ -663,7 +663,7 @@ func (p *parser) operand(keep_parens bool) Expr {
pos := p.pos()
p.next()
p.xnest++
x := p.expr() // expr_or_type
x := p.expr()
p.xnest--
p.want(_Rparen)
@ -719,12 +719,6 @@ func (p *parser) operand(keep_parens bool) Expr {
case _Lbrack, _Chan, _Map, _Struct, _Interface:
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:
p.syntax_error("expecting expression")
p.advance()
@ -850,12 +844,12 @@ loop:
// operand may have returned a parenthesized complit
// type; accept it but complain if we have a complit
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
switch t.(type) {
case *Name, *SelectorExpr:
if p.xnest >= 0 {
// x is considered a comptype
// x is considered a composite literal type
complit_ok = true
}
case *ArrayType, *SliceType, *StructType, *MapType:
@ -1692,6 +1686,7 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
}
return
}
// p.tok != _Lbrace
outer := p.xnest
p.xnest = -1
@ -1712,7 +1707,7 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
var condStmt SimpleStmt
var semi struct {
pos src.Pos
lit string
lit string // valid if pos.IsKnown()
}
if p.tok == _Semi {
semi.pos = p.pos()
@ -1720,6 +1715,10 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
p.next()
if keyword == _For {
if p.tok != _Semi {
if p.tok == _Lbrace {
p.syntax_error("expecting for loop condition")
goto done
}
condStmt = p.simpleStmt(nil, false)
}
p.want(_Semi)
@ -1734,10 +1733,11 @@ func (p *parser) header(keyword token) (init SimpleStmt, cond Expr, post SimpleS
init = nil
}
done:
// unpack condStmt
switch s := condStmt.(type) {
case nil:
if keyword == _If {
if keyword == _If && semi.pos.IsKnown() {
if semi.lit != "semicolon" {
p.syntax_error_at(semi.pos, fmt.Sprintf("unexpected %s, expecting { after if clause", semi.lit))
} else {
@ -2037,7 +2037,7 @@ func (p *parser) call(fun Expr) *CallExpr {
p.xnest++
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)
if !p.ocomma(_Rparen) || c.HasDots {
break

View file

@ -10,8 +10,8 @@ var c chan int
var v int
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 <-"

View file

@ -4,14 +4,9 @@
// Use of this source code is governed by a BSD-style
// 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
func main() {
for x // GCCGO_ERROR "undefined"
{ // ERROR "expecting .*{.* after for clause|missing operand"
z // ERROR "undefined|expecting { after for clause"
{ // ERROR "unexpected {, expecting for loop condition"
z