]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: Remove unused Parse* functions. Simplified ParseExpr signature.
authorRobert Griesemer <gri@golang.org>
Fri, 13 Jan 2012 00:04:48 +0000 (16:04 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 13 Jan 2012 00:04:48 +0000 (16:04 -0800)
Only ParseFile, ParseDir, and ParseExpr are used in the tree.
If partial parsing of code is required, it is fairly simple
to wrap the relevant piece of code into a dummy package for
parsing (see parser.ParseExpr).

Also: minor cleanups.

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

src/cmd/cgo/gcc.go
src/cmd/gofix/fix.go
src/cmd/gofmt/rewrite.go
src/pkg/go/parser/interface.go
src/pkg/go/parser/parser.go
src/pkg/go/parser/parser_test.go

index 486090e90efba91034359e49504cdf120bd78d3d..155eb0440f944626944edca56bbbe39d3f6e2e4a 100644 (file)
@@ -344,8 +344,7 @@ func (p *Package) guessKinds(f *File) []*Name {
                        if _, err := strconv.Atoi(n.Define); err == nil {
                                ok = true
                        } else if n.Define[0] == '"' || n.Define[0] == '\'' {
-                               _, err := parser.ParseExpr(fset, "", n.Define)
-                               if err == nil {
+                               if _, err := parser.ParseExpr(n.Define); err == nil {
                                        ok = true
                                }
                        }
index 5d70e9cf9c71e67ec0ac0d647cd43160a251d2a5..d1a7bc8749a56f1b0f2f66da000e89b650b62060 100644 (file)
@@ -746,7 +746,7 @@ func usesImport(f *ast.File, path string) (used bool) {
 }
 
 func expr(s string) ast.Expr {
-       x, err := parser.ParseExpr(fset, "", s)
+       x, err := parser.ParseExpr(s)
        if err != nil {
                panic("parsing " + s + ": " + err.Error())
        }
index 60a4a7b49f95cfdfcf977ab6d6514375026955eb..3c7861f0d1152e7ad8e1753854e8fe22eafd9b23 100644 (file)
@@ -36,7 +36,7 @@ func initRewrite() {
 // but there are problems with preserving formatting and also
 // with what a wildcard for a statement looks like.
 func parseExpr(s string, what string) ast.Expr {
-       x, err := parser.ParseExpr(fset, "input", s)
+       x, err := parser.ParseExpr(s)
        if err != nil {
                fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
                os.Exit(2)
index be11f461c3b33b7351811c60335aad41c7761030..2ce3df8df714750db66d8e785fd18bda450c0351 100644 (file)
@@ -10,7 +10,6 @@ import (
        "bytes"
        "errors"
        "go/ast"
-       "go/scanner"
        "go/token"
        "io"
        "io/ioutil"
@@ -36,86 +35,28 @@ func readSource(filename string, src interface{}) ([]byte, error) {
                        }
                case io.Reader:
                        var buf bytes.Buffer
-                       _, err := io.Copy(&buf, s)
-                       if err != nil {
+                       if _, err := io.Copy(&buf, s); err != nil {
                                return nil, err
                        }
                        return buf.Bytes(), nil
-               default:
-                       return nil, errors.New("invalid source")
                }
+               return nil, errors.New("invalid source")
        }
-
        return ioutil.ReadFile(filename)
 }
 
-func (p *parser) errors() error {
-       mode := scanner.Sorted
-       if p.mode&SpuriousErrors == 0 {
-               mode = scanner.NoMultiples
-       }
-       return p.GetError(mode)
-}
-
-// ParseExpr parses a Go expression and returns the corresponding
-// AST node. The fset, filename, and src arguments have the same interpretation
-// as for ParseFile. If there is an error, the result expression
-// may be nil or contain a partial AST.
-//
-func ParseExpr(fset *token.FileSet, filename string, src interface{}) (ast.Expr, error) {
-       data, err := readSource(filename, src)
-       if err != nil {
-               return nil, err
-       }
-
-       var p parser
-       p.init(fset, filename, data, 0)
-       x := p.parseRhs()
-       if p.tok == token.SEMICOLON {
-               p.next() // consume automatically inserted semicolon, if any
-       }
-       p.expect(token.EOF)
-
-       return x, p.errors()
-}
-
-// ParseStmtList parses a list of Go statements and returns the list
-// of corresponding AST nodes. The fset, filename, and src arguments have the same
-// interpretation as for ParseFile. If there is an error, the node
-// list may be nil or contain partial ASTs.
+// The mode parameter to the Parse* functions is a set of flags (or 0).
+// They control the amount of source code parsed and other optional
+// parser functionality.
 //
-func ParseStmtList(fset *token.FileSet, filename string, src interface{}) ([]ast.Stmt, error) {
-       data, err := readSource(filename, src)
-       if err != nil {
-               return nil, err
-       }
-
-       var p parser
-       p.init(fset, filename, data, 0)
-       list := p.parseStmtList()
-       p.expect(token.EOF)
-
-       return list, p.errors()
-}
-
-// ParseDeclList parses a list of Go declarations and returns the list
-// of corresponding AST nodes. The fset, filename, and src arguments have the same
-// interpretation as for ParseFile. If there is an error, the node
-// list may be nil or contain partial ASTs.
-//
-func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast.Decl, error) {
-       data, err := readSource(filename, src)
-       if err != nil {
-               return nil, err
-       }
-
-       var p parser
-       p.init(fset, filename, data, 0)
-       list := p.parseDeclList()
-       p.expect(token.EOF)
-
-       return list, p.errors()
-}
+const (
+       PackageClauseOnly uint = 1 << iota // parsing stops after package clause
+       ImportsOnly                        // parsing stops after import declarations
+       ParseComments                      // parse comments and add them to AST
+       Trace                              // print a trace of parsed productions
+       DeclarationErrors                  // report declaration errors
+       SpuriousErrors                     // report all (not just the first) errors per line
+)
 
 // ParseFile parses the source code of a single Go source file and returns
 // the corresponding ast.File node. The source code may be provided via
@@ -124,7 +65,6 @@ func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast
 // If src != nil, ParseFile parses the source from src and the filename is
 // only used when recording position information. The type of the argument
 // for the src parameter must be string, []byte, or io.Reader.
-//
 // If src == nil, ParseFile parses the file specified by filename.
 //
 // The mode parameter controls the amount of source text parsed and other
@@ -133,49 +73,18 @@ func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast
 //
 // If the source couldn't be read, the returned AST is nil and the error
 // indicates the specific failure. If the source was read but syntax
-// errors were found, the result is a partial AST (with ast.BadX nodes
+// errors were found, the result is a partial AST (with ast.Bad* nodes
 // representing the fragments of erroneous source code). Multiple errors
 // are returned via a scanner.ErrorList which is sorted by file position.
 //
 func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint) (*ast.File, error) {
-       data, err := readSource(filename, src)
+       text, err := readSource(filename, src)
        if err != nil {
                return nil, err
        }
-
        var p parser
-       p.init(fset, filename, data, mode)
-       file := p.parseFile() // parseFile reads to EOF
-
-       return file, p.errors()
-}
-
-// ParseFiles calls ParseFile for each file in the filenames list and returns
-// a map of package name -> package AST with all the packages found. The mode
-// bits are passed to ParseFile unchanged. Position information is recorded
-// in the file set fset.
-//
-// Files with parse errors are ignored. In this case the map of packages may
-// be incomplete (missing packages and/or incomplete packages) and the first
-// error encountered is returned.
-//
-func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[string]*ast.Package, first error) {
-       pkgs = make(map[string]*ast.Package)
-       for _, filename := range filenames {
-               if src, err := ParseFile(fset, filename, nil, mode); err == nil {
-                       name := src.Name.Name
-                       pkg, found := pkgs[name]
-                       if !found {
-                               // TODO(gri) Use NewPackage here; reconsider ParseFiles API.
-                               pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
-                               pkgs[name] = pkg
-                       }
-                       pkg.Files[filename] = src
-               } else if first == nil {
-                       first = err
-               }
-       }
-       return
+       p.init(fset, filename, text, mode)
+       return p.parseFile(), p.errors()
 }
 
 // ParseDir calls ParseFile for the files in the directory specified by path and
@@ -186,9 +95,9 @@ func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[st
 //
 // If the directory couldn't be read, a nil map and the respective error are
 // returned. If a parse error occurred, a non-nil but incomplete map and the
-// error are returned.
+// first error encountered are returned.
 //
-func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode uint) (map[string]*ast.Package, error) {
+func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode uint) (pkgs map[string]*ast.Package, first error) {
        fd, err := os.Open(path)
        if err != nil {
                return nil, err
@@ -200,15 +109,36 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
                return nil, err
        }
 
-       filenames := make([]string, len(list))
-       n := 0
+       pkgs = make(map[string]*ast.Package)
        for _, d := range list {
                if filter == nil || filter(d) {
-                       filenames[n] = filepath.Join(path, d.Name())
-                       n++
+                       filename := filepath.Join(path, d.Name())
+                       if src, err := ParseFile(fset, filename, nil, mode); err == nil {
+                               name := src.Name.Name
+                               pkg, found := pkgs[name]
+                               if !found {
+                                       pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
+                                       pkgs[name] = pkg
+                               }
+                               pkg.Files[filename] = src
+                       } else if first == nil {
+                               first = err
+                       }
                }
        }
-       filenames = filenames[0:n]
 
-       return ParseFiles(fset, filenames, mode)
+       return
+}
+
+// ParseExpr is a convenience function for obtaining the AST of an expression x.
+// The position information recorded in the AST is undefined.
+// 
+func ParseExpr(x string) (ast.Expr, error) {
+       // parse x within the context of a complete package for correct scopes;
+       // use //line directive for correct positions in error messages
+       file, err := ParseFile(token.NewFileSet(), "", "package p;func _(){_=\n//line :1\n"+x+";}", 0)
+       if err != nil {
+               return nil, err
+       }
+       return file.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt).Rhs[0], nil
 }
index 8467b0e4e4a832fe3bc81436869414b285c9eee3..d90f5775df45eff5c6b51c10bffdb62a8e583f5d 100644 (file)
@@ -16,19 +16,6 @@ import (
        "go/token"
 )
 
-// The mode parameter to the Parse* functions is a set of flags (or 0).
-// They control the amount of source code parsed and other optional
-// parser functionality.
-//
-const (
-       PackageClauseOnly uint = 1 << iota // parsing stops after package clause
-       ImportsOnly                        // parsing stops after import declarations
-       ParseComments                      // parse comments and add them to AST
-       Trace                              // print a trace of parsed productions
-       DeclarationErrors                  // report declaration errors
-       SpuriousErrors                     // report all (not just the first) errors per line
-)
-
 // The parser structure holds the parser's internal state.
 type parser struct {
        file *token.File
@@ -65,18 +52,13 @@ type parser struct {
        targetStack [][]*ast.Ident // stack of unresolved labels
 }
 
-// scannerMode returns the scanner mode bits given the parser's mode bits.
-func scannerMode(mode uint) uint {
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
+       p.file = fset.AddFile(filename, fset.Base(), len(src))
        var m uint
        if mode&ParseComments != 0 {
-               m |= scanner.ScanComments
+               m = scanner.ScanComments
        }
-       return m
-}
-
-func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
-       p.file = fset.AddFile(filename, fset.Base(), len(src))
-       p.scanner.Init(p.file, src, p, scannerMode(mode))
+       p.scanner.Init(p.file, src, p, m)
 
        p.mode = mode
        p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
@@ -92,6 +74,14 @@ func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uin
        p.openLabelScope()
 }
 
+func (p *parser) errors() error {
+       m := scanner.Sorted
+       if p.mode&SpuriousErrors == 0 {
+               m = scanner.NoMultiples
+       }
+       return p.GetError(m)
+}
+
 // ----------------------------------------------------------------------------
 // Scoping support
 
@@ -2109,18 +2099,6 @@ func (p *parser) parseDecl() ast.Decl {
        return p.parseGenDecl(p.tok, f)
 }
 
-func (p *parser) parseDeclList() (list []ast.Decl) {
-       if p.trace {
-               defer un(trace(p, "DeclList"))
-       }
-
-       for p.tok != token.EOF {
-               list = append(list, p.parseDecl())
-       }
-
-       return
-}
-
 // ----------------------------------------------------------------------------
 // Source files
 
index f602db8896db5e02e6fe962a98d0f3a656f21fd4..a3ee8525de29b931e73594c9570f3b91684e2139 100644 (file)
@@ -54,7 +54,7 @@ func TestParseIllegalInputs(t *testing.T) {
        }
 }
 
-var validPrograms = []interface{}{
+var validPrograms = []string{
        "package p\n",
        `package p;`,
        `package p; import "fmt"; func f() { fmt.Println("Hello, World!") };`,
@@ -136,6 +136,32 @@ func TestParse4(t *testing.T) {
        }
 }
 
+func TestParseExpr(t *testing.T) {
+       // just kicking the tires:
+       // a valid expression
+       src := "a + b"
+       x, err := ParseExpr(src)
+       if err != nil {
+               t.Errorf("ParseExpr(%s): %v", src, err)
+       }
+       // sanity check
+       if _, ok := x.(*ast.BinaryExpr); !ok {
+               t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x)
+       }
+
+       // an invalid expression
+       src = "a + *"
+       _, err = ParseExpr(src)
+       if err == nil {
+               t.Errorf("ParseExpr(%s): %v", src, err)
+       }
+
+       // it must not crash
+       for _, src := range validPrograms {
+               ParseExpr(src)
+       }
+}
+
 func TestColonEqualsScope(t *testing.T) {
        f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
        if err != nil {