Tidy up error reporting

This commit is contained in:
Tangent Wantwight 2024-06-08 13:28:21 -04:00
parent a2c8eb66b9
commit ac1a38e75f

View file

@ -35,6 +35,12 @@ export function parse(
// Parser for evaluating Notcl scripts // Parser for evaluating Notcl scripts
export class ParseError extends Error {
constructor(message: string, public pos: number) {
super(message);
}
}
type TokenType = type TokenType =
| "newline" | "newline"
| "whitespace" | "whitespace"
@ -47,8 +53,7 @@ type TokenType =
| "backslash" | "backslash"
| "comment" | "comment"
| "text" | "text"
| "EOF" | "EOF";
| "ERROR";
type Token = [TokenType, string, number]; type Token = [TokenType, string, number];
@ -81,9 +86,9 @@ class WipScript {
return this.wipWord.length == 0 && this.wipCommand.length == 0; return this.wipWord.length == 0 && this.wipCommand.length == 0;
} }
addWordPiece(piece: InterpolatedPiece, pos?: number) { addWordPiece(piece: InterpolatedPiece, pos: number) {
if (this.endOfWordError) { if (this.endOfWordError) {
throw new Error(this.endOfWordError); throw new ParseError(this.endOfWordError, pos);
} }
if (this.startOfWord()) { if (this.startOfWord()) {
this.wordPos = pos; this.wordPos = pos;
@ -137,13 +142,14 @@ class Parser {
} }
} }
return (this.next = ["ERROR", "Token not matched", startPos]); throw new ParseError("Token not matched", startPos);
} }
expect(type: TokenType) { expect(type: TokenType) {
if (this.next[0] != type) { if (this.next[0] != type) {
throw new Error( throw new ParseError(
`Expected ${type}, found ${this.next[0]} (${this.next[1]})` `Expected ${type}, found ${this.next[0]} (${this.next[1]})`,
this.next[2]
); );
} }
} }
@ -175,7 +181,7 @@ class Parser {
case "[": { case "[": {
this.advance(); this.advance();
const script = this.parseScript(); const script = this.parseScript();
wip.addWordPiece({ script }); wip.addWordPiece({ script }, pos);
this.expect("]"); this.expect("]");
break; break;
} }
@ -200,8 +206,6 @@ class Parser {
case "backslash": case "backslash":
this.advance(); this.advance();
continue; continue;
case "ERROR":
throw new Error(chars);
default: default:
continue; continue;
} }
@ -223,10 +227,11 @@ class Parser {
case "quote": case "quote":
throw new Error(`Unhandled case: ${type} (${chars})`); throw new Error(`Unhandled case: ${type} (${chars})`);
case "ERROR":
throw new Error(chars);
default: default:
throw new Error(`Unhandled case: ${type satisfies never} (${chars})`); throw new ParseError(
`Unhandled case: ${type satisfies never} (${chars})`,
pos
);
} }
this.advance(); this.advance();
@ -261,17 +266,19 @@ class Parser {
wip.addWordPiece({ text: "\n" }, pos); wip.addWordPiece({ text: "\n" }, pos);
break; break;
default: default:
throw new Error(`Unknown backslash escape: ${chars}`); throw new ParseError(`Unknown backslash escape: ${chars}`, pos);
} }
break; break;
case "EOF": case "EOF":
throw new Error( throw new ParseError(
"Reached end of input while parsing a backslash escape" "Reached end of input while parsing a backslash escape",
pos
); );
case "ERROR":
throw new Error(chars);
default: default:
throw new Error(`Unhandled case: ${type satisfies never} (${chars})`); throw new ParseError(
`Unhandled case: ${type satisfies never} (${chars})`,
pos
);
} }
} }
@ -297,9 +304,10 @@ class Parser {
case "}": case "}":
return wip; return wip;
case "EOF": case "EOF":
throw new Error("Reached end of input while parsing a brace word"); throw new ParseError(
case "ERROR": "Reached end of input while parsing a brace word",
throw new Error(chars); pos
);
default: default:
wip += chars; wip += chars;
} }