summaryrefslogtreecommitdiff
path: root/src/go/parser/parser.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2022-08-31 13:43:28 -0700
committerGopher Robot <gobot@golang.org>2022-09-02 02:09:06 +0000
commitd394f99f49aa9249324f7c3ef3bc77a7cc1cebf7 (patch)
tree9566200ba7d489a05c4be904a14c95930aa910ab /src/go/parser/parser.go
parenta330ca5c541e99e4561420c852b14df63574a065 (diff)
downloadgo-git-d394f99f49aa9249324f7c3ef3bc77a7cc1cebf7.tar.gz
go/parser: more tolerant parsing of import declarations
This is a port of CL 427156 from the syntax package's parser to go/parser. While at it, remove an unused token.Pos parameter from parseSpecFunction and dependent declarations. Also, consolidate the respective test file. For #54511. Change-Id: Id6a28eb3d23a46fa5fa1d85d2c4e634b7015513c Reviewed-on: https://go-review.googlesource.com/c/go/+/427157 Run-TryBot: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/go/parser/parser.go')
-rw-r--r--src/go/parser/parser.go34
1 files changed, 21 insertions, 13 deletions
diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
index fcd6a4adcc..6d1ab34815 100644
--- a/src/go/parser/parser.go
+++ b/src/go/parser/parser.go
@@ -399,9 +399,10 @@ var stmtStart = map[token.Token]bool{
}
var declStart = map[token.Token]bool{
- token.CONST: true,
- token.TYPE: true,
- token.VAR: true,
+ token.IMPORT: true,
+ token.CONST: true,
+ token.TYPE: true,
+ token.VAR: true,
}
var exprEnd = map[token.Token]bool{
@@ -2416,9 +2417,9 @@ func (p *parser) parseStmt() (s ast.Stmt) {
// ----------------------------------------------------------------------------
// Declarations
-type parseSpecFunction func(doc *ast.CommentGroup, pos token.Pos, keyword token.Token, iota int) ast.Spec
+type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
-func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec {
+func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
if p.trace {
defer un(trace(p, "ImportSpec"))
}
@@ -2442,10 +2443,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Tok
p.next()
} else {
p.error(pos, "missing import path")
- // don't advance if we're at a semicolon or closing parenthesis
- if p.tok != token.SEMICOLON && p.tok != token.RPAREN {
- p.next()
- }
+ p.advance(exprEnd)
}
p.expectSemi() // call before accessing p.linecomment
@@ -2461,7 +2459,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Tok
return spec
}
-func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword token.Token, iota int) ast.Spec {
+func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
if p.trace {
defer un(trace(p, keyword.String()+"Spec"))
}
@@ -2520,7 +2518,7 @@ func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *
spec.Type = p.parseType()
}
-func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec {
+func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
if p.trace {
defer un(trace(p, "TypeSpec"))
}
@@ -2673,12 +2671,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
lparen = p.pos
p.next()
for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
- list = append(list, f(p.leadComment, pos, keyword, iota))
+ list = append(list, f(p.leadComment, keyword, iota))
}
rparen = p.expect(token.RPAREN)
p.expectSemi()
} else {
- list = append(list, f(nil, pos, keyword, 0))
+ list = append(list, f(nil, keyword, 0))
}
return &ast.GenDecl{
@@ -2754,6 +2752,9 @@ func (p *parser) parseDecl(sync map[token.Token]bool) ast.Decl {
var f parseSpecFunction
switch p.tok {
+ case token.IMPORT:
+ f = p.parseImportSpec
+
case token.CONST, token.VAR:
f = p.parseValueSpec
@@ -2813,7 +2814,14 @@ func (p *parser) parseFile() *ast.File {
if p.mode&ImportsOnly == 0 {
// rest of package body
+ prev := token.IMPORT
for p.tok != token.EOF {
+ // Continue to accept import declarations for error tolerance, but complain.
+ if p.tok == token.IMPORT && prev != token.IMPORT {
+ p.error(p.pos, "imports must appear before other declarations")
+ }
+ prev = p.tok
+
decls = append(decls, p.parseDecl(declStart))
}
}