]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: match const/var decl parsing of syntax package
authorRobert Griesemer <gri@golang.org>
Thu, 18 Aug 2022 23:42:28 +0000 (16:42 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 19 Aug 2022 19:39:48 +0000 (19:39 +0000)
Use same approach to parsing const and var declarations
as the syntax package. Specifically, don't complain if
the first const specification in a const declaration
doesn't have a type and initialization expression. This
removes some duplicate errors when combined with the
type checker.

Adjust corresponding type checker tests accordingly.

For #54511.

Change-Id: I96702eba51dda6b581dad44577a7f93e4c02c857
Reviewed-on: https://go-review.googlesource.com/c/go/+/424904
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>

src/go/parser/parser.go
src/go/parser/short_test.go
src/go/types/testdata/check/constdecl.go
src/go/types/testdata/check/vardecl.go

index 36f9db9ddfc81a031b2cc10f28637ea6847742c4..d405ade6a5bbfbea4d68603f691f8c6e7f054203 100644 (file)
@@ -2553,27 +2553,31 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword toke
                defer un(trace(p, keyword.String()+"Spec"))
        }
 
-       pos := p.pos
        idents := p.parseIdentList()
-       typ := p.tryIdentOrType()
+       var typ ast.Expr
        var values []ast.Expr
-       // always permit optional initialization for more tolerant parsing
-       if p.tok == token.ASSIGN {
-               p.next()
-               values = p.parseList(true)
-       }
-       p.expectSemi() // call before accessing p.linecomment
-
        switch keyword {
+       case token.CONST:
+               // always permit optional type and initialization for more tolerant parsing
+               if p.tok != token.EOF && p.tok != token.SEMICOLON && p.tok != token.RPAREN {
+                       typ = p.tryIdentOrType()
+                       if p.tok == token.ASSIGN {
+                               p.next()
+                               values = p.parseList(true)
+                       }
+               }
        case token.VAR:
-               if typ == nil && values == nil {
-                       p.error(pos, "missing variable type or initialization")
+               if p.tok != token.ASSIGN {
+                       typ = p.parseType()
                }
-       case token.CONST:
-               if values == nil && (iota == 0 || typ != nil) {
-                       p.error(pos, "missing constant value")
+               if p.tok == token.ASSIGN {
+                       p.next()
+                       values = p.parseList(true)
                }
+       default:
+               panic("unreachable")
        }
+       p.expectSemi() // call before accessing p.linecomment
 
        spec := &ast.ValueSpec{
                Doc:     doc,
index 6e28e23377dbbff5bb15b5955789fbbe67cc4bb8..4d1da11706f253b4d23e31a8ce9f9632cbacdcb2 100644 (file)
@@ -194,10 +194,7 @@ var invalids = []string{
        `package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
 
        // issue 9639
-       `package p; var x /* ERROR "missing variable type or initialization" */ , y, z;`,
-       `package p; const x /* ERROR "missing constant value" */ ;`,
-       `package p; const x /* ERROR "missing constant value" */ int;`,
-       `package p; const (x = 0; y; z /* ERROR "missing constant value" */ int);`,
+       `package p; var x, y, z; /* ERROR "expected type" */`,
 
        // issue 12437
        `package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ }{};`,
index f7a9dd43c088c9d4041544dd5e856280d64f76d7..bb07a361fa534a9a30247ddf99241f8c65649734 100644 (file)
@@ -21,20 +21,17 @@ func _() {
 }
 
 // Identifier and expression arity must match.
-// The first error message is produced by the parser.
-// In a real-world scenario, the type-checker would not be run
-// in this case and the 2nd error message would not appear.
-const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+const _ /* ERROR "missing init expr for _" */
 const _ = 1, 2 /* ERROR "extra init expr 2" */
 
-const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+const _ /* ERROR "missing init expr for _" */ int
 const _ int = 1, 2 /* ERROR "extra init expr 2" */
 
 const (
-       _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+       _ /* ERROR "missing init expr for _" */
        _ = 1, 2 /* ERROR "extra init expr 2" */
 
-       _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+       _ /* ERROR "missing init expr for _" */ int
        _ int = 1, 2 /* ERROR "extra init expr 2" */
 )
 
@@ -55,17 +52,17 @@ const (
 )
 
 func _() {
-       const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+       const _ /* ERROR "missing init expr for _" */
        const _ = 1, 2 /* ERROR "extra init expr 2" */
 
-       const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+       const _ /* ERROR "missing init expr for _" */ int
        const _ int = 1, 2 /* ERROR "extra init expr 2" */
 
        const (
-               _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */
+               _ /* ERROR "missing init expr for _" */
                _ = 1, 2 /* ERROR "extra init expr 2" */
 
-               _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int
+               _ /* ERROR "missing init expr for _" */ int
                _ int = 1, 2 /* ERROR "extra init expr 2" */
        )
 
index 56abf977224d5560539f4c1d0c3aaa1bdd5d736d..d4dc4a6c6067264ee3190ed9f3fa08451f4e7575 100644 (file)
@@ -14,12 +14,9 @@ var m map[string]int
 var _ int
 var _, _ int
 
-// The first error message is produced by the parser.
-// In a real-world scenario, the type-checker would not be run
-// in this case and the 2nd error message would not appear.
-var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */
-var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */, _
-var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */, _, _
+var _; /* ERROR "expected type" */
+var _, _; /* ERROR "expected type" */
+var _, _, _; /* ERROR "expected type" */
 
 // The initializer must be an expression.
 var _ = int /* ERROR "not an expression" */