summaryrefslogtreecommitdiff
path: root/src/pkg/go/parser/parser.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/parser/parser.go')
-rw-r--r--src/pkg/go/parser/parser.go42
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}
}
}