Commit dc061ffc authored by Robert Griesemer's avatar Robert Griesemer

steps towards a simplified parser interface

minor cleanups (which I did at home before
but missed this morning at work)

R=rsc
CC=golang-dev
https://golang.org/cl/193095
parent a1792909
...@@ -50,6 +50,14 @@ func readSource(filename string, src interface{}) ([]byte, os.Error) { ...@@ -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 // ParseExpr parses a Go expression and returns the corresponding
// AST node. The filename and src arguments have the same interpretation // AST node. The filename and src arguments have the same interpretation
// as for ParseFile. If there is an error, the result expression // 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) { ...@@ -62,7 +70,7 @@ func ParseExpr(filename string, src interface{}) (ast.Expr, os.Error) {
} }
var p parser var p parser
p.init(filename, data, 0) p.init(filename, data, nil, 0)
return p.parseExpr(), p.GetError(scanner.Sorted) return p.parseExpr(), p.GetError(scanner.Sorted)
} }
...@@ -79,7 +87,7 @@ func ParseStmtList(filename string, src interface{}) ([]ast.Stmt, os.Error) { ...@@ -79,7 +87,7 @@ func ParseStmtList(filename string, src interface{}) ([]ast.Stmt, os.Error) {
} }
var p parser var p parser
p.init(filename, data, 0) p.init(filename, data, nil, 0)
return p.parseStmtList(), p.GetError(scanner.Sorted) return p.parseStmtList(), p.GetError(scanner.Sorted)
} }
...@@ -96,7 +104,7 @@ func ParseDeclList(filename string, src interface{}) ([]ast.Decl, os.Error) { ...@@ -96,7 +104,7 @@ func ParseDeclList(filename string, src interface{}) ([]ast.Decl, os.Error) {
} }
var p parser var p parser
p.init(filename, data, 0) p.init(filename, data, nil, 0)
return p.parseDeclList(), p.GetError(scanner.Sorted) return p.parseDeclList(), p.GetError(scanner.Sorted)
} }
...@@ -126,7 +134,13 @@ func ParseFile(filename string, src interface{}, mode uint) (*ast.File, os.Error ...@@ -126,7 +134,13 @@ func ParseFile(filename string, src interface{}, mode uint) (*ast.File, os.Error
} }
var p parser 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) return p.parseFile(), p.GetError(scanner.NoMultiples)
} }
......
...@@ -42,7 +42,6 @@ type parser struct { ...@@ -42,7 +42,6 @@ type parser struct {
// Tracing/debugging // Tracing/debugging
mode uint // parsing mode mode uint // parsing mode
check bool // == (mode & CheckSemantics != 0)
trace bool // == (mode & Trace != 0) trace bool // == (mode & Trace != 0)
indent uint // indentation used for tracing output indent uint // indentation used for tracing output
...@@ -61,6 +60,7 @@ type parser struct { ...@@ -61,6 +60,7 @@ type parser struct {
exprLev int // < 0: in control clause, >= 0: in expression exprLev int // < 0: in control clause, >= 0: in expression
// Scopes // Scopes
checkDecl bool // if set, check declarations
pkgScope *ast.Scope pkgScope *ast.Scope
fileScope *ast.Scope fileScope *ast.Scope
funcScope *ast.Scope funcScope *ast.Scope
...@@ -77,13 +77,16 @@ func scannerMode(mode uint) uint { ...@@ -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.scanner.Init(filename, src, p, scannerMode(mode))
p.mode = mode p.mode = mode
p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently) p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
p.check = mode&CheckSemantics != 0 // for convenience (p.check is used frequently) if scope != nil {
p.pkgScope = ast.NewScope(nil) // TODO(gri) should probably provide the pkgScope from outside p.checkDecl = true
p.fileScope = ast.NewScope(p.pkgScope) } else {
scope = ast.NewScope(nil) // provide a dummy scope
}
p.pkgScope = scope
p.next() p.next()
} }
...@@ -320,7 +323,7 @@ func (p *parser) parseIdentList(kind ast.ObjKind) []*ast.Ident { ...@@ -320,7 +323,7 @@ func (p *parser) parseIdentList(kind ast.ObjKind) []*ast.Ident {
func (p *parser) declIdent(scope *ast.Scope, id *ast.Ident) { func (p *parser) declIdent(scope *ast.Scope, id *ast.Ident) {
ok := scope.Declare(id.Obj) ok := scope.Declare(id.Obj)
if p.check && !ok { if p.checkDecl && !ok {
p.Error(id.Pos(), "'"+id.Name()+"' declared already") p.Error(id.Pos(), "'"+id.Name()+"' declared already")
} }
} }
...@@ -342,7 +345,7 @@ func (p *parser) declFieldList(scope *ast.Scope, list []*ast.Field) { ...@@ -342,7 +345,7 @@ func (p *parser) declFieldList(scope *ast.Scope, list []*ast.Field) {
func (p *parser) findIdent() *ast.Ident { func (p *parser) findIdent() *ast.Ident {
pos := p.pos pos := p.pos
name := "" name := "_"
var obj *ast.Object var obj *ast.Object
if p.tok == token.IDENT { if p.tok == token.IDENT {
name = string(p.lit) name = string(p.lit)
...@@ -2033,6 +2036,7 @@ func (p *parser) parseFile() *ast.File { ...@@ -2033,6 +2036,7 @@ func (p *parser) parseFile() *ast.File {
ident := p.parseIdent(ast.Pkg) // package name is in no scope ident := p.parseIdent(ast.Pkg) // package name is in no scope
p.expectSemi() p.expectSemi()
p.fileScope = ast.NewScope(p.pkgScope)
var decls []ast.Decl var decls []ast.Decl
// Don't bother parsing the rest if we had errors already. // Don't bother parsing the rest if we had errors already.
......
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