mirror of
https://github.com/golang/go
synced 2024-11-25 17:27:58 -07:00
- improved error handling
SVN=126718
This commit is contained in:
parent
9ec762791e
commit
8be580e20d
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
package Parser
|
package Parser
|
||||||
|
|
||||||
//import . "scanner"
|
|
||||||
import Scanner "scanner"
|
import Scanner "scanner"
|
||||||
|
|
||||||
|
|
||||||
@ -63,8 +62,8 @@ func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) Error(msg string) {
|
func (P *Parser) Error(pos int, msg string) {
|
||||||
P.S.Error(P.S.pos, msg);
|
P.S.Error(pos, msg);
|
||||||
P.Next(); // make progress
|
P.Next(); // make progress
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ func (P *Parser) Expect(tok int) {
|
|||||||
if P.tok == tok {
|
if P.tok == tok {
|
||||||
P.Next()
|
P.Next()
|
||||||
} else {
|
} 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() {
|
func (P *Parser) ParseType() {
|
||||||
P.Trace("Type");
|
P.Trace("Type");
|
||||||
if !P.TryType() {
|
if !P.TryType() {
|
||||||
P.Error("type expected");
|
P.Error(P.beg, "type expected");
|
||||||
}
|
}
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
}
|
}
|
||||||
@ -583,7 +582,7 @@ func (P *Parser) ParseControlFlowStat(tok int) {
|
|||||||
func (P *Parser) ParseStatement() {
|
func (P *Parser) ParseStatement() {
|
||||||
P.Trace("Statement");
|
P.Trace("Statement");
|
||||||
if !P.TryStatement() {
|
if !P.TryStatement() {
|
||||||
P.Error("statement expected");
|
P.Error(P.beg, "statement expected");
|
||||||
}
|
}
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
}
|
}
|
||||||
@ -874,7 +873,7 @@ func (P *Parser) ParseDeclaration() {
|
|||||||
case Scanner.EXPORT:
|
case Scanner.EXPORT:
|
||||||
P.ParseExportDecl();
|
P.ParseExportDecl();
|
||||||
default:
|
default:
|
||||||
P.Error("declaration expected");
|
P.Error(P.beg, "declaration expected");
|
||||||
}
|
}
|
||||||
if indent != P.indent {
|
if indent != P.indent {
|
||||||
panic "imbalanced tracing code"
|
panic "imbalanced tracing code"
|
||||||
@ -916,7 +915,7 @@ func (P *Parser) ParseOperand() {
|
|||||||
case Scanner.NEW:
|
case Scanner.NEW:
|
||||||
P.ParseNew();
|
P.ParseNew();
|
||||||
default:
|
default:
|
||||||
P.Error("operand expected");
|
P.Error(P.beg, "operand expected");
|
||||||
}
|
}
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
}
|
}
|
||||||
@ -1004,9 +1003,9 @@ func (P *Parser) ParseUnaryExpr() {
|
|||||||
func Precedence(tok int) int {
|
func Precedence(tok int) int {
|
||||||
// TODO should use a map or array here for lookup
|
// TODO should use a map or array here for lookup
|
||||||
switch tok {
|
switch tok {
|
||||||
case Scanner.COR:
|
case Scanner.LOR:
|
||||||
return 1;
|
return 1;
|
||||||
case Scanner.CAND:
|
case Scanner.LAND:
|
||||||
return 2;
|
return 2;
|
||||||
case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
|
case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -16,7 +16,7 @@ export
|
|||||||
SHL, SHR,
|
SHL, SHR,
|
||||||
ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN,
|
ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN,
|
||||||
AND_ASSIGN, OR_ASSIGN, XOR_ASSIGN, SHL_ASSIGN, SHR_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,
|
BREAK, CASE, CHAN, CONST, CONTINUE, DEFAULT, ELSE, EXPORT, FALLTHROUGH, FALSE,
|
||||||
FOR, FUNC, GO, GOTO, IF, IMPORT, INTERFACE, IOTA, MAP, NEW, NIL, PACKAGE, RANGE,
|
FOR, FUNC, GO, GOTO, IF, IMPORT, INTERFACE, IOTA, MAP, NEW, NIL, PACKAGE, RANGE,
|
||||||
RETURN, SELECT, STRUCT, SWITCH, TRUE, TYPE, VAR
|
RETURN, SELECT, STRUCT, SWITCH, TRUE, TYPE, VAR
|
||||||
@ -81,8 +81,8 @@ const (
|
|||||||
SHL_ASSIGN;
|
SHL_ASSIGN;
|
||||||
SHR_ASSIGN;
|
SHR_ASSIGN;
|
||||||
|
|
||||||
CAND;
|
LAND;
|
||||||
COR;
|
LOR;
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
KEYWORDS_BEG;
|
KEYWORDS_BEG;
|
||||||
@ -184,8 +184,8 @@ func TokenName(tok int) string {
|
|||||||
case SHL_ASSIGN: return "<<=";
|
case SHL_ASSIGN: return "<<=";
|
||||||
case SHR_ASSIGN: return ">>=";
|
case SHR_ASSIGN: return ">>=";
|
||||||
|
|
||||||
case CAND: return "&&";
|
case LAND: return "&&";
|
||||||
case COR: return "||";
|
case LOR: return "||";
|
||||||
|
|
||||||
case BREAK: return "break";
|
case BREAK: return "break";
|
||||||
case CASE: return "case";
|
case CASE: return "case";
|
||||||
@ -249,6 +249,10 @@ func digit_val (ch int) int {
|
|||||||
|
|
||||||
export Scanner
|
export Scanner
|
||||||
type Scanner struct {
|
type Scanner struct {
|
||||||
|
filename string; // error reporting only
|
||||||
|
nerrors int; // number of errors
|
||||||
|
errpos int; // last error position
|
||||||
|
|
||||||
src string;
|
src string;
|
||||||
pos int; // current reading position
|
pos int; // current reading position
|
||||||
ch int; // one char look-ahead
|
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) {
|
func (S *Scanner) Error(pos int, msg string) {
|
||||||
line, col := S.LineCol(pos);
|
const errdist = 10;
|
||||||
print "error ", line, ":", col, ": ", msg, "\n";
|
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 {
|
if Keywords == nil {
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
//S.nerrors = 0;
|
S.filename = filename;
|
||||||
|
S.nerrors = 0;
|
||||||
|
S.errpos = 0;
|
||||||
|
|
||||||
S.src = src;
|
S.src = src;
|
||||||
S.pos = 0;
|
S.pos = 0;
|
||||||
S.Next();
|
S.Next();
|
||||||
@ -438,19 +450,18 @@ func IntString(x, base int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func CharString(ch int) string {
|
func CharString(ch int) string {
|
||||||
s := string(ch);
|
s := string(ch);
|
||||||
switch ch {
|
switch ch {
|
||||||
case '\a': s = "\\a";
|
case '\a': s = `\a`;
|
||||||
case '\b': s = "\\b";
|
case '\b': s = `\b`;
|
||||||
case '\f': s = "\\f";
|
case '\f': s = `\f`;
|
||||||
case '\n': s = "\\n";
|
case '\n': s = `\n`;
|
||||||
case '\r': s = "\\r";
|
case '\r': s = `\r`;
|
||||||
case '\t': s = "\\t";
|
case '\t': s = `\t`;
|
||||||
case '\v': s = "\\v";
|
case '\v': s = `\v`;
|
||||||
case '\\': s = "\\";
|
case '\\': s = `\\`;
|
||||||
case '\'': s = "\\'";
|
case '\'': s = `\'`;
|
||||||
}
|
}
|
||||||
return "'" + s + "' (U+" + IntString(ch, 16) + ")";
|
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) {
|
func (S *Scanner) Scan () (tok, beg, end int) {
|
||||||
S.SkipWhitespace();
|
S.SkipWhitespace();
|
||||||
|
|
||||||
tok = ILLEGAL;
|
|
||||||
beg = S.pos - 1;
|
|
||||||
end = beg;
|
|
||||||
|
|
||||||
ch := S.ch;
|
ch := S.ch;
|
||||||
|
tok = ILLEGAL;
|
||||||
|
beg = S.chpos;
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case is_letter(ch): tok = S.ScanIdentifier();
|
case is_letter(ch): tok = S.ScanIdentifier();
|
||||||
case digit_val(ch) < 10: tok = S.ScanNumber(false);
|
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.Select4(GTR, GEQ, '>', SHR, SHR_ASSIGN);
|
||||||
case '=': tok = S.Select2(ASSIGN, EQL);
|
case '=': tok = S.Select2(ASSIGN, EQL);
|
||||||
case '!': tok = S.Select2(NOT, NEQ);
|
case '!': tok = S.Select2(NOT, NEQ);
|
||||||
case '&': tok = S.Select3(AND, AND_ASSIGN, '&', CAND);
|
case '&': tok = S.Select3(AND, AND_ASSIGN, '&', LAND);
|
||||||
case '|': tok = S.Select3(OR, OR_ASSIGN, '|', COR);
|
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, S.chpos;
|
||||||
|
|
||||||
return tok, beg, end;
|
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ import Scanner "scanner"
|
|||||||
import Parser "parser"
|
import Parser "parser"
|
||||||
|
|
||||||
|
|
||||||
func Parse(src string, verbose int) {
|
func Parse(filename, src string, verbose int) {
|
||||||
S := new(Scanner.Scanner);
|
S := new(Scanner.Scanner);
|
||||||
S.Open(src);
|
S.Open(filename, src);
|
||||||
|
|
||||||
P := new(Parser.Parser);
|
P := new(Parser.Parser);
|
||||||
P.Open(S, verbose);
|
P.Open(S, verbose);
|
||||||
@ -31,12 +31,10 @@ func main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var src string;
|
src, ok := sys.readfile(sys.argv(i));
|
||||||
var ok bool;
|
|
||||||
src, ok = sys.readfile(sys.argv(i));
|
|
||||||
if ok {
|
if ok {
|
||||||
print "parsing " + sys.argv(i) + "\n";
|
print "parsing " + sys.argv(i) + "\n";
|
||||||
Parse(src, verbose);
|
Parse(sys.argv(i), src, verbose);
|
||||||
} else {
|
} else {
|
||||||
print "error: cannot read " + sys.argv(i) + "\n";
|
print "error: cannot read " + sys.argv(i) + "\n";
|
||||||
}
|
}
|
||||||
|
@ -7,14 +7,11 @@ package main
|
|||||||
import Scanner "scanner"
|
import Scanner "scanner"
|
||||||
|
|
||||||
|
|
||||||
func Scan(src string) {
|
func Scan(filename, src string) {
|
||||||
S := new(Scanner.Scanner);
|
S := new(Scanner.Scanner);
|
||||||
S.Open(src);
|
S.Open(filename, src);
|
||||||
for {
|
for {
|
||||||
//var t Scanner.Token;
|
tok, beg, end := S.Scan();
|
||||||
var tok, beg, end int;
|
|
||||||
tok, beg, end = S.Scan(/*&t*/);
|
|
||||||
//t.Print(); // TODO this doesn't compile?
|
|
||||||
print Scanner.TokenName(tok), "\t ", src[beg : end], "\n";
|
print Scanner.TokenName(tok), "\t ", src[beg : end], "\n";
|
||||||
if tok == Scanner.EOF {
|
if tok == Scanner.EOF {
|
||||||
return;
|
return;
|
||||||
@ -30,7 +27,7 @@ func main() {
|
|||||||
src, ok = sys.readfile(sys.argv(i));
|
src, ok = sys.readfile(sys.argv(i));
|
||||||
if ok {
|
if ok {
|
||||||
print "scanning " + sys.argv(i) + "\n";
|
print "scanning " + sys.argv(i) + "\n";
|
||||||
Scan(src);
|
Scan(sys.argv(i), src);
|
||||||
} else {
|
} else {
|
||||||
print "error: cannot read " + sys.argv(i) + "\n";
|
print "error: cannot read " + sys.argv(i) + "\n";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user