diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go index a434c64e474..3a6bfee7e7a 100644 --- a/src/pkg/go/parser/interface.go +++ b/src/pkg/go/parser/interface.go @@ -50,6 +50,14 @@ func readSource(filename string, src interface{}) ([]byte, os.Error) { } +// TODO(gri) Simplify parser interface by splitting these functions +// into two parts: a single Init and a respective xParse +// function. The Init function can be shared. +// +// - the Init function will take a scope +// - if a scope is provided, the parser tracks declarations, otherwise it won't + + // ParseExpr parses a Go expression and returns the corresponding // AST node. The filename and src arguments have the same interpretation // as for ParseFile. If there is an error, the result expression @@ -62,7 +70,7 @@ func ParseExpr(filename string, src interface{}) (ast.Expr, os.Error) { } var p parser - p.init(filename, data, 0) + p.init(filename, data, nil, 0) return p.parseExpr(), p.GetError(scanner.Sorted) } @@ -79,7 +87,7 @@ func ParseStmtList(filename string, src interface{}) ([]ast.Stmt, os.Error) { } var p parser - p.init(filename, data, 0) + p.init(filename, data, nil, 0) return p.parseStmtList(), p.GetError(scanner.Sorted) } @@ -96,7 +104,7 @@ func ParseDeclList(filename string, src interface{}) ([]ast.Decl, os.Error) { } var p parser - p.init(filename, data, 0) + p.init(filename, data, nil, 0) return p.parseDeclList(), p.GetError(scanner.Sorted) } @@ -126,7 +134,13 @@ func ParseFile(filename string, src interface{}, mode uint) (*ast.File, os.Error } var p parser - p.init(filename, data, mode) + // TODO(gri) Remove CheckSemantics flag and code below once + // scope is provided via Init. + var scope *ast.Scope + if mode&CheckSemantics != 0 { + scope = ast.NewScope(nil) + } + p.init(filename, data, scope, mode) return p.parseFile(), p.GetError(scanner.NoMultiples) } diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index a680d862e56..ef610209e81 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -42,7 +42,6 @@ type parser struct { // Tracing/debugging mode uint // parsing mode - check bool // == (mode & CheckSemantics != 0) trace bool // == (mode & Trace != 0) indent uint // indentation used for tracing output @@ -61,6 +60,7 @@ type parser struct { exprLev int // < 0: in control clause, >= 0: in expression // Scopes + checkDecl bool // if set, check declarations pkgScope *ast.Scope fileScope *ast.Scope funcScope *ast.Scope @@ -77,13 +77,16 @@ func scannerMode(mode uint) uint { } -func (p *parser) init(filename string, src []byte, mode uint) { +func (p *parser) init(filename string, src []byte, scope *ast.Scope, 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.check = mode&CheckSemantics != 0 // for convenience (p.check is used frequently) - p.pkgScope = ast.NewScope(nil) // TODO(gri) should probably provide the pkgScope from outside - p.fileScope = ast.NewScope(p.pkgScope) + p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently) + if scope != nil { + p.checkDecl = true + } else { + scope = ast.NewScope(nil) // provide a dummy scope + } + p.pkgScope = scope p.next() } @@ -320,7 +323,7 @@ func (p *parser) parseIdentList(kind ast.ObjKind) []*ast.Ident { func (p *parser) declIdent(scope *ast.Scope, id *ast.Ident) { ok := scope.Declare(id.Obj) - if p.check && !ok { + if p.checkDecl && !ok { p.Error(id.Pos(), "'"+id.Name()+"' declared already") } } @@ -342,7 +345,7 @@ func (p *parser) declFieldList(scope *ast.Scope, list []*ast.Field) { func (p *parser) findIdent() *ast.Ident { pos := p.pos - name := "" + name := "_" var obj *ast.Object if p.tok == token.IDENT { name = string(p.lit) @@ -2033,6 +2036,7 @@ func (p *parser) parseFile() *ast.File { ident := p.parseIdent(ast.Pkg) // package name is in no scope p.expectSemi() + p.fileScope = ast.NewScope(p.pkgScope) var decls []ast.Decl // Don't bother parsing the rest if we had errors already.