diff --git a/src/cmd/ebnflint/ebnflint.go b/src/cmd/ebnflint/ebnflint.go index 7757085dd5e..253f286d16a 100644 --- a/src/cmd/ebnflint/ebnflint.go +++ b/src/cmd/ebnflint/ebnflint.go @@ -9,6 +9,7 @@ import ( "ebnf"; "flag"; "fmt"; + "go/scanner"; "io"; "os"; "path"; @@ -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() { flag.Parse(); @@ -102,19 +86,19 @@ func main() { src, err := io.ReadFile(filename); if err != nil { - reportError(filename, err); + scanner.PrintError(os.Stderr, err); } if path.Ext(filename) == ".html" { src = extractEBNF(src); } - grammar, err := ebnf.Parse(src); + grammar, err := ebnf.Parse(filename, src); if err != nil { - reportError(filename, err); + scanner.PrintError(os.Stderr, err); } if err = ebnf.Verify(grammar, *start); err != nil { - reportError(filename, err); + scanner.PrintError(os.Stderr, err); } } diff --git a/src/cmd/gobuild/util.go b/src/cmd/gobuild/util.go index fa8b382f205..10920d15282 100644 --- a/src/cmd/gobuild/util.go +++ b/src/cmd/gobuild/util.go @@ -225,7 +225,7 @@ func PackageImports(file string) (pkg string, imports []string, err1 os.Error) { return "", nil, err } - prog, err := parser.Parse(f, parser.ImportsOnly); + prog, err := parser.Parse(file, f, parser.ImportsOnly); if err != nil { return "", nil, err; } diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index ab95b519f35..3b3d4fabaeb 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -35,6 +35,7 @@ import ( "go/doc"; "go/parser"; "go/printer"; + "go/scanner"; "go/token"; "http"; "io"; @@ -166,10 +167,10 @@ func parse(path string, mode uint) (*ast.Program, *parseErrors) { return nil, &parseErrors{path, errs, nil}; } - prog, err := parser.Parse(src, mode); + prog, err := parser.Parse(path, src, mode); if err != nil { // sort and convert error list - if errors, ok := err.(parser.ErrorList); ok { + if errors, ok := err.(scanner.ErrorList); ok { sort.Sort(errors); errs := make([]parseError, len(errors) + 1); // +1 for final fragment of source offs := 0; diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 11d3cca1831..57c07d93e7e 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -10,6 +10,7 @@ import ( "go/ast"; "go/parser"; "go/printer"; + "go/scanner"; "io"; "os"; "sort"; @@ -84,16 +85,9 @@ func main() { os.Exit(1); } - prog, err := parser.Parse(src, parserMode()); + prog, err := parser.Parse(filename, src, parserMode()); if err != nil { - if errors, ok := err.(parser.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); - } + scanner.PrintError(os.Stderr, err); os.Exit(1); } @@ -102,7 +96,7 @@ func main() { ast.FilterExports(prog); // ignore result } w := makeTabwriter(os.Stdout); - printer.Fprint(w, prog, printerMode()); + printer.Fprint(w, prog, printerMode()); // ignore errors w.Flush(); } } diff --git a/src/pkg/Make.deps b/src/pkg/Make.deps index 12f0ef6e5fb..7bbb22eb664 100644 --- a/src/pkg/Make.deps +++ b/src/pkg/Make.deps @@ -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/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/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 gob.install: fmt.install io.install math.install os.install reflect.install strings.install sync.install unicode.install hash.install: io.install diff --git a/src/pkg/datafmt/datafmt_test.go b/src/pkg/datafmt/datafmt_test.go index 95354945193..8c3e002870f 100644 --- a/src/pkg/datafmt/datafmt_test.go +++ b/src/pkg/datafmt/datafmt_test.go @@ -14,7 +14,7 @@ import ( 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 { t.Errorf("Parse(%s): %v", form, err); return nil; diff --git a/src/pkg/datafmt/parser.go b/src/pkg/datafmt/parser.go index 17d4be982e0..ea34623dcca 100644 --- a/src/pkg/datafmt/parser.go +++ b/src/pkg/datafmt/parser.go @@ -15,53 +15,11 @@ import ( "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 type parser struct { - errors vector.Vector; + scanner.ErrorVector; scanner scanner.Scanner; pos token.Position; // token position tok token.Token; // one token look-ahead @@ -83,26 +41,15 @@ func (p *parser) next() { } -func (p *parser) init(src []byte) { - p.errors.Init(0); - p.scanner.Init(src, p, scanner.AllowIllegalChars); // return '@' as token.ILLEGAL w/o error message +func (p *parser) init(filename string, src []byte) { + p.ErrorVector.Init(); + p.scanner.Init(filename, src, p, scanner.AllowIllegalChars); // return '@' as token.ILLEGAL w/o error message p.next(); // initializes pos, tok, lit p.packs = make(map [string] string); 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) { msg = "expected " + msg; if pos.Offset == p.pos.Offset { @@ -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. // 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 var p parser; - p.init(src); + p.init(filename, src); p.parseFormat(); // add custom formatters, if any @@ -433,14 +380,5 @@ func Parse(src []byte, fmap FormatterMap) (Format, os.Error) { } } - // convert errors list, if any - 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; + return p.rules, p.GetError(scanner.NoMultiples); }