Commit 3f42f442 authored by Robert Griesemer's avatar Robert Griesemer

- incorporation of suggestions by rsc

R=rsc
OCL=26959
CL=26959
parent dc5b4678
...@@ -49,16 +49,14 @@ func (list ErrorList) Swap(i, j int) { list[i], list[j] = list[j], list[i]; } ...@@ -49,16 +49,14 @@ func (list ErrorList) Swap(i, j int) { list[i], list[j] = list[j], list[i]; }
type errorHandler struct { type errorHandler struct {
filename string; filename string;
src []byte;
columns bool; columns bool;
errline int; errline int;
errors vector.Vector; 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.filename = filename;
h.src = src;
h.columns = columns; h.columns = columns;
h.errors.Init(0); h.errors.Init(0);
} }
...@@ -84,26 +82,24 @@ func (h *errorHandler) Error(pos token.Position, msg string) { ...@@ -84,26 +82,24 @@ func (h *errorHandler) Error(pos token.Position, msg string) {
} }
func Compile(src_file string, flags *Flags) (*ast.Package, ErrorList) { func Compile(filename string, flags *Flags) (*ast.Package, ErrorList) {
src, ok := Platform.ReadSourceFile(src_file); src, os_err := os.Open(filename, os.O_RDONLY, 0);
if !ok { defer src.Close();
print("cannot open ", src_file, "\n"); if os_err != nil {
fmt.Printf("cannot open %s (%s)\n", filename, os_err.String());
return nil, nil; return nil, nil;
} }
var err errorHandler; var err errorHandler;
err.Init(src_file, src, flags.Columns); err.Init(filename, flags.Columns);
var scanner scanner.Scanner; mode := parser.ParseComments;
scanner.Init(src, &err, true);
mode := uint(0);
if flags.Verbose { if flags.Verbose {
mode |= parser.Trace; 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); TypeChecker.CheckProgram(&err, prog);
} }
......
...@@ -10,24 +10,15 @@ ...@@ -10,24 +10,15 @@
package parser package parser
import ( import (
"ast";
"fmt"; "fmt";
"vector"; "io";
"scanner";
"token"; "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. // An implementation of an ErrorHandler may be provided to the parser.
// If a syntax error is encountered and a handler was installed, Error // If a syntax error is encountered and a handler was installed, Error
// is called with a position and an error message. The position points // is called with a position and an error message. The position points
...@@ -45,7 +36,7 @@ type interval struct { ...@@ -45,7 +36,7 @@ type interval struct {
// The parser structure holds the parser's internal state. // The parser structure holds the parser's internal state.
type parser struct { type parser struct {
scanner Scanner; scanner scanner.Scanner;
err ErrorHandler; // nil if no handler installed err ErrorHandler; // nil if no handler installed
errorCount int; errorCount int;
...@@ -81,11 +72,10 @@ func (p *parser) printTrace(a ...) { ...@@ -81,11 +72,10 @@ func (p *parser) printTrace(a ...) {
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "; ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ";
const n = uint(len(dots)); const n = uint(len(dots));
fmt.Printf("%5d:%3d: ", p.pos.Line, p.pos.Column); fmt.Printf("%5d:%3d: ", p.pos.Line, p.pos.Column);
i := 2*p.indent; i := 2*p.indent;
for ; i > n; i -= n { for ; i > n; i -= n {
fmt.Print(dots[0 : i%n]); fmt.Print(dots);
} }
fmt.Print(dots[0 : i]); fmt.Print(dots[0 : i]);
fmt.Println(a); fmt.Println(a);
...@@ -1847,13 +1837,14 @@ func (p *parser) parseDeclaration() ast.Decl { ...@@ -1847,13 +1837,14 @@ func (p *parser) parseDeclaration() ast.Decl {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Packages // Packages
// A set of flags (or 0) must be provided via the mode parameter to // The mode parameter to the Parse function is a set of flags (or 0).
// the Parse function. They control the amount of source code parsed // They control the amount of source code parsed and other optional
// and other optional parser functionality. // parser functionality.
// //
const ( const (
PackageClauseOnly = 1 << iota; // parsing stops after package clause PackageClauseOnly uint = 1 << iota; // parsing stops after package clause
ImportsOnly; // parsing stops after import declarations ImportsOnly; // parsing stops after import declarations
ParseComments; // parse comments and add them to AST
Trace; // print a trace of parsed productions Trace; // print a trace of parsed productions
) )
...@@ -1914,29 +1905,57 @@ func (p *parser) parsePackage() *ast.Package { ...@@ -1914,29 +1905,57 @@ func (p *parser) parsePackage() *ast.Package {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Parsing of entire programs. // Parsing of entire programs.
// Parse invokes the Go parser. It calls the scanner's Scan method repeatedly func readSource(src interface{}, err ErrorHandler) []byte {
// to obtain a token sequence which is parsed according to Go syntax. If an errmsg := "could not read input src";
// error handler is provided (err != nil), it is invoked for each syntax error
// encountered. 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 // The program source src may be provided in a variety of formats. At the
// error count is 0, the result is the correct AST for the token sequence // moment the following types are supported: string, []byte, and io.Read.
// 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 mode parameter controls the amount of source text parsed and other // The ErrorHandler err, if not nil, is invoked if src cannot be read and
// optional parser functionality. // 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 // Parse returns an AST and the boolean value true if no errors occured;
// a legal token sequence. To be sure there are no syntax errors in the // it returns a partial AST (or nil if the source couldn't be read) and
// source (and not just the token sequence corresponding to the source) // the boolean value false to indicate failure.
// both the parser and scanner error count must be 0. //
// 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 // initialize parser state
var p parser; var p parser;
p.scanner = scanner; p.scanner.Init(data, err, mode & ParseComments != 0);
p.err = err; p.err = err;
p.mode = mode; p.mode = mode;
p.trace = mode & Trace != 0; // for convenience (p.trace is used frequently) 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) { ...@@ -1944,6 +1963,6 @@ func Parse(scanner Scanner, err ErrorHandler, mode uint) (*ast.Package, int) {
p.next(); p.next();
// parse program // parse program
pak := p.parsePackage(); prog := p.parsePackage();
return pak, p.errorCount; return prog, p.scanner.ErrorCount == 0 && p.errorCount == 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment