Commit f8ae30c4 authored by Robert Griesemer's avatar Robert Griesemer

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/37386Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent 2fa09a20
...@@ -663,7 +663,7 @@ func (p *parser) operand(keep_parens bool) Expr { ...@@ -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 { ...@@ -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: ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 ...@@ -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 @@ ...@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment