diff options
| author | Robert Griesemer <gri@golang.org> | 2009-03-31 13:28:01 -0700 | 
|---|---|---|
| committer | Robert Griesemer <gri@golang.org> | 2009-03-31 13:28:01 -0700 | 
| commit | 8cc192978b611a277658bb790157e28b09ec4477 (patch) | |
| tree | 1b0daa982e25d4a719b8cf0c6d0278ab278f7b2c | |
| parent | 826b1ac7ec294deccb021738fccc381f63d68ffb (diff) | |
| download | golang-8cc192978b611a277658bb790157e28b09ec4477.tar.gz | |
- incorporation of suggestions by rsc
R=rsc
OCL=26959
CL=26959
| -rw-r--r-- | usr/gri/pretty/compilation.go | 24 | ||||
| -rw-r--r-- | usr/gri/pretty/parser.go | 97 | 
2 files changed, 68 insertions, 53 deletions
| diff --git a/usr/gri/pretty/compilation.go b/usr/gri/pretty/compilation.go index c068ce840..b6b95f30b 100644 --- a/usr/gri/pretty/compilation.go +++ b/usr/gri/pretty/compilation.go @@ -49,16 +49,14 @@ func (list ErrorList) Swap(i, j int) { list[i], list[j] = list[j], list[i]; }  type errorHandler struct {  	filename string; -	src []byte;  	columns bool;  	errline int;  	errors vector.Vector;  } -func (h *errorHandler) Init(filename string, src []byte, columns bool) { +func (h *errorHandler) Init(filename string, columns bool) {  	h.filename = filename; -	h.src = src;  	h.columns = columns;  	h.errors.Init(0);  } @@ -84,26 +82,24 @@ func (h *errorHandler) Error(pos token.Position, msg string) {  } -func Compile(src_file string, flags *Flags) (*ast.Package, ErrorList) { -	src, ok := Platform.ReadSourceFile(src_file); -	if !ok { -		print("cannot open ", src_file, "\n"); +func Compile(filename string, flags *Flags) (*ast.Package, ErrorList) { +	src, os_err := os.Open(filename, os.O_RDONLY, 0); +	defer src.Close(); +	if os_err != nil { +		fmt.Printf("cannot open %s (%s)\n", filename, os_err.String());  		return nil, nil;  	}  	var err errorHandler; -	err.Init(src_file, src, flags.Columns); +	err.Init(filename, flags.Columns); -	var scanner scanner.Scanner; -	scanner.Init(src, &err, true); - -	mode := uint(0); +	mode := parser.ParseComments;  	if flags.Verbose {  		mode |= parser.Trace;  	} -	prog, nerrs := parser.Parse(&scanner, &err, mode); +	prog, ok2 := parser.Parse(src, &err, mode); -	if err.errors.Len() == 0 { +	if ok2 {  		TypeChecker.CheckProgram(&err, prog);  	} diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index 8e77ff7cf..e60893abf 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -10,24 +10,15 @@  package parser  import ( +	"ast";  	"fmt"; -	"vector"; +	"io"; +	"scanner";  	"token"; -	"ast"; +	"vector";  ) -// An implementation of a Scanner must be provided to the Parser. -// The parser calls Scan() repeatedly until token.EOF is returned. -// Scan must return the current token position pos, the token value -// tok, and the corresponding token literal string lit; lit can be -// undefined/nil unless the token is a literal (tok.IsLiteral() == true). -// -type Scanner interface { -	Scan() (pos token.Position, tok token.Token, lit []byte); -} - -  // An implementation of an ErrorHandler may be provided to the parser.  // If a syntax error is encountered and a handler was installed, Error  // is called with a position and an error message. The position points @@ -45,7 +36,7 @@ type interval struct {  // The parser structure holds the parser's internal state.  type parser struct { -	scanner Scanner; +	scanner scanner.Scanner;  	err ErrorHandler;  // nil if no handler installed  	errorCount int; @@ -81,11 +72,10 @@ func (p *parser) printTrace(a ...) {  		". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "  		". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ";  	const n = uint(len(dots)); -  	fmt.Printf("%5d:%3d: ", p.pos.Line, p.pos.Column);  	i := 2*p.indent;  	for ; i > n; i -= n { -		fmt.Print(dots[0 : i%n]); +		fmt.Print(dots);  	}  	fmt.Print(dots[0 : i]);  	fmt.Println(a); @@ -1847,13 +1837,14 @@ func (p *parser) parseDeclaration() ast.Decl {  // ----------------------------------------------------------------------------  // Packages -// A set of flags (or 0) must be provided via the mode parameter to -// the Parse function. They control the amount of source code parsed -// and other optional parser functionality. +// The mode parameter to the Parse function is a set of flags (or 0). +// They control the amount of source code parsed and other optional +// parser functionality.  //  const ( -	PackageClauseOnly = 1 << iota;  // parsing stops after package clause +	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  ) @@ -1914,29 +1905,57 @@ func (p *parser) parsePackage() *ast.Package {  // ----------------------------------------------------------------------------  // Parsing of entire programs. -// Parse invokes the Go parser. It calls the scanner's Scan method repeatedly -// to obtain a token sequence which is parsed according to Go syntax. If an -// error handler is provided (err != nil), it is invoked for each syntax error -// encountered. +func readSource(src interface{}, err ErrorHandler) []byte { +	errmsg := "could not read input src"; + +	switch s := src.(type) { +	case string: +		return io.StringBytes(s); +	case []byte: +		return s; +	case *io.ByteBuffer: +		// is io.Read, but src is already available in []byte form +		if s != nil { +			return s.Data(); +		} +	case io.Read: +		var buf io.ByteBuffer; +		n, os_err := io.Copy(s, &buf); +		if os_err == nil { +			return buf.Data(); +		} +		errmsg = os_err.String(); +	} + +	if err != nil { +		err.Error(noPos, errmsg); +	} +	return nil; +} + + +// Parse parses a Go program.  // -// Parse returns an AST and the number of syntax errors encountered. If the -// error count is 0, the result is the correct AST for the token sequence -// returned by the scanner (*). If the error count is > 0, the AST may only -// be constructed partially, with ast.BadX nodes representing the fragments -// of source code that contained syntax errors. +// The program source src may be provided in a variety of formats. At the +// moment the following types are supported: string, []byte, and io.Read.  // -// The mode parameter controls the amount of source text parsed and other -// optional parser functionality. +// The ErrorHandler err, if not nil, is invoked if src cannot be read and +// for each syntax error found. The mode parameter controls the amount of +// source text parsed and other optional parser functionality.  // -// (*) Note that a scanner may find lexical syntax errors but still return -//     a legal token sequence. To be sure there are no syntax errors in the -//     source (and not just the token sequence corresponding to the source) -//     both the parser and scanner error count must be 0. +// Parse returns an AST and the boolean value true if no errors occured; +// it returns a partial AST (or nil if the source couldn't be read) and +// the boolean value false to indicate failure. +//  +// If syntax errors were found, the AST may only be constructed partially, +// with ast.BadX nodes representing the fragments of erroneous source code.  // -func Parse(scanner Scanner, err ErrorHandler, mode uint) (*ast.Package, int) { +func Parse(src interface{}, err ErrorHandler, mode uint) (*ast.Package, bool) { +	data := readSource(src, err); +  	// initialize parser state  	var p parser; -	p.scanner = scanner; +	p.scanner.Init(data, err, mode & ParseComments != 0);  	p.err = err;  	p.mode = mode;  	p.trace = mode & Trace != 0;  // for convenience (p.trace is used frequently) @@ -1944,6 +1963,6 @@ func Parse(scanner Scanner, err ErrorHandler, mode uint) (*ast.Package, int) {  	p.next();  	// parse program -	pak := p.parsePackage(); -	return pak, p.errorCount; +	prog := p.parsePackage(); +	return prog, p.scanner.ErrorCount == 0 && p.errorCount == 0;  } | 
