]> Cypherpunks repositories - gostls13.git/commitdiff
steps towards a simplified parser interface
authorRobert Griesemer <gri@golang.org>
Tue, 26 Jan 2010 01:24:50 +0000 (17:24 -0800)
committerRobert Griesemer <gri@golang.org>
Tue, 26 Jan 2010 01:24:50 +0000 (17:24 -0800)
minor cleanups (which I did at home before
but missed this morning at work)

R=rsc
CC=golang-dev
https://golang.org/cl/193095

src/pkg/go/parser/interface.go
src/pkg/go/parser/parser.go

index a434c64e474db32a5efeda5387336177078e4c75..3a6bfee7e7a86d0241087081f62a3d2fbed1c479 100644 (file)
@@ -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)
 }
 
index a680d862e56c3406915a50febbd730382e5acabb..ef610209e81d53b6707def7366e707fc2b9944e8 100644 (file)
@@ -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.