mirror of
https://github.com/golang/go
synced 2024-11-26 09:08:07 -07:00
Some AST tuning:
- have explicit XSpec nodes for declarations - have a general GenDecl node instead of DeclList R=rsc DELTA=164 (52 added, 52 deleted, 60 changed) OCL=27005 CL=27027
This commit is contained in:
parent
c4ad4f9fcf
commit
3ba69bf08b
@ -654,6 +654,38 @@ func (s *RangeStmt) Visit(v StmtVisitor) { v.DoRangeStmt(s); }
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
|
// A Spec node represents a single (non-parenthesized) import,
|
||||||
|
// constant, type, or variable declaration.
|
||||||
|
//
|
||||||
|
type (
|
||||||
|
// The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec.
|
||||||
|
Spec interface {};
|
||||||
|
|
||||||
|
// An ImportSpec node represents a single package import.
|
||||||
|
ImportSpec struct {
|
||||||
|
Doc Comments; // associated documentation; or nil
|
||||||
|
Name *Ident; // local package name (including "."); or nil
|
||||||
|
Path []*StringLit; // package path
|
||||||
|
};
|
||||||
|
|
||||||
|
// A ValueSpec node represents a constant or variable declaration
|
||||||
|
// (ConstSpec or VarSpec production).
|
||||||
|
ValueSpec struct {
|
||||||
|
Doc Comments; // associated documentation; or nil
|
||||||
|
Names []*Ident;
|
||||||
|
Type Expr; // value type; or nil
|
||||||
|
Values []Expr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A TypeSpec node represents a type declaration (TypeSpec production).
|
||||||
|
TypeSpec struct {
|
||||||
|
Doc Comments; // associated documentation; or nil
|
||||||
|
Name *Ident; // type name
|
||||||
|
Type Expr;
|
||||||
|
};
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
// A declaration is represented by one of the following declaration nodes.
|
// A declaration is represented by one of the following declaration nodes.
|
||||||
//
|
//
|
||||||
type (
|
type (
|
||||||
@ -665,51 +697,33 @@ type (
|
|||||||
token.Position; // beginning position of bad declaration
|
token.Position; // beginning position of bad declaration
|
||||||
};
|
};
|
||||||
|
|
||||||
ImportDecl struct {
|
// A GenDecl node (generic declaration node) represents an import,
|
||||||
Doc Comments; // associated documentation; or nil
|
// constant, type or variable declaration. A valid Lparen position
|
||||||
token.Position; // position of "import" keyword
|
// (Lparen.Line > 0) indicates a parenthesized declaration.
|
||||||
Name *Ident; // local package name or nil
|
//
|
||||||
Path []*StringLit; // package path
|
// Relationship between Tok value and Specs element type:
|
||||||
};
|
//
|
||||||
|
// token.IMPORT *ImportSpec
|
||||||
ConstDecl struct {
|
// token.CONST *ValueSpec
|
||||||
Doc Comments; // associated documentation; or nil
|
// token.TYPE *TypeSpec
|
||||||
token.Position; // position of "const" keyword
|
// token.VAR *ValueSpec
|
||||||
Names []*Ident;
|
//
|
||||||
Type Expr; // constant type or nil
|
GenDecl struct {
|
||||||
Values []Expr;
|
|
||||||
};
|
|
||||||
|
|
||||||
TypeDecl struct {
|
|
||||||
Doc Comments; // associated documentation; or nil
|
|
||||||
token.Position; // position of "type" keyword
|
|
||||||
Name *Ident;
|
|
||||||
Type Expr;
|
|
||||||
};
|
|
||||||
|
|
||||||
VarDecl struct {
|
|
||||||
Doc Comments; // associated documentation; or nil
|
|
||||||
token.Position; // position of "var" keyword
|
|
||||||
Names []*Ident;
|
|
||||||
Type Expr; // variable type or nil
|
|
||||||
Values []Expr;
|
|
||||||
};
|
|
||||||
|
|
||||||
FuncDecl struct {
|
|
||||||
Doc Comments; // associated documentation; or nil
|
|
||||||
Recv *Field; // receiver (methods) or nil (functions)
|
|
||||||
Name *Ident; // function/method name
|
|
||||||
Type *FuncType; // position of Func keyword, parameters and results
|
|
||||||
Body *BlockStmt; // function body or nil (forward declaration)
|
|
||||||
};
|
|
||||||
|
|
||||||
DeclList struct {
|
|
||||||
Doc Comments; // associated documentation; or nil
|
Doc Comments; // associated documentation; or nil
|
||||||
token.Position; // position of Tok
|
token.Position; // position of Tok
|
||||||
Tok token.Token; // IMPORT, CONST, VAR, TYPE
|
Tok token.Token; // IMPORT, CONST, TYPE, VAR
|
||||||
Lparen token.Position; // position of '('
|
Lparen token.Position; // position of '(', if any
|
||||||
List []Decl; // the list of parenthesized declarations
|
Specs []Spec;
|
||||||
Rparen token.Position; // position of ')'
|
Rparen token.Position; // position of ')', if any
|
||||||
|
};
|
||||||
|
|
||||||
|
// A FuncDecl node represents a function declaration.
|
||||||
|
FuncDecl struct {
|
||||||
|
Doc Comments; // associated documentation; or nil
|
||||||
|
Recv *Field; // receiver (methods); or nil (functions)
|
||||||
|
Name *Ident; // function/method name
|
||||||
|
Type *FuncType; // position of Func keyword, parameters and results
|
||||||
|
Body *BlockStmt; // function body; or nil (forward declaration)
|
||||||
};
|
};
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -725,24 +739,16 @@ func (d *FuncDecl) Pos() token.Position { return d.Type.Pos(); }
|
|||||||
//
|
//
|
||||||
type DeclVisitor interface {
|
type DeclVisitor interface {
|
||||||
DoBadDecl(d *BadDecl);
|
DoBadDecl(d *BadDecl);
|
||||||
DoImportDecl(d *ImportDecl);
|
DoGenDecl(d *GenDecl);
|
||||||
DoConstDecl(d *ConstDecl);
|
|
||||||
DoTypeDecl(d *TypeDecl);
|
|
||||||
DoVarDecl(d *VarDecl);
|
|
||||||
DoFuncDecl(d *FuncDecl);
|
DoFuncDecl(d *FuncDecl);
|
||||||
DoDeclList(d *DeclList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Visit() implementations for all declaration nodes.
|
// Visit() implementations for all declaration nodes.
|
||||||
//
|
//
|
||||||
func (d *BadDecl) Visit(v DeclVisitor) { v.DoBadDecl(d); }
|
func (d *BadDecl) Visit(v DeclVisitor) { v.DoBadDecl(d); }
|
||||||
func (d *ImportDecl) Visit(v DeclVisitor) { v.DoImportDecl(d); }
|
func (d *GenDecl) Visit(v DeclVisitor) { v.DoGenDecl(d); }
|
||||||
func (d *ConstDecl) Visit(v DeclVisitor) { v.DoConstDecl(d); }
|
|
||||||
func (d *TypeDecl) Visit(v DeclVisitor) { v.DoTypeDecl(d); }
|
|
||||||
func (d *VarDecl) Visit(v DeclVisitor) { v.DoVarDecl(d); }
|
|
||||||
func (d *FuncDecl) Visit(v DeclVisitor) { v.DoFuncDecl(d); }
|
func (d *FuncDecl) Visit(v DeclVisitor) { v.DoFuncDecl(d); }
|
||||||
func (d *DeclList) Visit(v DeclVisitor) { v.DoDeclList(d); }
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -1645,14 +1645,16 @@ func (p *parser) parseStatement() ast.Stmt {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
func (p *parser) parseImportSpec(pos token.Position, doc ast.Comments) *ast.ImportDecl {
|
type parseSpecFunction func(p *parser, doc ast.Comments) ast.Spec
|
||||||
|
|
||||||
|
func parseImportSpec(p *parser, doc ast.Comments) ast.Spec {
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "ImportSpec"));
|
defer un(trace(p, "ImportSpec"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var ident *ast.Ident;
|
var ident *ast.Ident;
|
||||||
if p.tok == token.PERIOD {
|
if p.tok == token.PERIOD {
|
||||||
p.error(p.pos, `"import ." not yet handled properly`);
|
ident = &ast.Ident{p.pos, []byte{'.'}};
|
||||||
p.next();
|
p.next();
|
||||||
} else if p.tok == token.IDENT {
|
} else if p.tok == token.IDENT {
|
||||||
ident = p.parseIdent();
|
ident = p.parseIdent();
|
||||||
@ -1665,11 +1667,11 @@ func (p *parser) parseImportSpec(pos token.Position, doc ast.Comments) *ast.Impo
|
|||||||
p.expect(token.STRING); // use expect() error handling
|
p.expect(token.STRING); // use expect() error handling
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.ImportDecl{doc, pos, ident, path};
|
return &ast.ImportSpec{doc, ident, path};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.ConstDecl {
|
func parseConstSpec(p *parser, doc ast.Comments) ast.Spec {
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "ConstSpec"));
|
defer un(trace(p, "ConstSpec"));
|
||||||
}
|
}
|
||||||
@ -1682,11 +1684,11 @@ func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.Const
|
|||||||
values = p.parseExpressionList();
|
values = p.parseExpressionList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.ConstDecl{doc, pos, idents, typ, values};
|
return &ast.ValueSpec{doc, idents, typ, values};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *parser) parseTypeSpec(pos token.Position, doc ast.Comments) *ast.TypeDecl {
|
func parseTypeSpec(p *parser, doc ast.Comments) ast.Spec {
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "TypeSpec"));
|
defer un(trace(p, "TypeSpec"));
|
||||||
}
|
}
|
||||||
@ -1694,11 +1696,11 @@ func (p *parser) parseTypeSpec(pos token.Position, doc ast.Comments) *ast.TypeDe
|
|||||||
ident := p.parseIdent();
|
ident := p.parseIdent();
|
||||||
typ := p.parseType();
|
typ := p.parseType();
|
||||||
|
|
||||||
return &ast.TypeDecl{doc, pos, ident, typ};
|
return &ast.TypeSpec{doc, ident, typ};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl {
|
func parseVarSpec(p *parser, doc ast.Comments) ast.Spec {
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "VarSpec"));
|
defer un(trace(p, "VarSpec"));
|
||||||
}
|
}
|
||||||
@ -1711,55 +1713,43 @@ func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl
|
|||||||
values = p.parseExpressionList();
|
values = p.parseExpressionList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ast.VarDecl{doc, pos, idents, typ, values};
|
return &ast.ValueSpec{doc, idents, typ, values};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p *parser) parseSpec(pos token.Position, doc ast.Comments, keyword int) ast.Decl {
|
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
|
||||||
switch keyword {
|
|
||||||
case token.IMPORT: return p.parseImportSpec(pos, doc);
|
|
||||||
case token.CONST: return p.parseConstSpec(pos, doc);
|
|
||||||
case token.TYPE: return p.parseTypeSpec(pos, doc);
|
|
||||||
case token.VAR: return p.parseVarSpec(pos, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(); // unreachable
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func (p *parser) parseDecl(keyword int) ast.Decl {
|
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "Decl"));
|
defer un(trace(p, keyword.String() + "Decl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
doc := p.getDoc();
|
doc := p.getDoc();
|
||||||
pos := p.expect(keyword);
|
pos := p.expect(keyword);
|
||||||
|
var lparen, rparen token.Position;
|
||||||
|
list := vector.New(0);
|
||||||
if p.tok == token.LPAREN {
|
if p.tok == token.LPAREN {
|
||||||
lparen := p.pos;
|
lparen = p.pos;
|
||||||
p.next();
|
p.next();
|
||||||
list := vector.New(0);
|
|
||||||
for p.tok != token.RPAREN && p.tok != token.EOF {
|
for p.tok != token.RPAREN && p.tok != token.EOF {
|
||||||
list.Push(p.parseSpec(noPos, nil, keyword));
|
doc := p.getDoc();
|
||||||
|
list.Push(f(p, doc));
|
||||||
if p.tok == token.SEMICOLON {
|
if p.tok == token.SEMICOLON {
|
||||||
p.next();
|
p.next();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rparen := p.expect(token.RPAREN);
|
rparen = p.expect(token.RPAREN);
|
||||||
p.opt_semi = true;
|
p.opt_semi = true;
|
||||||
|
} else {
|
||||||
// convert vector
|
list.Push(f(p, doc));
|
||||||
decls := make([]ast.Decl, list.Len());
|
|
||||||
for i := 0; i < list.Len(); i++ {
|
|
||||||
decls[i] = list.At(i).(ast.Decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ast.DeclList{doc, pos, keyword, lparen, decls, rparen};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.parseSpec(pos, doc, keyword);
|
// convert vector
|
||||||
|
specs := make([]ast.Spec, list.Len());
|
||||||
|
for i := 0; i < list.Len(); i++ {
|
||||||
|
specs[i] = list.At(i);
|
||||||
|
}
|
||||||
|
return &ast.GenDecl{doc, pos, keyword, lparen, specs, rparen};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1820,17 +1810,21 @@ func (p *parser) parseDeclaration() ast.Decl {
|
|||||||
defer un(trace(p, "Declaration"));
|
defer un(trace(p, "Declaration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var f parseSpecFunction;
|
||||||
switch p.tok {
|
switch p.tok {
|
||||||
case token.CONST, token.TYPE, token.VAR:
|
case token.CONST: f = parseConstSpec;
|
||||||
return p.parseDecl(p.tok);
|
case token.TYPE: f = parseTypeSpec;
|
||||||
|
case token.VAR: f = parseVarSpec;
|
||||||
case token.FUNC:
|
case token.FUNC:
|
||||||
return p.parseFunctionDecl();
|
return p.parseFunctionDecl();
|
||||||
|
default:
|
||||||
|
pos := p.pos;
|
||||||
|
p.error_expected(pos, "declaration");
|
||||||
|
p.next(); // make progress
|
||||||
|
return &ast.BadDecl{pos};
|
||||||
}
|
}
|
||||||
|
|
||||||
pos := p.pos;
|
return p.parseGenDecl(p.tok, f);
|
||||||
p.error_expected(pos, "declaration");
|
|
||||||
p.next(); // make progress
|
|
||||||
return &ast.BadDecl{pos};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1869,7 +1863,7 @@ func (p *parser) parsePackage() *ast.Program {
|
|||||||
// import decls
|
// import decls
|
||||||
list := vector.New(0);
|
list := vector.New(0);
|
||||||
for p.tok == token.IMPORT {
|
for p.tok == token.IMPORT {
|
||||||
list.Push(p.parseDecl(token.IMPORT));
|
list.Push(p.parseGenDecl(token.IMPORT, parseImportSpec));
|
||||||
if p.tok == token.SEMICOLON {
|
if p.tok == token.SEMICOLON {
|
||||||
p.next();
|
p.next();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user