aboutsummaryrefslogtreecommitdiff
path: root/src/go/parser/parser.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2015-09-14 16:30:37 -0700
committerRobert Griesemer <gri@golang.org>2015-09-16 20:06:01 +0000
commit5b3f29a2e791c2489e6de16d44f3a626ce81a0ec (patch)
tree5ece854616b3bd80831149ce2ee4f4aa622b1f23 /src/go/parser/parser.go
parent5512ac2786f505dc4e63235de1e593ab295a15be (diff)
downloadgo-5b3f29a2e791c2489e6de16d44f3a626ce81a0ec.tar.gz
go-5b3f29a2e791c2489e6de16d44f3a626ce81a0ec.zip
go/parser: comma is not permitted at the end of a struct field list
Fixes #11611. Change-Id: I63d35cf15c3be759c899e3e561e631330dcc0bbb Reviewed-on: https://go-review.googlesource.com/14565 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Chris Manghane <cmang@golang.org>
Diffstat (limited to 'src/go/parser/parser.go')
-rw-r--r--src/go/parser/parser.go71
1 files changed, 34 insertions, 37 deletions
diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
index 855caa3daa..521bdce1dd 100644
--- a/src/go/parser/parser.go
+++ b/src/go/parser/parser.go
@@ -695,16 +695,19 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
doc := p.leadComment
- // FieldDecl
- list, typ := p.parseVarList(false)
-
- // Tag
- var tag *ast.BasicLit
- if p.tok == token.STRING {
- tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+ // 1st FieldDecl
+ // A type name used as an anonymous field looks like a field identifier.
+ var list []ast.Expr
+ for {
+ list = append(list, p.parseVarType(false))
+ if p.tok != token.COMMA {
+ break
+ }
p.next()
}
+ typ := p.tryVarType(false)
+
// analyze case
var idents []*ast.Ident
if typ != nil {
@@ -713,13 +716,22 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
} else {
// ["*"] TypeName (AnonymousField)
typ = list[0] // we always have at least one element
- if n := len(list); n > 1 || !isTypeName(deref(typ)) {
- pos := typ.Pos()
- p.errorExpected(pos, "anonymous field")
- typ = &ast.BadExpr{From: pos, To: p.safePos(list[n-1].End())}
+ if n := len(list); n > 1 {
+ p.errorExpected(p.pos, "type")
+ typ = &ast.BadExpr{From: p.pos, To: p.pos}
+ } else if !isTypeName(deref(typ)) {
+ p.errorExpected(typ.Pos(), "anonymous field")
+ typ = &ast.BadExpr{From: typ.Pos(), To: p.safePos(typ.End())}
}
}
+ // Tag
+ var tag *ast.BasicLit
+ if p.tok == token.STRING {
+ tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+ p.next()
+ }
+
p.expectSemi() // call before accessing p.linecomment
field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment}
@@ -796,42 +808,27 @@ func (p *parser) parseVarType(isParam bool) ast.Expr {
return typ
}
-// If any of the results are identifiers, they are not resolved.
-func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
+func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
if p.trace {
- defer un(trace(p, "VarList"))
+ defer un(trace(p, "ParameterList"))
}
- // a list of identifiers looks like a list of type names
- //
- // 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)
+ // 1st ParameterDecl
+ // A list of identifiers looks like a list of type names.
+ var list []ast.Expr
+ for {
+ list = append(list, p.parseVarType(ellipsisOk))
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)
-
- return
-}
-
-func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
- if p.trace {
- defer un(trace(p, "ParameterList"))
+ if p.tok == token.RPAREN {
+ break
+ }
}
- // ParameterDecl
- list, typ := p.parseVarList(ellipsisOk)
-
// analyze case
- if typ != nil {
+ if typ := p.tryVarType(ellipsisOk); typ != nil {
// IdentifierList Type
idents := p.makeIdentList(list)
field := &ast.Field{Names: idents, Type: typ}