Commit 6c740e76 authored by Robert Griesemer's avatar Robert Griesemer

go/parser: unify parsing of const and var declarations

The AST representation is already identical. Making the
code (nearly) identical in the parser reduces code size
and ensures that the ast.ValueSpec nodes have the same
values (specifically, iota). This in turn permits the
sharing of much of the respective code in the typechecker.

While at it: type functions work now, so use them.

R=r
CC=golang-dev
https://golang.org/cl/6624047
parent 9f807fcc
...@@ -2040,7 +2040,7 @@ func (p *parser) parseStmt() (s ast.Stmt) { ...@@ -2040,7 +2040,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Declarations // Declarations
type parseSpecFunction func(p *parser, doc *ast.CommentGroup, iota int) ast.Spec type parseSpecFunction func(p *parser, doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
func isValidImport(lit string) bool { func isValidImport(lit string) bool {
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
...@@ -2053,7 +2053,7 @@ func isValidImport(lit string) bool { ...@@ -2053,7 +2053,7 @@ func isValidImport(lit string) bool {
return s != "" return s != ""
} }
func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec { func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
if p.trace { if p.trace {
defer un(trace(p, "ImportSpec")) defer un(trace(p, "ImportSpec"))
} }
...@@ -2091,15 +2091,15 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec { ...@@ -2091,15 +2091,15 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
return spec return spec
} }
func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec { func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
if p.trace { if p.trace {
defer un(trace(p, "ConstSpec")) defer un(trace(p, keyword.String()+"Spec"))
} }
idents := p.parseIdentList() idents := p.parseIdentList()
typ := p.tryType() typ := p.tryType()
var values []ast.Expr var values []ast.Expr
if typ != nil || p.tok == token.ASSIGN || iota == 0 { if p.tok == token.ASSIGN || keyword == token.CONST && (typ != nil || iota == 0) || keyword == token.VAR && typ == nil {
p.expect(token.ASSIGN) p.expect(token.ASSIGN)
values = p.parseRhsList() values = p.parseRhsList()
} }
...@@ -2121,7 +2121,7 @@ func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec { ...@@ -2121,7 +2121,7 @@ func parseConstSpec(p *parser, doc *ast.CommentGroup, iota int) ast.Spec {
return spec return spec
} }
func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec { func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
if p.trace { if p.trace {
defer un(trace(p, "TypeSpec")) defer un(trace(p, "TypeSpec"))
} }
...@@ -2142,36 +2142,6 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec { ...@@ -2142,36 +2142,6 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
return spec return spec
} }
func parseVarSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
if p.trace {
defer un(trace(p, "VarSpec"))
}
idents := p.parseIdentList()
typ := p.tryType()
var values []ast.Expr
if typ == nil || p.tok == token.ASSIGN {
p.expect(token.ASSIGN)
values = p.parseRhsList()
}
p.expectSemi() // call before accessing p.linecomment
// Go spec: The scope of a constant or variable identifier declared inside
// a function begins at the end of the ConstSpec or VarSpec and ends at
// the end of the innermost containing block.
// (Global identifiers are resolved in a separate phase after parsing.)
spec := &ast.ValueSpec{
Doc: doc,
Names: idents,
Type: typ,
Values: values,
Comment: p.lineComment,
}
p.declare(spec, nil, p.topScope, ast.Var, idents...)
return spec
}
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl { func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
if p.trace { if p.trace {
defer un(trace(p, "GenDecl("+keyword.String()+")")) defer un(trace(p, "GenDecl("+keyword.String()+")"))
...@@ -2185,12 +2155,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen ...@@ -2185,12 +2155,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
lparen = p.pos lparen = p.pos
p.next() p.next()
for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ { for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
list = append(list, f(p, p.leadComment, iota)) list = append(list, f(p, p.leadComment, keyword, iota))
} }
rparen = p.expect(token.RPAREN) rparen = p.expect(token.RPAREN)
p.expectSemi() p.expectSemi()
} else { } else {
list = append(list, f(p, nil, 0)) list = append(list, f(p, nil, keyword, 0))
} }
return &ast.GenDecl{ return &ast.GenDecl{
...@@ -2290,14 +2260,11 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl { ...@@ -2290,14 +2260,11 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
var f parseSpecFunction var f parseSpecFunction
switch p.tok { switch p.tok {
case token.CONST: case token.CONST, token.VAR:
f = parseConstSpec f = (*parser).parseValueSpec
case token.TYPE: case token.TYPE:
f = parseTypeSpec f = (*parser).parseTypeSpec
case token.VAR:
f = parseVarSpec
case token.FUNC: case token.FUNC:
return p.parseFuncDecl() return p.parseFuncDecl()
...@@ -2349,7 +2316,7 @@ func (p *parser) parseFile() *ast.File { ...@@ -2349,7 +2316,7 @@ func (p *parser) parseFile() *ast.File {
if p.mode&PackageClauseOnly == 0 { if p.mode&PackageClauseOnly == 0 {
// import decls // import decls
for p.tok == token.IMPORT { for p.tok == token.IMPORT {
decls = append(decls, p.parseGenDecl(token.IMPORT, parseImportSpec)) decls = append(decls, p.parseGenDecl(token.IMPORT, (*parser).parseImportSpec))
} }
if p.mode&ImportsOnly == 0 { if p.mode&ImportsOnly == 0 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment