1
0
mirror of https://github.com/golang/go synced 2024-11-21 22:04:39 -07:00

go/parser: accept corner cases of signature syntax

- func f(int,) is a legal signature
- func f(...int,) is a legal signature

Defer checking for correct use of "..." with last
paremeter type to type checker instead of parser.

R=rsc
CC=golang-dev
https://golang.org/cl/4973059
This commit is contained in:
Robert Griesemer 2011-09-06 11:48:05 -07:00
parent c10679009a
commit 0783dd9027
2 changed files with 12 additions and 12 deletions

View File

@ -610,9 +610,6 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
p.error(pos, "'...' parameter is missing type") p.error(pos, "'...' parameter is missing type")
typ = &ast.BadExpr{pos, p.pos} typ = &ast.BadExpr{pos, p.pos}
} }
if p.tok != token.RPAREN {
p.error(pos, "can use '...' with last parameter type only")
}
return &ast.Ellipsis{pos, typ} return &ast.Ellipsis{pos, typ}
} }
return p.tryIdentOrType(false) return p.tryIdentOrType(false)
@ -635,21 +632,21 @@ func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
} }
// a list of identifiers looks like a list of type names // a list of identifiers looks like a list of type names
for { //
// parseVarType accepts any type (including parenthesized ones) // parse/tryVarType accepts any type (including parenthesized
// even though the syntax does not permit them here: we // ones) even though the syntax does not permit them here: we
// accept them all for more robust parsing and complain // accept them all for more robust parsing and complain later
// afterwards for typ := p.parseVarType(isParam); typ != nil; {
list = append(list, p.parseVarType(isParam)) list = append(list, typ)
if p.tok != token.COMMA { if p.tok != token.COMMA {
break break
} }
p.next() p.next()
typ = p.tryVarType(isParam) // maybe nil as in: func f(int,) {}
} }
// if we had a list of identifiers, it must be followed by a type // if we had a list of identifiers, it must be followed by a type
typ = p.tryVarType(isParam) if typ = p.tryVarType(isParam); typ != nil {
if typ != nil {
p.resolve(typ) p.resolve(typ)
} }

View File

@ -64,6 +64,9 @@ var validPrograms = []interface{}{
`package p; func f(...T);`, `package p; func f(...T);`,
`package p; func f(float, ...int);`, `package p; func f(float, ...int);`,
`package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`, `package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
`package p; func f(int,) {};`,
`package p; func f(...int,) {};`,
`package p; func f(x ...int,) {};`,
`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`, `package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`, `package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`, `package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
@ -77,7 +80,7 @@ var validPrograms = []interface{}{
func TestParseValidPrograms(t *testing.T) { func TestParseValidPrograms(t *testing.T) {
for _, src := range validPrograms { for _, src := range validPrograms {
_, err := ParseFile(fset, "", src, 0) _, err := ParseFile(fset, "", src, SpuriousErrors)
if err != nil { if err != nil {
t.Errorf("ParseFile(%q): %v", src, err) t.Errorf("ParseFile(%q): %v", src, err)
} }