OSDN Git Service

libgo: Update to weekly.2012-01-15.
[pf3gnuchains/gcc-fork.git] / libgo / go / go / parser / interface.go
index be11f46..2ce3df8 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
 }