]> Cypherpunks repositories - gostls13.git/commitdiff
- improved error handling
authorRobert Griesemer <gri@golang.org>
Thu, 10 Jul 2008 21:42:33 +0000 (14:42 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 10 Jul 2008 21:42:33 +0000 (14:42 -0700)
SVN=126718

usr/gri/src/parser.go
usr/gri/src/scanner.go
usr/gri/src/test_parser.go
usr/gri/src/test_scanner.go

index b14c7780566357d0bf7cd8e54482c609b9083489..49b0f6ab2545f14ce163a8f20f59cd96ad58a96e 100644 (file)
@@ -4,7 +4,6 @@
 
 package Parser
 
-//import . "scanner"
 import Scanner "scanner"
 
 
@@ -63,8 +62,8 @@ func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
 }
 
 
-func (P *Parser) Error(msg string) {
-       P.S.Error(P.S.pos, msg);
+func (P *Parser) Error(pos int, msg string) {
+       P.S.Error(pos, msg);
        P.Next();  // make progress
 }
 
@@ -73,7 +72,7 @@ func (P *Parser) Expect(tok int) {
        if P.tok == tok {
                P.Next()
        } else {
-               P.Error("expected `" + Scanner.TokenName(tok) + "`, found `" + Scanner.TokenName(P.tok) + "`");
+               P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
        }
 }
 
@@ -130,7 +129,7 @@ func (P *Parser) ParseTypeName() {
 func (P *Parser) ParseType() {
        P.Trace("Type");
        if !P.TryType() {
-               P.Error("type expected");
+               P.Error(P.beg, "type expected");
        }
        P.Ecart();
 }
@@ -583,7 +582,7 @@ func (P *Parser) ParseControlFlowStat(tok int) {
 func (P *Parser) ParseStatement() {
        P.Trace("Statement");
        if !P.TryStatement() {
-               P.Error("statement expected");
+               P.Error(P.beg, "statement expected");
        }
        P.Ecart();
 }
@@ -874,7 +873,7 @@ func (P *Parser) ParseDeclaration() {
        case Scanner.EXPORT:
                P.ParseExportDecl();
        default:
-               P.Error("declaration expected");
+               P.Error(P.beg, "declaration expected");
        }
        if indent != P.indent {
                panic "imbalanced tracing code"
@@ -916,7 +915,7 @@ func (P *Parser) ParseOperand() {
        case Scanner.NEW:
                P.ParseNew();
        default:
-               P.Error("operand expected");
+               P.Error(P.beg, "operand expected");
        }
        P.Ecart();
 }
@@ -1004,9 +1003,9 @@ func (P *Parser) ParseUnaryExpr() {
 func Precedence(tok int) int {
        // TODO should use a map or array here for lookup
        switch tok {
-       case Scanner.COR:
+       case Scanner.LOR:
                return 1;
-       case Scanner.CAND:
+       case Scanner.LAND:
                return 2;
        case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
                return 3;
index 7389cdac3fd40af466998909571f04e4eea4242c..94d8f1915187d5ebc649b862297fb09c69c7c795 100644 (file)
@@ -16,7 +16,7 @@ export
        SHL, SHR,
        ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN,
        AND_ASSIGN, OR_ASSIGN, XOR_ASSIGN, SHL_ASSIGN, SHR_ASSIGN,
-       CAND, COR,
+       LAND, LOR,
        BREAK, CASE, CHAN, CONST, CONTINUE, DEFAULT, ELSE, EXPORT, FALLTHROUGH, FALSE,
        FOR, FUNC, GO, GOTO, IF, IMPORT, INTERFACE, IOTA, MAP, NEW, NIL, PACKAGE, RANGE,
        RETURN, SELECT, STRUCT, SWITCH, TRUE, TYPE, VAR
@@ -81,8 +81,8 @@ const (
        SHL_ASSIGN;
        SHR_ASSIGN;
 
-       CAND;
-       COR;
+       LAND;
+       LOR;
        
        // keywords
        KEYWORDS_BEG;
@@ -184,8 +184,8 @@ func TokenName(tok int) string {
        case SHL_ASSIGN: return "<<=";
        case SHR_ASSIGN: return ">>=";
 
-       case CAND: return "&&";
-       case COR: return "||";
+       case LAND: return "&&";
+       case LOR: return "||";
 
        case BREAK: return "break";
        case CASE: return "case";
@@ -249,6 +249,10 @@ func digit_val (ch int) int {
 
 export Scanner
 type Scanner struct {
+       filename string;  // error reporting only
+       nerrors int;  // number of errors
+       errpos int;  // last error position
+       
        src string;
        pos int;  // current reading position
        ch int;  // one char look-ahead
@@ -389,17 +393,25 @@ func (S *Scanner) LineCol(pos int) (line, col int) {
 
 
 func (S *Scanner) Error(pos int, msg string) {
-       line, col := S.LineCol(pos);
-       print "error ", line, ":", col, ": ", msg, "\n";
+       const errdist = 10;
+       if pos > S.errpos + errdist || S.nerrors == 0 {
+               line, col := S.LineCol(pos);
+               print S.filename, ":", line, ":", col, ": ", msg, "\n";
+               S.nerrors++;
+               S.errpos = pos;
+       }
 }
 
 
-func (S *Scanner) Open (src string) {
+func (S *Scanner) Open (filename, src string) {
        if Keywords == nil {
                Init();
        }
 
-       //S.nerrors = 0;
+       S.filename = filename;
+       S.nerrors = 0;
+       S.errpos = 0;
+       
        S.src = src;
        S.pos = 0;
        S.Next();
@@ -438,19 +450,18 @@ func IntString(x, base int) string {
 }
 
 
-
 func CharString(ch int) string {
        s := string(ch);
        switch ch {
-       case '\a': s = "\\a";
-       case '\b': s = "\\b";
-       case '\f': s = "\\f";
-       case '\n': s = "\\n";
-       case '\r': s = "\\r";
-       case '\t': s = "\\t";
-       case '\v': s = "\\v";
-       case '\\': s = "\\";
-       case '\'': s = "\\'";
+       case '\a': s = `\a`;
+       case '\b': s = `\b`;
+       case '\f': s = `\f`;
+       case '\n': s = `\n`;
+       case '\r': s = `\r`;
+       case '\t': s = `\t`;
+       case '\v': s = `\v`;
+       case '\\': s = `\\`;
+       case '\'': s = `\'`;
        }
        return "'" + s + "' (U+" + IntString(ch, 16) + ")";
 }
@@ -708,11 +719,10 @@ func (S *Scanner) Select4 (tok0, tok1, ch2, tok2, tok3 int) int {
 func (S *Scanner) Scan () (tok, beg, end int) {
        S.SkipWhitespace();
        
-       tok = ILLEGAL;
-       beg = S.pos - 1;
-       end = beg;
-       
        ch := S.ch;
+       tok = ILLEGAL;
+       beg = S.chpos;
+
        switch {
        case is_letter(ch): tok = S.ScanIdentifier();
        case digit_val(ch) < 10: tok = S.ScanNumber(false);
@@ -755,12 +765,13 @@ func (S *Scanner) Scan () (tok, beg, end int) {
                case '>': tok = S.Select4(GTR, GEQ, '>', SHR, SHR_ASSIGN);
                case '=': tok = S.Select2(ASSIGN, EQL);
                case '!': tok = S.Select2(NOT, NEQ);
-               case '&': tok = S.Select3(AND, AND_ASSIGN, '&', CAND);
-               case '|': tok = S.Select3(OR, OR_ASSIGN, '|', COR);
+               case '&': tok = S.Select3(AND, AND_ASSIGN, '&', LAND);
+               case '|': tok = S.Select3(OR, OR_ASSIGN, '|', LOR);
+               default:
+                       S.Error(beg, "illegal character " + CharString(ch));
+                       tok = ILLEGAL;
                }
        }
        
-       end = S.pos - 1;  // TODO correct? (Unicode)
-       
-       return tok, beg, end;
+       return tok, beg, S.chpos;
 }
index 35d51b57aaf8ad604a39207bd6dd07826d58e239..78d8d87119cdb36f439b1f1104712f389d8e2fc8 100644 (file)
@@ -8,9 +8,9 @@ import Scanner "scanner"
 import Parser "parser"
 
 
-func Parse(src string, verbose int) {
+func Parse(filename, src string, verbose int) {
        S := new(Scanner.Scanner);
-       S.Open(src);
+       S.Open(filename, src);
        
        P := new(Parser.Parser);
        P.Open(S, verbose);
@@ -31,12 +31,10 @@ func main() {
                        continue;
                }
                
-               var src string;
-               var ok bool;
-               src, ok = sys.readfile(sys.argv(i));
+               src, ok := sys.readfile(sys.argv(i));
                if ok {
                        print "parsing " + sys.argv(i) + "\n";
-                       Parse(src, verbose);
+                       Parse(sys.argv(i), src, verbose);
                } else {
                        print "error: cannot read " + sys.argv(i) + "\n";
                }
index f43d126419a13a5c5606e66b72179dc0cb513789..5ebff817bd9776207bdfef4a3d0bba67b1f7f93d 100644 (file)
@@ -7,14 +7,11 @@ package main
 import Scanner "scanner"
 
 
-func Scan(src string) {
+func Scan(filename, src string) {
        S := new(Scanner.Scanner);
-       S.Open(src);
+       S.Open(filename, src);
        for {
-               //var t Scanner.Token;
-               var tok, beg, end int;
-               tok, beg, end = S.Scan(/*&t*/);
-               //t.Print();  // TODO  this doesn't compile?
+               tok, beg, end := S.Scan();
                print Scanner.TokenName(tok), "\t ", src[beg : end], "\n";
                if tok == Scanner.EOF {
                        return;
@@ -30,7 +27,7 @@ func main() {
                src, ok = sys.readfile(sys.argv(i));
                if ok {
                        print "scanning " + sys.argv(i) + "\n";
-                       Scan(src);
+                       Scan(sys.argv(i), src);
                } else {
                        print "error: cannot read " + sys.argv(i) + "\n";
                }