1
0
mirror of https://github.com/golang/go synced 2024-11-25 08:07:57 -07:00

Simplified parser interface.

R=rsc, r
CC=golang-dev, rog
https://golang.org/cl/183116
This commit is contained in:
Robert Griesemer 2010-01-04 17:26:01 -08:00
parent a0ee18bdd5
commit 50442290bb
4 changed files with 39 additions and 54 deletions

View File

@ -59,7 +59,7 @@ type FuncType struct {
func openProg(name string, p *Prog) {
var err os.Error
p.AST, err = parser.ParsePkgFile("", name, parser.ParseComments)
p.AST, err = parser.ParseFile(name, nil, parser.ParseComments)
if err != nil {
if list, ok := err.(scanner.ErrorList); ok {
// If err is a scanner.ErrorList, its String will print just

View File

@ -1021,10 +1021,18 @@ func (h *httpHandler) getPageInfo(path string) PageInfo {
}
// get package AST
pkg, err := parser.ParsePackage(dirname, filter, parser.ParseComments)
pkgs, err := parser.ParseDir(dirname, filter, parser.ParseComments)
if err != nil {
// TODO: parse errors should be shown instead of an empty directory
log.Stderrf("parser.parsePackage: %s", err)
// TODO: errors should be shown instead of an empty directory
log.Stderrf("parser.parseDir: %s", err)
}
if len(pkgs) != 1 {
// TODO: should handle multiple packages
log.Stderrf("parser.parseDir: found %d packages", len(pkgs))
}
var pkg *ast.Package
for _, pkg = range pkgs {
break // take the first package found
}
// compute package documentation

View File

@ -8,7 +8,6 @@ package parser
import (
"bytes"
"fmt"
"go/ast"
"go/scanner"
"io"
@ -132,41 +131,16 @@ func ParseFile(filename string, src interface{}, mode uint) (*ast.File, os.Error
}
// ParsePkgFile parses the file specified by filename and returns the
// corresponding AST. If the file cannot be read, has syntax errors, or
// does not belong to the package (i.e., pkgname != "" and the package
// name in the file doesn't match pkkname), an error is returned.
// ParseDir calls ParseFile for the files in the directory specified by path and
// returns a map of package name -> package AST with all the packages found. If
// filter != nil, only the files with os.Dir entries passing through the filter
// are considered. The mode bits are passed to ParseFile unchanged.
//
func ParsePkgFile(pkgname, filename string, mode uint) (*ast.File, os.Error) {
src, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
if pkgname != "" {
prog, err := ParseFile(filename, src, PackageClauseOnly)
if err != nil {
return nil, err
}
if prog.Name.Value != pkgname {
return nil, os.NewError(fmt.Sprintf("multiple packages found: %s, %s", prog.Name.Value, pkgname))
}
if mode == PackageClauseOnly {
return prog, nil
}
}
return ParseFile(filename, src, mode)
}
// ParsePackage parses all files in the directory specified by path and
// returns an AST representing the package found. The set of files may be
// restricted by providing a non-nil filter function; only the files with
// os.Dir entries passing through the filter are considered.
// If ParsePackage does not find exactly one package, it returns an error.
// If the directory couldn't be read, a nil map and the respective error are
// returned. If a parse error occured, a non-nil but incomplete map and the
// error are returned.
//
func ParsePackage(path string, filter func(*os.Dir) bool, mode uint) (*ast.Package, os.Error) {
func ParseDir(path string, filter func(*os.Dir) bool, mode uint) (map[string]*ast.Package, os.Error) {
fd, err := os.Open(path, os.O_RDONLY, 0)
if err != nil {
return nil, err
@ -178,25 +152,23 @@ func ParsePackage(path string, filter func(*os.Dir) bool, mode uint) (*ast.Packa
return nil, err
}
name := ""
files := make(map[string]*ast.File)
pkgs := make(map[string]*ast.Package)
for i := 0; i < len(list); i++ {
entry := &list[i]
if filter == nil || filter(entry) {
src, err := ParsePkgFile(name, pathutil.Join(path, entry.Name), mode)
src, err := ParseFile(pathutil.Join(path, entry.Name), nil, mode)
if err != nil {
return nil, err
return pkgs, err
}
files[entry.Name] = src
if name == "" {
name = src.Name.Value
name := src.Name.Value
pkg, found := pkgs[name]
if !found {
pkg = &ast.Package{name, path, make(map[string]*ast.File)}
pkgs[name] = pkg
}
pkg.Files[entry.Name] = src
}
}
if len(files) == 0 {
return nil, os.NewError(path + ": no package found")
}
return &ast.Package{name, path, files}, nil
return pkgs, nil
}

View File

@ -78,12 +78,17 @@ func dirFilter(d *os.Dir) bool { return nameFilter(d.Name) }
func TestParse4(t *testing.T) {
path := "."
pkg, err := ParsePackage(path, dirFilter, 0)
pkgs, err := ParseDir(path, dirFilter, 0)
if err != nil {
t.Fatalf("ParsePackage(%s): %v", path, err)
t.Fatalf("ParseDir(%s): %v", path, err)
}
if pkg.Name != "parser" {
t.Errorf("incorrect package name: %s", pkg.Name)
if len(pkgs) != 1 {
t.Errorf("incorrect number of packages: %d", len(pkgs))
}
pkg, found := pkgs["parser"]
if pkg == nil || !found {
t.Errorf(`package "parser" not found`)
return
}
for filename, _ := range pkg.Files {
if !nameFilter(filename) {