]> Cypherpunks repositories - gostls13.git/commitdiff
- use new scanner error handling code
authorRobert Griesemer <gri@golang.org>
Tue, 14 Jul 2009 17:45:43 +0000 (10:45 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 14 Jul 2009 17:45:43 +0000 (10:45 -0700)
R=rsc
DELTA=109  (0 added, 87 deleted, 22 changed)
OCL=31573
CL=31603

src/pkg/ebnf/ebnf.go
src/pkg/ebnf/ebnf_test.go
src/pkg/ebnf/parser.go

index c54f0f8dae109ac4c7e8b77af78bd15eec471ad9..368a3c8123747c61eba0bc57202e5b3b20e16e57 100644 (file)
@@ -119,58 +119,6 @@ func (p *Production) Pos() token.Position {
 }
 
 
-// ----------------------------------------------------------------------------
-// Error handling
-
-// TODO(gri) This is the same code as in datafmt and go/parser.
-//           Should factor this out as part of some parsing framework
-//           that could also deal with reading various input sources.
-
-// 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;
-}
-
-
-// String returns the error message. If the error contains (line, column)
-// position information, it starts with "line:column: ", otherwise it
-// starts with a blank " ". 
-//
-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);
-}
-
-
 // ----------------------------------------------------------------------------
 // Grammar verification
 
@@ -181,30 +129,13 @@ func isLexical(name string) bool {
 
 
 type verifier struct {
-       errors vector.Vector;
+       scanner.ErrorVector;
        worklist vector.Vector;
        reached Grammar;  // set of productions reached from (and including) the root production
        grammar Grammar;
 }
 
 
-func (v *verifier) error(pos token.Position, msg string) {
-       v.errors.Push(&Error{pos, msg});
-}
-
-
-func makeErrorList(v *vector.Vector) os.Error {
-       if v.Len() > 0 {
-               errors := make(ErrorList, v.Len());
-               for i := 0; i < v.Len(); i++ {
-                       errors[i] = v.At(i).(*Error);
-               }
-               return errors;
-       }
-       return nil;
-}
-
-
 func (v *verifier) push(prod *Production) {
        name := prod.Name.String;
        if _, found := v.reached[name]; !found {
@@ -217,7 +148,7 @@ func (v *verifier) push(prod *Production) {
 func (v *verifier) verifyChar(x *Token) int {
        s := x.String;
        if utf8.RuneCountInString(s) != 1 {
-               v.error(x.Pos(), "single char expected, found " + s);
+               v.Error(x.Pos(), "single char expected, found " + s);
                return 0;
        }
        ch, _ := utf8.DecodeRuneInString(s);
@@ -243,12 +174,12 @@ func (v *verifier) verifyExpr(expr Expression, lexical bool) {
                if prod, found := v.grammar[x.String]; found {
                        v.push(prod);
                } else {
-                       v.error(x.Pos(), "missing production " + x.String);
+                       v.Error(x.Pos(), "missing production " + x.String);
                }
                // within a lexical production references
                // to non-lexical productions are invalid
                if lexical && !isLexical(x.String) {
-                       v.error(x.Pos(), "reference to non-lexical production " + x.String);
+                       v.Error(x.Pos(), "reference to non-lexical production " + x.String);
                }
        case *Token:
                // nothing to do for now
@@ -256,7 +187,7 @@ func (v *verifier) verifyExpr(expr Expression, lexical bool) {
                i := v.verifyChar(x.Begin);
                j := v.verifyChar(x.End);
                if i >= j {
-                       v.error(x.Pos(), "decreasing character range");
+                       v.Error(x.Pos(), "decreasing character range");
                }
        case *Group:
                v.verifyExpr(x.Body, lexical);
@@ -275,12 +206,12 @@ func (v *verifier) verify(grammar Grammar, start string) {
        root, found := grammar[start];
        if !found {
                var noPos token.Position;
-               v.error(noPos, "no start production " + start);
+               v.Error(noPos, "no start production " + start);
                return;
        }
 
        // initialize verifier
-       v.errors.Init(0);
+       v.ErrorVector.Init();
        v.worklist.Init(0);
        v.reached = make(Grammar);
        v.grammar = grammar;
@@ -296,7 +227,7 @@ func (v *verifier) verify(grammar Grammar, start string) {
        if len(v.reached) < len(v.grammar) {
                for name, prod := range v.grammar {
                        if _, found := v.reached[name]; !found {
-                               v.error(prod.Pos(), name + " is unreachable");
+                               v.Error(prod.Pos(), name + " is unreachable");
                        }
                }
        }
@@ -311,5 +242,5 @@ func (v *verifier) verify(grammar Grammar, start string) {
 func Verify(grammar Grammar, start string) os.Error {
        var v verifier;
        v.verify(grammar, start);
-       return makeErrorList(&v.errors);
+       return v.GetError(scanner.Sorted);
 }
index ab4ea4c955f63a755d9ab1b2b057c5d9490e05e1..9bcb5d91f833a5fc71d573a607fbb08c53babd2c 100644 (file)
@@ -41,8 +41,8 @@ var grammars = []string {
 }
 
 
-func check(t *testing.T, src []byte) {
-       grammar, err := Parse(src);
+func check(t *testing.T, filename string, src []byte) {
+       grammar, err := Parse(filename, src);
        if err != nil {
                t.Errorf("Parse(%s) failed: %v", src, err);
        }
@@ -54,7 +54,7 @@ func check(t *testing.T, src []byte) {
 
 func TestGrammars(t *testing.T) {
        for _, src := range grammars {
-               check(t, strings.Bytes(src));
+               check(t, "", strings.Bytes(src));
        }
 }
 
@@ -70,6 +70,6 @@ func TestFiles(t *testing.T) {
                if err != nil {
                        t.Fatal(err);
                }
-               check(t, src);
+               check(t, filename, src);
        }
 }
index 84905d5fe51a8e3825563c1d5299881a43952d7d..e621c4d89d1721ed658677ba03ddd1fefb6bac38 100644 (file)
@@ -19,7 +19,7 @@ import (
 
 
 type parser struct {
-       errors vector.Vector;
+       scanner.ErrorVector;
        scanner scanner.Scanner;
        pos token.Position;  // token position
        tok token.Token;  // one token look-ahead
@@ -37,24 +37,6 @@ func (p *parser) next() {
 }
 
 
-func (p *parser) init(src []byte) {
-       p.errors.Init(0);
-       p.scanner.Init(src, p, 0);
-       p.next();  // initializes pos, tok, lit
-}
-
-
-// The parser implements scanner.Error.
-func (p *parser) Error(pos token.Position, msg string) {
-       // Do not collect errors that are on the same line as the previous
-       // error 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 {
@@ -207,10 +189,10 @@ func (p *parser) parseProduction() *Production {
 }
 
 
-func (p *parser) parse(src []byte) Grammar {
+func (p *parser) parse(filename string, src []byte) Grammar {
        // initialize parser
-       p.errors.Init(0);
-       p.scanner.Init(src, p, 0);
+       p.ErrorVector.Init();
+       p.scanner.Init(filename, src, p, 0);
        p.next();  // initializes pos, tok, lit
 
        grammar := make(Grammar);
@@ -233,8 +215,8 @@ func (p *parser) parse(src []byte) Grammar {
 // for incorrect syntax and if a production is declared
 // more than once.
 //
-func Parse(src []byte) (Grammar, os.Error) {
+func Parse(filename string, src []byte) (Grammar, os.Error) {
        var p parser;
-       grammar := p.parse(src);
-       return grammar, makeErrorList(&p.errors);
+       grammar := p.parse(filename, src);
+       return grammar, p.GetError(scanner.Sorted);
 }