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.go117
1 files changed, 38 insertions, 79 deletions
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go
index 0f5582da9..270403aac 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/pkg/go/parser/parser.go
@@ -22,17 +22,6 @@ import (
)
-// Names to index the parser's commentIndex array.
-const (
- leading = iota; // index of the leading comments entry
- trailing; // index of the trailing comments entry
-)
-
-
-// Initial value for parser.commentsIndex.
-var noIndex = [2]int{-1, -1};
-
-
// noPos is used when there is no corresponding source position for a token.
var noPos token.Position;
@@ -60,8 +49,10 @@ type parser struct {
indent uint; // indentation used for tracing output
// Comments
- comments vector.Vector; // list of collected, unassociated comment groups
- commentsIndex [2]int; // comments indexes of last leading/trailing comment group; or -1
+ comments *ast.CommentGroup; // list of collected comments
+ lastComment *ast.CommentGroup; // last comment in the comments list
+ leadComment *ast.CommentGroup; // the last lead comment
+ lineComment *ast.CommentGroup; // the last line comment
// Next token
pos token.Position; // token position
@@ -90,8 +81,6 @@ func (p *parser) init(filename string, src []byte, mode uint) {
p.scanner.Init(filename, src, p, scannerMode(mode));
p.mode = mode;
p.trace = mode & Trace != 0; // for convenience (p.trace is used frequently)
- p.comments.Init(0);
- p.commentsIndex = noIndex;
p.next();
}
@@ -190,42 +179,49 @@ func (p *parser) consumeCommentGroup() int {
group[i] = list.At(i).(*ast.Comment);
}
- p.comments.Push(&ast.CommentGroup{group, endline});
+ // add comment group to the comments list
+ g := &ast.CommentGroup{group, nil};
+ if p.lastComment != nil {
+ p.lastComment.Next = g;
+ } else {
+ p.comments = g;
+ }
+ p.lastComment = g;
+
return endline;
}
// Advance to the next non-comment token. In the process, collect
-// any comment groups encountered, and remember the last leading
-// and trailing comments.
+// any comment groups encountered, and remember the last lead and
+// and line comments.
//
-// A leading comment is a comment group that starts and ends in a
+// A lead comment is a comment group that starts and ends in a
// line without any other tokens and that is followed by a non-comment
// token on the line immediately after the comment group.
//
-// A trailing comment is a comment group that follows a non-comment
+// A line comment is a comment group that follows a non-comment
// token on the same line, and that has no tokens after it on the line
// where it ends.
//
-// Leading and trailing comments may be considered documentation
-// that is stored in the AST. In that case they are removed from
-// the parser's list of unassociated comments (via getComment).
+// Lead and line comments may be considered documentation that is
+// stored in the AST.
//
func (p *parser) next() {
- p.commentsIndex = noIndex;
+ p.leadComment = nil;
+ p.lineComment = nil;
line := p.pos.Line; // current line
p.next0();
if p.tok == token.COMMENT {
if p.pos.Line == line {
// The comment is on same line as previous token; it
- // cannot be a leading comment but may be a trailing
- // comment.
+ // cannot be a lead comment but may be a line comment.
endline := p.consumeCommentGroup();
if p.pos.Line != endline {
// The next token is on a different line, thus
- // the last comment group is a trailing comment.
- p.commentsIndex[trailing] = p.comments.Len() - 1;
+ // the last comment group is a line comment.
+ p.lineComment = p.lastComment;
}
}
@@ -237,27 +233,13 @@ func (p *parser) next() {
if endline >= 0 && endline+1 == p.pos.Line {
// The next token is following on the line immediately after the
- // comment group, thus the last comment group is a leading comment.
- p.commentsIndex[leading] = p.comments.Len() - 1;
+ // comment group, thus the last comment group is a lead comment.
+ p.leadComment = p.lastComment;
}
}
}
-// Get leading/trailing comment group, if any.
-func (p *parser) getComment(kind int) *ast.CommentGroup {
- i := p.commentsIndex[kind];
- if i >= 0 {
- // get comment and remove if from the list of unassociated comment groups
- c := p.comments.At(i).(*ast.CommentGroup);
- p.comments.Set(i, nil); // clear entry
- p.commentsIndex[kind] = -1; // comment was consumed
- return c;
- }
- return nil;
-}
-
-
func (p *parser) errorExpected(pos token.Position, msg string) {
msg = "expected " + msg;
if pos.Offset == p.pos.Offset {
@@ -435,7 +417,7 @@ func (p *parser) parseFieldDecl() *ast.Field {
defer un(trace(p, "FieldDecl"));
}
- doc := p.getComment(leading);
+ doc := p.leadComment;
// a list of identifiers looks like a list of type names
list := vector.New(0);
@@ -496,9 +478,9 @@ func (p *parser) parseStructType() *ast.StructType {
list.Push(f);
if p.tok == token.SEMICOLON {
p.next();
- f.Comment = p.getComment(trailing);
+ f.Comment = p.lineComment;
} else {
- f.Comment = p.getComment(trailing);
+ f.Comment = p.lineComment;
break;
}
}
@@ -680,7 +662,7 @@ func (p *parser) parseMethodSpec() *ast.Field {
defer un(trace(p, "MethodSpec"));
}
- doc := p.getComment(leading);
+ doc := p.leadComment;
var idents []*ast.Ident;
var typ ast.Expr;
x := p.parseQualifiedIdent();
@@ -1680,7 +1662,7 @@ func (p *parser) parseStmt() ast.Stmt {
type parseSpecFunction func(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec, gotSemi bool)
-// Consume semicolon if there is one and getSemi is set, and get any trailing comment.
+// Consume semicolon if there is one and getSemi is set, and get any line comment.
// Return the comment if any and indicate if a semicolon was consumed.
//
func (p *parser) parseComment(getSemi bool) (comment *ast.CommentGroup, gotSemi bool) {
@@ -1688,7 +1670,7 @@ func (p *parser) parseComment(getSemi bool) (comment *ast.CommentGroup, gotSemi
p.next();
gotSemi = true;
}
- return p.getComment(trailing), gotSemi;
+ return p.lineComment, gotSemi;
}
@@ -1772,7 +1754,7 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction, getSemi
defer un(trace(p, keyword.String() + "Decl"));
}
- doc := p.getComment(leading);
+ doc := p.leadComment;
pos := p.expect(keyword);
var lparen, rparen token.Position;
list := vector.New(0);
@@ -1780,7 +1762,7 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction, getSemi
lparen = p.pos;
p.next();
for p.tok != token.RPAREN && p.tok != token.EOF {
- doc := p.getComment(leading);
+ doc := p.leadComment;
spec, semi := f(p, doc, true); // consume semicolon if any
list.Push(spec);
if !semi {
@@ -1845,7 +1827,7 @@ func (p *parser) parseFunctionDecl() *ast.FuncDecl {
defer un(trace(p, "FunctionDecl"));
}
- doc := p.getComment(leading);
+ doc := p.leadComment;
pos := p.expect(token.FUNC);
var recv *ast.Field;
@@ -1883,13 +1865,7 @@ func (p *parser) parseDecl(getSemi bool) (decl ast.Decl, gotSemi bool) {
case token.FUNC:
decl = p.parseFunctionDecl();
- // Do not use parseComment here to consume a semicolon
- // because we don't want to remove a trailing comment
- // from the list of unassociated comments.
- if getSemi && p.tok == token.SEMICOLON {
- p.next();
- gotSemi = true;
- }
+ _, gotSemi := p.parseComment(getSemi);
return decl, gotSemi;
default:
@@ -1915,7 +1891,7 @@ func (p *parser) parseFile() *ast.File {
}
// package clause
- comment := p.getComment(leading);
+ doc := p.leadComment;
pos := p.expect(token.PACKAGE);
ident := p.parseIdent();
var decls []ast.Decl;
@@ -1946,22 +1922,5 @@ func (p *parser) parseFile() *ast.File {
}
}
- // convert comments list
- // 1) determine number of remaining comments
- n := 0;
- for i := 0; i < p.comments.Len(); i++ {
- if p.comments.At(i) != nil {
- n++;
- }
- }
- // 2) convert the remaining comments
- comments := make([]*ast.CommentGroup, n);
- for i, j := 0, 0; i < p.comments.Len(); i++ {
- if p.comments.At(i) != nil {
- comments[j] = p.comments.At(i).(*ast.CommentGroup);
- j++;
- }
- }
-
- return &ast.File{comment, pos, ident, decls, comments};
+ return &ast.File{doc, pos, ident, decls, p.comments};
}