diff options
Diffstat (limited to 'src/pkg/go/parser/parser.go')
-rw-r--r-- | src/pkg/go/parser/parser.go | 42 |
1 files changed, 24 insertions, 18 deletions
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index e362e13a7..20e505d97 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -267,13 +267,13 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) { // Consume a group of adjacent comments, add it to the parser's // comments list, and return it together with the line at which -// the last comment in the group ends. An empty line or non-comment -// token terminates a comment group. +// the last comment in the group ends. A non-comment token or n +// empty lines terminate a comment group. // -func (p *parser) consumeCommentGroup() (comments *ast.CommentGroup, endline int) { +func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) { var list []*ast.Comment endline = p.file.Line(p.pos) - for p.tok == token.COMMENT && endline+1 >= p.file.Line(p.pos) { + for p.tok == token.COMMENT && p.file.Line(p.pos) <= endline+n { var comment *ast.Comment comment, endline = p.consumeComment() list = append(list, comment) @@ -314,7 +314,7 @@ func (p *parser) next() { if p.file.Line(p.pos) == line { // The comment is on same line as the previous token; it // cannot be a lead comment but may be a line comment. - comment, endline = p.consumeCommentGroup() + comment, endline = p.consumeCommentGroup(0) if p.file.Line(p.pos) != endline { // The next token is on a different line, thus // the last comment group is a line comment. @@ -325,7 +325,7 @@ func (p *parser) next() { // consume successor comments, if any endline = -1 for p.tok == token.COMMENT { - comment, endline = p.consumeCommentGroup() + comment, endline = p.consumeCommentGroup(1) } if endline+1 == p.file.Line(p.pos) { @@ -627,10 +627,10 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field { doc := p.leadComment - // fields + // FieldDecl list, typ := p.parseVarList(false) - // optional tag + // Tag var tag *ast.BasicLit if p.tok == token.STRING { tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit} @@ -645,7 +645,6 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field { } else { // ["*"] TypeName (AnonymousField) typ = list[0] // we always have at least one element - p.resolve(typ) if n := len(list); n > 1 || !isTypeName(deref(typ)) { pos := typ.Pos() p.errorExpected(pos, "anonymous field") @@ -657,6 +656,7 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field { field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment} p.declare(field, nil, scope, ast.Var, idents...) + p.resolve(typ) return field } @@ -699,12 +699,15 @@ func (p *parser) parsePointerType() *ast.StarExpr { return &ast.StarExpr{Star: star, X: base} } +// If the result is an identifier, it is not resolved. func (p *parser) tryVarType(isParam bool) ast.Expr { if isParam && p.tok == token.ELLIPSIS { pos := p.pos p.next() typ := p.tryIdentOrType(isParam) // don't use parseType so we can provide better error message - if typ == nil { + if typ != nil { + p.resolve(typ) + } else { p.error(pos, "'...' parameter is missing type") typ = &ast.BadExpr{From: pos, To: p.pos} } @@ -713,6 +716,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr { return p.tryIdentOrType(false) } +// If the result is an identifier, it is not resolved. func (p *parser) parseVarType(isParam bool) ast.Expr { typ := p.tryVarType(isParam) if typ == nil { @@ -724,6 +728,7 @@ 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) { if p.trace { defer un(trace(p, "VarList")) @@ -744,9 +749,7 @@ func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) { } // if we had a list of identifiers, it must be followed by a type - if typ = p.tryVarType(isParam); typ != nil { - p.resolve(typ) - } + typ = p.tryVarType(isParam) return } @@ -756,7 +759,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [ defer un(trace(p, "ParameterList")) } + // ParameterDecl list, typ := p.parseVarList(ellipsisOk) + + // analyze case if typ != nil { // IdentifierList Type idents := p.makeIdentList(list) @@ -765,10 +771,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [ // Go spec: The scope of an identifier denoting a function // parameter or result variable is the function body. p.declare(field, nil, scope, ast.Var, idents...) + p.resolve(typ) if p.tok == token.COMMA { p.next() } - for p.tok != token.RPAREN && p.tok != token.EOF { idents := p.parseIdentList() typ := p.parseVarType(ellipsisOk) @@ -777,18 +783,18 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [ // Go spec: The scope of an identifier denoting a function // parameter or result variable is the function body. p.declare(field, nil, scope, ast.Var, idents...) + p.resolve(typ) if !p.atComma("parameter list") { break } p.next() } - } else { // Type { "," Type } (anonymous parameters) params = make([]*ast.Field, len(list)) - for i, x := range list { - p.resolve(x) - params[i] = &ast.Field{Type: x} + for i, typ := range list { + p.resolve(typ) + params[i] = &ast.Field{Type: typ} } } |