js-slang
Version:
Javascript-based implementations of Source, written in Typescript
256 lines • 12.1 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.TranslatorErrors = exports.ResolverErrors = exports.ParserErrors = exports.TokenizerErrors = void 0;
/*The offset is calculated as follows:
Current position is one after real position of end of token: 1
*/
const MAGIC_OFFSET = 1;
const SPECIAL_CHARS = new RegExp("[\\\\$'\"]", "g");
function escape(unsafe) {
// @TODO escape newlines
return unsafe.replace(SPECIAL_CHARS, "\\$&");
}
/* Searches backwards and forwards till it hits a newline */
function getFullLine(source, current) {
let back = current;
let forward = current;
while (back > 0 && source[back] != '\n') {
back--;
}
if (source[back] === '\n') {
back++;
}
while (forward < source.length && source[forward] != '\n') {
forward++;
}
return '\n' + source.slice(back, forward);
}
function toEstreeLocation(line, column, offset) {
return { line, column, offset };
}
var TokenizerErrors;
(function (TokenizerErrors) {
class BaseTokenizerError extends SyntaxError {
constructor(message, line, col) {
super(`SyntaxError at line ${line} column ${col - 1}
${message}`);
this.line = line;
this.col = col;
this.name = "BaseTokenizerError";
this.loc = toEstreeLocation(line, col, 0);
}
}
TokenizerErrors.BaseTokenizerError = BaseTokenizerError;
class UnknownTokenError extends BaseTokenizerError {
constructor(token, line, col, source, current) {
let msg = getFullLine(source, current - 1) + "\n";
let hint = `${col > 1 ? '~' : ''}^~ Unknown token '${escape(token)}'`;
// The extra `~` character takes up some space.
hint = hint.padStart(hint.length + col - MAGIC_OFFSET - (col > 1 ? 1 : 0), " ");
super(msg + hint, line, col);
this.name = "UnknownTokenError";
}
}
TokenizerErrors.UnknownTokenError = UnknownTokenError;
class UnterminatedStringError extends BaseTokenizerError {
constructor(line, col, source, start, current) {
let msg = getFullLine(source, start) + "\n";
let hint = `^ Unterminated string`;
const diff = (current - start);
// +1 because we want the arrow to point after the string (where we expect the closing ")
hint = hint.padStart(hint.length + diff - MAGIC_OFFSET + 1, "~");
hint = hint.padStart(hint.length + col - diff, " ");
super(msg + hint, line, col);
this.name = "UnterminatedStringError";
}
}
TokenizerErrors.UnterminatedStringError = UnterminatedStringError;
class NonFourIndentError extends BaseTokenizerError {
constructor(line, col, source, start) {
let msg = getFullLine(source, start) + "\n";
let hint = `^ This indent should be a multiple of 4 spaces. It's currently ${col} spaces.`;
hint = hint.padStart(hint.length + col - MAGIC_OFFSET, "-");
super(msg + hint, line, col);
this.name = "NonFourIndentError";
}
}
TokenizerErrors.NonFourIndentError = NonFourIndentError;
class InvalidNumberError extends BaseTokenizerError {
constructor(line, col, source, start, current) {
let msg = getFullLine(source, start) + "\n";
let hint = `^ Invalid Number input.`;
const diff = (current - start);
// +1 because we want the arrow to point after the string (where we expect the closing ")
hint = hint.padStart(hint.length + diff - MAGIC_OFFSET + 1, "~");
hint = hint.padStart(hint.length + col - diff, " ");
super(msg + hint, line, col);
this.name = "InvalidNumberError";
}
}
TokenizerErrors.InvalidNumberError = InvalidNumberError;
class InconsistentIndentError extends BaseTokenizerError {
constructor(line, col, source, start) {
let msg = getFullLine(source, start) + "\n";
let hint = `^ This indent/dedent is inconsistent with other indents/dedents. It's currently ${col} spaces.`;
hint = hint.padStart(hint.length + col - MAGIC_OFFSET, "-");
super(msg + hint, line, col);
this.name = "InconsistentIndentError";
}
}
TokenizerErrors.InconsistentIndentError = InconsistentIndentError;
class ForbiddenIdentifierError extends BaseTokenizerError {
constructor(line, col, source, start) {
let msg = getFullLine(source, start) + "\n";
let hint = `^ This identifier is reserved for use in Python. Consider using another identifier.`;
hint = hint.padStart(hint.length + col - MAGIC_OFFSET, "^");
super(msg + hint, line, col);
this.name = "ForbiddenIdentifierError";
}
}
TokenizerErrors.ForbiddenIdentifierError = ForbiddenIdentifierError;
class ForbiddenOperatorError extends BaseTokenizerError {
constructor(line, col, source, start, current) {
let msg = getFullLine(source, start) + "\n";
let hint = ` This operator is reserved for use in Python. It's not allowed to be used.`;
const diff = (current - start);
hint = hint.padStart(hint.length + diff - MAGIC_OFFSET + 1, "^");
hint = hint.padStart(hint.length + col - diff, " ");
super(msg + hint, line, col);
this.name = "ForbiddenOperatorError";
}
}
TokenizerErrors.ForbiddenOperatorError = ForbiddenOperatorError;
class NonMatchingParenthesesError extends BaseTokenizerError {
constructor(line, col, source, current) {
let msg = getFullLine(source, current - 1) + "\n";
let hint = `${col > 1 ? '~' : ''}^~ Non-matching closing parentheses.`;
// The extra `~` character takes up some space.
hint = hint.padStart(hint.length + col - MAGIC_OFFSET - (col > 1 ? 1 : 0), " ");
super(msg + hint, line, col);
this.name = "NonMatchingParenthesesError";
}
}
TokenizerErrors.NonMatchingParenthesesError = NonMatchingParenthesesError;
})(TokenizerErrors = exports.TokenizerErrors || (exports.TokenizerErrors = {}));
var ParserErrors;
(function (ParserErrors) {
class BaseParserError extends SyntaxError {
constructor(message, line, col) {
super(`SyntaxError at line ${line} column ${col - 1}
${message}`);
this.line = line;
this.col = col;
this.name = "BaseParserError";
this.loc = toEstreeLocation(line, col, 0);
}
}
ParserErrors.BaseParserError = BaseParserError;
class ExpectedTokenError extends BaseParserError {
constructor(source, current, expected) {
let msg = getFullLine(source, current.indexInSource - current.lexeme.length) + "\n";
let hint = `^ ${expected}. Found '${escape(current.lexeme)}'.`;
hint = hint.padStart(hint.length + current.col - MAGIC_OFFSET, " ");
super(msg + hint, current.line, current.col);
this.name = "ExpectedTokenError";
}
}
ParserErrors.ExpectedTokenError = ExpectedTokenError;
class NoElseBlockError extends BaseParserError {
constructor(source, current) {
let msg = getFullLine(source, current.indexInSource) + "\n";
let hint = `^ Expected else block after this if block.`;
hint = hint.padStart(hint.length + current.col - MAGIC_OFFSET, " ");
super(msg + hint, current.line, current.col);
this.name = "ExpectedTokenError";
}
}
ParserErrors.NoElseBlockError = NoElseBlockError;
class GenericUnexpectedSyntaxError extends BaseParserError {
constructor(line, col, source, start, current) {
let msg = getFullLine(source, start) + "\n";
let hint = ` Detected invalid syntax.`;
const diff = (current - start);
hint = hint.padStart(hint.length + diff - MAGIC_OFFSET, "^");
hint = hint.padStart(hint.length + col - diff, " ");
super(msg + hint, line, col);
this.name = "GenericUnexpectedSyntaxError";
}
}
ParserErrors.GenericUnexpectedSyntaxError = GenericUnexpectedSyntaxError;
})(ParserErrors = exports.ParserErrors || (exports.ParserErrors = {}));
var ResolverErrors;
(function (ResolverErrors) {
class BaseResolverError extends SyntaxError {
constructor(message, line, col) {
super(`ResolverError at line ${line} column ${col - 1}
${message}`);
this.line = line;
this.col = col;
this.name = "BaseResolverError";
this.loc = toEstreeLocation(line, col, 0);
}
}
ResolverErrors.BaseResolverError = BaseResolverError;
class NameNotFoundError extends BaseResolverError {
constructor(line, col, source, start, current, suggestion) {
let msg = getFullLine(source, start) + "\n";
let hint = ` This name is not found in the current or enclosing environment(s).`;
const diff = (current - start);
hint = hint.padStart(hint.length + diff - MAGIC_OFFSET + 1, "^");
hint = hint.padStart(hint.length + col - diff, " ");
if (suggestion !== null) {
let sugg = ` Perhaps you meant to type '${suggestion}'?`;
sugg = sugg.padStart(sugg.length + col - MAGIC_OFFSET + 1, " ");
sugg = '\n' + sugg;
hint += sugg;
}
super(msg + hint, line, col);
this.name = "NameNotFoundError";
}
}
ResolverErrors.NameNotFoundError = NameNotFoundError;
class NameReassignmentError extends BaseResolverError {
constructor(line, col, source, start, current, oldName) {
let msg = getFullLine(source, start) + "\n";
let hint = ` A name has been declared here.`;
const diff = (current - start);
hint = hint.padStart(hint.length + diff - MAGIC_OFFSET + 1, "^");
hint = hint.padStart(hint.length + col - diff, " ");
let sugg = ` However, it has already been declared in the same environment at line ${oldName.line}, here:`;
sugg = sugg.padStart(sugg.length + col - MAGIC_OFFSET + 1, " ");
sugg = '\n' + sugg;
hint += sugg;
let oldNameLine = getFullLine(source, oldName.indexInSource);
oldNameLine.padStart(oldNameLine.length + col - MAGIC_OFFSET + 1, " ");
hint += oldNameLine;
super(msg + hint, line, col);
this.name = "NameReassignmentError";
}
}
ResolverErrors.NameReassignmentError = NameReassignmentError;
})(ResolverErrors = exports.ResolverErrors || (exports.ResolverErrors = {}));
var TranslatorErrors;
(function (TranslatorErrors) {
class BaseTranslatorError extends SyntaxError {
constructor(message, line, col) {
super(`BaseTranslatorError at line ${line} column ${col - 1}
${message}`);
this.line = line;
this.col = col;
this.name = "BaseTranslatorError";
this.loc = toEstreeLocation(line, col, 0);
}
}
TranslatorErrors.BaseTranslatorError = BaseTranslatorError;
class UnsupportedOperator extends BaseTranslatorError {
constructor(line, col, source, start) {
let msg = getFullLine(source, start) + "\n";
let hint = `^ This operator is not yet supported by us.`;
hint = hint.padStart(hint.length + col - MAGIC_OFFSET, " ");
super(msg + hint, line, col);
this.name = "UnsupportedOperator";
}
}
TranslatorErrors.UnsupportedOperator = UnsupportedOperator;
})(TranslatorErrors = exports.TranslatorErrors || (exports.TranslatorErrors = {}));
//# sourceMappingURL=errors.js.map
;