Make scanner work with exceptions

This commit is contained in:
Sam Vervaeck 2022-08-31 13:37:26 +02:00
parent 48f1b0f45c
commit eac4279a5e
3 changed files with 35 additions and 12 deletions

View file

@ -8,7 +8,7 @@ import fs from "fs"
import yargs from "yargs" import yargs from "yargs"
import { Diagnostics, UnexpectedCharDiagnostic, UnexpectedTokenDiagnostic } from "../diagnostics" import { Diagnostics, UnexpectedCharDiagnostic, UnexpectedTokenDiagnostic } from "../diagnostics"
import { Punctuator, Scanner } from "../scanner" import { Punctuator, ScanError, Scanner } from "../scanner"
import { ParseError, Parser } from "../parser" import { ParseError, Parser } from "../parser"
import { Checker } from "../checker" import { Checker } from "../checker"
import { TextFile } from "../cst" import { TextFile } from "../cst"
@ -44,11 +44,15 @@ yargs
try { try {
sourceFile = parser.parseSourceFile(); sourceFile = parser.parseSourceFile();
} catch (error) { } catch (error) {
if (!(error instanceof ParseError)) { if (error instanceof ParseError) {
throw error; diagnostics.add(new UnexpectedTokenDiagnostic(error.file, error.actual, error.expected));
return;
} }
diagnostics.add(new UnexpectedTokenDiagnostic(error.file, error.actual, error.expected)); if (error instanceof ScanError) {
return; diagnostics.add(new UnexpectedCharDiagnostic(error.file, error.position, error.actual));
return;
}
throw error;
} }
sourceFile.setParents(); sourceFile.setParents();
//debug(sourceFile.toJSON()); //debug(sourceFile.toJSON());

View file

@ -40,7 +40,7 @@ export class UnexpectedCharDiagnostic {
const endPos = this.position.clone(); const endPos = this.position.clone();
endPos.advance(this.actual); endPos.advance(this.actual);
return ANSI_FG_RED + ANSI_BOLD + 'error: ' + ANSI_RESET return ANSI_FG_RED + ANSI_BOLD + 'error: ' + ANSI_RESET
+ `unexpeced character '${this.actual}'.\n\n` + `unexpeced character sequence '${this.actual}'.\n\n`
+ printExcerpt(this.file, new TextRange(this.position, endPos)) + '\n'; + printExcerpt(this.file, new TextRange(this.position, endPos)) + '\n';
} }

View file

@ -28,6 +28,8 @@ import {
Constructor, Constructor,
Integer, Integer,
TextFile, TextFile,
Dot,
DotDot,
} from "./cst" } from "./cst"
import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics" import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics"
import { Stream, BufferedStream, assert } from "./util"; import { Stream, BufferedStream, assert } from "./util";
@ -64,7 +66,17 @@ function isOperatorPart(ch: string): boolean {
return /\+-*\/%^&|$<>!?=/.test(ch); return /\+-*\/%^&|$<>!?=/.test(ch);
} }
class ScanError extends Error {} export class ScanError extends Error {
public constructor(
public file: TextFile,
public position: TextPosition,
public actual: string,
) {
super(`Uncaught scanner error`);
}
}
export class Scanner extends BufferedStream<Token> { export class Scanner extends BufferedStream<Token> {
@ -174,8 +186,7 @@ export class Scanner extends BufferedStream<Token> {
case '\'': contents += '\''; break; case '\'': contents += '\''; break;
case '\"': contents += '\"'; break; case '\"': contents += '\"'; break;
default: default:
this.diagnostics.add(new UnexpectedCharDiagnostic(this.file, startPos, c1)); throw new ScanError(this.file, startPos, c1);
throw new ScanError();
} }
escaping = false; escaping = false;
} else { } else {
@ -203,7 +214,16 @@ export class Scanner extends BufferedStream<Token> {
case '}': return new RBrace(startPos); case '}': return new RBrace(startPos);
case ',': return new Comma(startPos); case ',': return new Comma(startPos);
case ':': return new Colon(startPos); case ':': return new Colon(startPos);
case '.': return new Dot(startPos); case '.': {
const dots = c0 + this.takeWhile(ch => ch === '.');
if (dots === '.') {
return new Dot(startPos);
} else if (dots === '..') {
return new DotDot(startPos);
} else {
throw new ScanError(this.file, startPos, dots);
}
}
case '+': case '+':
case '-': case '-':
@ -336,8 +356,7 @@ export class Scanner extends BufferedStream<Token> {
default: default:
// Nothing matched, so the current character is unrecognisable // Nothing matched, so the current character is unrecognisable
this.diagnostics.add(new UnexpectedCharDiagnostic(this.file, startPos, c0)); throw new ScanError(this.file, startPos, c0);
throw new ScanError();
} }
} }