]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: accept corner cases of signature syntax
authorRobert Griesemer <gri@golang.org>
Tue, 6 Sep 2011 18:48:05 +0000 (11:48 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 6 Sep 2011 18:48:05 +0000 (11:48 -0700)
- 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

src/pkg/go/parser/parser.go
src/pkg/go/parser/parser_test.go

index 7a9ed9dedd4546d16c19d4e1a8b605543a1e23a2..be82b2f801abaf99d1860dc966cff9ee11cc525b 100644 (file)
@@ -610,9 +610,6 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
                        p.error(pos, "'...' parameter is missing type")
                        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 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
-       for {
-               // parseVarType accepts any type (including parenthesized ones)
-               // even though the syntax does not permit them here: we
-               // accept them all for more robust parsing and complain
-               // afterwards
-               list = append(list, p.parseVarType(isParam))
+       //
+       // parse/tryVarType accepts any type (including parenthesized
+       // ones) even though the syntax does not permit them here: we
+       // accept them all for more robust parsing and complain later
+       for typ := p.parseVarType(isParam); typ != nil; {
+               list = append(list, typ)
                if p.tok != token.COMMA {
                        break
                }
                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
-       typ = p.tryVarType(isParam)
-       if typ != nil {
+       if typ = p.tryVarType(isParam); typ != nil {
                p.resolve(typ)
        }
 
index fb91dd1e7c1a1c0c2841f12bd32d2781bb7d3f83..9705dcff250468d18d99fdea08e922fa909c63ee 100644 (file)
@@ -64,6 +64,9 @@ var validPrograms = []interface{}{
        `package p; func f(...T);`,
        `package p; func f(float, ...int);`,
        `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; 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]} {} };`,
@@ -77,7 +80,7 @@ var validPrograms = []interface{}{
 
 func TestParseValidPrograms(t *testing.T) {
        for _, src := range validPrograms {
-               _, err := ParseFile(fset, "", src, 0)
+               _, err := ParseFile(fset, "", src, SpuriousErrors)
                if err != nil {
                        t.Errorf("ParseFile(%q): %v", src, err)
                }