]> Cypherpunks repositories - gostls13.git/commitdiff
- incorporation of suggestions by rsc
authorRobert Griesemer <gri@golang.org>
Tue, 31 Mar 2009 20:28:01 +0000 (13:28 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 31 Mar 2009 20:28:01 +0000 (13:28 -0700)
R=rsc
OCL=26959
CL=26959

usr/gri/pretty/compilation.go
usr/gri/pretty/parser.go

index c068ce8409347176082045dc3bb7e719f65d412b..b6b95f30bcc00ee70589f83261efc341fb9aab04 100644 (file)
@@ -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);
        }
        
index 8e77ff7cfb4543f03f809748405206299161f243..e60893abfdb307c6c0d7efad074e07027f81155c 100644 (file)
 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;
 }