Commit e48d8fe0 authored by Robert Griesemer's avatar Robert Griesemer

update remaining files to match new scanner/parser interface

and use shared error handling infrastructure

R=rsc
DELTA=109  (3 added, 86 deleted, 20 changed)
OCL=31600
CL=31605
parent 5945b251
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"ebnf"; "ebnf";
"flag"; "flag";
"fmt"; "fmt";
"go/scanner";
"io"; "io";
"os"; "os";
"path"; "path";
...@@ -70,23 +71,6 @@ func extractEBNF(src []byte) []byte { ...@@ -70,23 +71,6 @@ func extractEBNF(src []byte) []byte {
} }
// TODO(gri) This is the same code for reportError as in gofmt.
// Should factor this out as part of some parsing framework
// that could also deal with reading various input sources.
func reportError(filename string, err os.Error) {
if errors, ok := err.(ebnf.ErrorList); ok {
sort.Sort(errors);
for _, e := range errors {
fmt.Fprintf(os.Stderr, "%s:%v\n", filename, e);
}
} else {
fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err);
}
os.Exit(1);
}
func main() { func main() {
flag.Parse(); flag.Parse();
...@@ -102,19 +86,19 @@ func main() { ...@@ -102,19 +86,19 @@ func main() {
src, err := io.ReadFile(filename); src, err := io.ReadFile(filename);
if err != nil { if err != nil {
reportError(filename, err); scanner.PrintError(os.Stderr, err);
} }
if path.Ext(filename) == ".html" { if path.Ext(filename) == ".html" {
src = extractEBNF(src); src = extractEBNF(src);
} }
grammar, err := ebnf.Parse(src); grammar, err := ebnf.Parse(filename, src);
if err != nil { if err != nil {
reportError(filename, err); scanner.PrintError(os.Stderr, err);
} }
if err = ebnf.Verify(grammar, *start); err != nil { if err = ebnf.Verify(grammar, *start); err != nil {
reportError(filename, err); scanner.PrintError(os.Stderr, err);
} }
} }
...@@ -225,7 +225,7 @@ func PackageImports(file string) (pkg string, imports []string, err1 os.Error) { ...@@ -225,7 +225,7 @@ func PackageImports(file string) (pkg string, imports []string, err1 os.Error) {
return "", nil, err return "", nil, err
} }
prog, err := parser.Parse(f, parser.ImportsOnly); prog, err := parser.Parse(file, f, parser.ImportsOnly);
if err != nil { if err != nil {
return "", nil, err; return "", nil, err;
} }
......
...@@ -35,6 +35,7 @@ import ( ...@@ -35,6 +35,7 @@ import (
"go/doc"; "go/doc";
"go/parser"; "go/parser";
"go/printer"; "go/printer";
"go/scanner";
"go/token"; "go/token";
"http"; "http";
"io"; "io";
...@@ -166,10 +167,10 @@ func parse(path string, mode uint) (*ast.Program, *parseErrors) { ...@@ -166,10 +167,10 @@ func parse(path string, mode uint) (*ast.Program, *parseErrors) {
return nil, &parseErrors{path, errs, nil}; return nil, &parseErrors{path, errs, nil};
} }
prog, err := parser.Parse(src, mode); prog, err := parser.Parse(path, src, mode);
if err != nil { if err != nil {
// sort and convert error list // sort and convert error list
if errors, ok := err.(parser.ErrorList); ok { if errors, ok := err.(scanner.ErrorList); ok {
sort.Sort(errors); sort.Sort(errors);
errs := make([]parseError, len(errors) + 1); // +1 for final fragment of source errs := make([]parseError, len(errors) + 1); // +1 for final fragment of source
offs := 0; offs := 0;
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"go/ast"; "go/ast";
"go/parser"; "go/parser";
"go/printer"; "go/printer";
"go/scanner";
"io"; "io";
"os"; "os";
"sort"; "sort";
...@@ -84,16 +85,9 @@ func main() { ...@@ -84,16 +85,9 @@ func main() {
os.Exit(1); os.Exit(1);
} }
prog, err := parser.Parse(src, parserMode()); prog, err := parser.Parse(filename, src, parserMode());
if err != nil { if err != nil {
if errors, ok := err.(parser.ErrorList); ok { scanner.PrintError(os.Stderr, err);
sort.Sort(errors);
for _, e := range errors {
fmt.Fprintf(os.Stderr, "%s:%v\n", filename, e);
}
} else {
fmt.Fprintf(os.Stderr, "%s: %v\n", filename, err);
}
os.Exit(1); os.Exit(1);
} }
...@@ -102,7 +96,7 @@ func main() { ...@@ -102,7 +96,7 @@ func main() {
ast.FilterExports(prog); // ignore result ast.FilterExports(prog); // ignore result
} }
w := makeTabwriter(os.Stdout); w := makeTabwriter(os.Stdout);
printer.Fprint(w, prog, printerMode()); printer.Fprint(w, prog, printerMode()); // ignore errors
w.Flush(); w.Flush();
} }
} }
...@@ -22,7 +22,7 @@ go/ast.install: go/token.install unicode.install utf8.install ...@@ -22,7 +22,7 @@ go/ast.install: go/token.install unicode.install utf8.install
go/doc.install: container/vector.install fmt.install go/ast.install go/token.install io.install once.install regexp.install sort.install strings.install template.install go/doc.install: container/vector.install fmt.install go/ast.install go/token.install io.install once.install regexp.install sort.install strings.install template.install
go/parser.install: bytes.install container/vector.install fmt.install go/ast.install go/scanner.install go/token.install io.install os.install strings.install go/parser.install: bytes.install container/vector.install fmt.install go/ast.install go/scanner.install go/token.install io.install os.install strings.install
go/printer.install: fmt.install go/ast.install go/token.install io.install os.install reflect.install strings.install go/printer.install: fmt.install go/ast.install go/token.install io.install os.install reflect.install strings.install
go/scanner.install: go/token.install strconv.install unicode.install utf8.install go/scanner.install: bytes.install container/vector.install fmt.install go/token.install io.install os.install sort.install strconv.install unicode.install utf8.install
go/token.install: strconv.install go/token.install: strconv.install
gob.install: fmt.install io.install math.install os.install reflect.install strings.install sync.install unicode.install gob.install: fmt.install io.install math.install os.install reflect.install strings.install sync.install unicode.install
hash.install: io.install hash.install: io.install
......
...@@ -14,7 +14,7 @@ import ( ...@@ -14,7 +14,7 @@ import (
func parse(t *testing.T, form string, fmap FormatterMap) Format { func parse(t *testing.T, form string, fmap FormatterMap) Format {
f, err := Parse(strings.Bytes(form), fmap); f, err := Parse("", strings.Bytes(form), fmap);
if err != nil { if err != nil {
t.Errorf("Parse(%s): %v", form, err); t.Errorf("Parse(%s): %v", form, err);
return nil; return nil;
......
...@@ -15,53 +15,11 @@ import ( ...@@ -15,53 +15,11 @@ import (
"strings"; "strings";
) )
// ----------------------------------------------------------------------------
// Error handling
// Error describes an individual error. The position Pos, if valid,
// indicates the format source position the error relates to. The
// error is specified with the Msg string.
//
type Error struct {
Pos token.Position;
Msg string;
}
func (e *Error) String() string {
pos := "";
if e.Pos.IsValid() {
pos = fmt.Sprintf("%d:%d: ", e.Pos.Line, e.Pos.Column);
}
return pos + e.Msg;
}
// An ErrorList is a list of errors encountered during parsing.
type ErrorList []*Error
// ErrorList implements SortInterface and the os.Error interface.
func (p ErrorList) Len() int { return len(p); }
func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i]; }
func (p ErrorList) Less(i, j int) bool { return p[i].Pos.Offset < p[j].Pos.Offset; }
func (p ErrorList) String() string {
switch len(p) {
case 0: return "unspecified error";
case 1: return p[0].String();
}
return fmt.Sprintf("%s (and %d more errors)", p[0].String(), len(p) - 1);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Parsing // Parsing
type parser struct { type parser struct {
errors vector.Vector; scanner.ErrorVector;
scanner scanner.Scanner; scanner scanner.Scanner;
pos token.Position; // token position pos token.Position; // token position
tok token.Token; // one token look-ahead tok token.Token; // one token look-ahead
...@@ -83,26 +41,15 @@ func (p *parser) next() { ...@@ -83,26 +41,15 @@ func (p *parser) next() {
} }
func (p *parser) init(src []byte) { func (p *parser) init(filename string, src []byte) {
p.errors.Init(0); p.ErrorVector.Init();
p.scanner.Init(src, p, scanner.AllowIllegalChars); // return '@' as token.ILLEGAL w/o error message p.scanner.Init(filename, src, p, scanner.AllowIllegalChars); // return '@' as token.ILLEGAL w/o error message
p.next(); // initializes pos, tok, lit p.next(); // initializes pos, tok, lit
p.packs = make(map [string] string); p.packs = make(map [string] string);
p.rules = make(map [string] expr); p.rules = make(map [string] expr);
} }
// The parser implements scanner.Error.
func (p *parser) Error(pos token.Position, msg string) {
// Don't collect errors that are on the same line as the previous error
// in the hope to reduce the number of spurious errors due to incorrect
// parser synchronization.
if p.errors.Len() == 0 || p.errors.Last().(*Error).Pos.Line != pos.Line {
p.errors.Push(&Error{pos, msg});
}
}
func (p *parser) errorExpected(pos token.Position, msg string) { func (p *parser) errorExpected(pos token.Position, msg string) {
msg = "expected " + msg; msg = "expected " + msg;
if pos.Offset == p.pos.Offset { if pos.Offset == p.pos.Offset {
...@@ -416,10 +363,10 @@ func remap(p *parser, name string) string { ...@@ -416,10 +363,10 @@ func remap(p *parser, name string) string {
// there are no errors, the result is a Format and the error is nil. // there are no errors, the result is a Format and the error is nil.
// Otherwise the format is nil and a non-empty ErrorList is returned. // Otherwise the format is nil and a non-empty ErrorList is returned.
// //
func Parse(src []byte, fmap FormatterMap) (Format, os.Error) { func Parse(filename string, src []byte, fmap FormatterMap) (Format, os.Error) {
// parse source // parse source
var p parser; var p parser;
p.init(src); p.init(filename, src);
p.parseFormat(); p.parseFormat();
// add custom formatters, if any // add custom formatters, if any
...@@ -433,14 +380,5 @@ func Parse(src []byte, fmap FormatterMap) (Format, os.Error) { ...@@ -433,14 +380,5 @@ func Parse(src []byte, fmap FormatterMap) (Format, os.Error) {
} }
} }
// convert errors list, if any return p.rules, p.GetError(scanner.NoMultiples);
if p.errors.Len() > 0 {
errors := make(ErrorList, p.errors.Len());
for i := 0; i < p.errors.Len(); i++ {
errors[i] = p.errors.At(i).(*Error);
}
return nil, errors;
}
return p.rules, nil;
} }
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