Make scanner work with exceptions
This commit is contained in:
parent
48f1b0f45c
commit
eac4279a5e
3 changed files with 35 additions and 12 deletions
|
@ -8,7 +8,7 @@ import fs from "fs"
|
|||
import yargs from "yargs"
|
||||
|
||||
import { Diagnostics, UnexpectedCharDiagnostic, UnexpectedTokenDiagnostic } from "../diagnostics"
|
||||
import { Punctuator, Scanner } from "../scanner"
|
||||
import { Punctuator, ScanError, Scanner } from "../scanner"
|
||||
import { ParseError, Parser } from "../parser"
|
||||
import { Checker } from "../checker"
|
||||
import { TextFile } from "../cst"
|
||||
|
@ -44,12 +44,16 @@ yargs
|
|||
try {
|
||||
sourceFile = parser.parseSourceFile();
|
||||
} catch (error) {
|
||||
if (!(error instanceof ParseError)) {
|
||||
throw error;
|
||||
}
|
||||
if (error instanceof ParseError) {
|
||||
diagnostics.add(new UnexpectedTokenDiagnostic(error.file, error.actual, error.expected));
|
||||
return;
|
||||
}
|
||||
if (error instanceof ScanError) {
|
||||
diagnostics.add(new UnexpectedCharDiagnostic(error.file, error.position, error.actual));
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
sourceFile.setParents();
|
||||
//debug(sourceFile.toJSON());
|
||||
const checker = new Checker(diagnostics);
|
||||
|
|
|
@ -40,7 +40,7 @@ export class UnexpectedCharDiagnostic {
|
|||
const endPos = this.position.clone();
|
||||
endPos.advance(this.actual);
|
||||
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';
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ import {
|
|||
Constructor,
|
||||
Integer,
|
||||
TextFile,
|
||||
Dot,
|
||||
DotDot,
|
||||
} from "./cst"
|
||||
import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics"
|
||||
import { Stream, BufferedStream, assert } from "./util";
|
||||
|
@ -64,7 +66,17 @@ function isOperatorPart(ch: string): boolean {
|
|||
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> {
|
||||
|
||||
|
@ -174,8 +186,7 @@ export class Scanner extends BufferedStream<Token> {
|
|||
case '\'': contents += '\''; break;
|
||||
case '\"': contents += '\"'; break;
|
||||
default:
|
||||
this.diagnostics.add(new UnexpectedCharDiagnostic(this.file, startPos, c1));
|
||||
throw new ScanError();
|
||||
throw new ScanError(this.file, startPos, c1);
|
||||
}
|
||||
escaping = false;
|
||||
} else {
|
||||
|
@ -203,7 +214,16 @@ export class Scanner extends BufferedStream<Token> {
|
|||
case '}': return new RBrace(startPos);
|
||||
case ',': return new Comma(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 '-':
|
||||
|
@ -336,8 +356,7 @@ export class Scanner extends BufferedStream<Token> {
|
|||
default:
|
||||
|
||||
// Nothing matched, so the current character is unrecognisable
|
||||
this.diagnostics.add(new UnexpectedCharDiagnostic(this.file, startPos, c0));
|
||||
throw new ScanError();
|
||||
throw new ScanError(this.file, startPos, c0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue