From 3f42f44227db4bdcfd5848c5089ab96795ffc06e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 31 Mar 2009 13:28:01 -0700 Subject: [PATCH] - incorporation of suggestions by rsc R=rsc OCL=26959 CL=26959 --- usr/gri/pretty/compilation.go | 24 ++++----- 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 c068ce8409..b6b95f30bc 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 8e77ff7cfb..e60893abfd 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; } -- 2.48.1