swahili-lang
Version:
A new programming language with semantics borrowed from the Swahili language to help teach programming concepts to Swahili speaking students.
140 lines (127 loc) • 4.46 kB
JavaScript
const stringWithArrows = require('../utils/stringWithArrows');
class Error {
/**
* Error representation class
* @param {Position} posStart the start position of the node where the error occurred
* @param {Position} posEnd the end positoin of the node where the error occurred
* @param {String} errorName the type of error
* @param {String} details More information about the error
*/
constructor(posStart, posEnd, errorName, details) {
this.posStart = posStart;
this.posEnd = posEnd;
this.errorName = errorName;
this.details = details;
}
/**
* String representation of the error
* @returns {String}
*/
toString() {
let pos = this.posStart;
let result = `${this.errorName}: ${this.details}` + '\n';
result += `File "${pos.fileName}:${pos.lineNumber + 1}:${
pos.colNumber + 1
}"`;
if (pos.fileName === '<stdin>')
result += '\n\n' + stringWithArrows(pos.fileText, pos, this.posEnd);
return result;
}
}
class IllegalCharError extends Error {
/**
* Occurs when an unrecognized character is encountered by the lexer
* @param {Position} posStart the start position of the node where the error occurred
* @param {Position} posEnd the end positoin of the node where the error occurred
* @param {String} details More information about the error
*/
constructor(posStart, posEnd, details) {
super(posStart, posEnd, 'Illegal Character', details);
}
}
class ExpectedCharError extends Error {
/**
* Occurs when an expected character is not found by the lexer
* @param {Position} posStart the start position of the node where the error occurred
* @param {Position} posEnd the end positoin of the node where the error occurred
* @param {String} details More information about the error
*/
constructor(posStart, posEnd, details = '') {
super(posStart, posEnd, 'Expected Character', details);
}
}
class InvalidSyntaxError extends Error {
/**
* Occurs when an unrecognized combination of tokens is encountered by the parser
* @param {Position} posStart the start position of the node where the error occurred
* @param {Position} posEnd the end positoin of the node where the error occurred
* @param {String} details More information about the error
*/
constructor(posStart, posEnd, details = '') {
super(posStart, posEnd, 'Invalid Syntax', details);
}
}
/** Runtime error */
class RTError extends Error {
/**
* Occurs when something goes wrong while the interpreter visits the different nodes
* @param {Position} posStart the start position of the node where the error occurred
* @param {Position} posEnd the end positoin of the node where the error occurred
* @param {String} details More information about the error
*/
constructor(posStart, posEnd, details, context) {
super(posStart, posEnd, 'Runtime Error', details);
this.context = context;
}
/**
* Generates the call stack leading up to the current RTError
* @returns {String}
*/
generateTraceback() {
let result = '';
let pos = this.posStart;
let ctx = this.context;
while (ctx) {
result =
`File "${pos.fileName}:${pos.lineNumber}:${pos.colNumber + 1}", in ${
ctx.displayName || '<anonymous>'
}\n` + result;
pos = ctx.parentEntryPos;
ctx = ctx.parent;
}
return '\nTraceback (most recent call last):\n' + result;
}
/**
* String representation of the error (including traceback)
* @returns {String}
*/
toString() {
let pos = this.posStart;
let result = this.generateTraceback();
result += `${this.errorName}: ${this.details}`;
if (pos.fileName === '<stdin>')
result += '\n\n' + stringWithArrows(pos.fileText, pos, this.posEnd);
return result;
}
}
/** Uncaught exception */
class UncaughtException extends Error {
/**
* Occurs when an error is manually thrown by the program
* @param {Position} posStart the start position of the node where the error occurred
* @param {Position} posEnd the end positoin of the node where the error occurred
* @param {String} details More information about the error
*/
constructor(posStart, posEnd, details, context) {
super(posStart, posEnd, 'Uncaught Exception', details);
this.context = context;
}
}
module.exports = {
Error,
IllegalCharError,
ExpectedCharError,
InvalidSyntaxError,
RTError,
UncaughtException,
};