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]; }
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);
}
......
......@@ -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.
//
func Parse(scanner Scanner, err ErrorHandler, mode uint) (*ast.Package, int) {
// 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(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;
}
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