improved error handling
This commit is contained in:
parent
e82de580af
commit
b43f547ae5
|
@ -34,6 +34,12 @@ class Geometry extends HTMLElement
|
||||||
let content = loadScript(sourceFile);
|
let content = loadScript(sourceFile);
|
||||||
|
|
||||||
let parser = new Parser(content);
|
let parser = new Parser(content);
|
||||||
|
if(!parser.good())
|
||||||
|
{
|
||||||
|
console.error("Failed to create parser for script " + sourceFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(let instr of parser.instructions)
|
for(let instr of parser.instructions)
|
||||||
{
|
{
|
||||||
console.log(instr.eval());
|
console.log(instr.eval());
|
||||||
|
|
|
@ -5,22 +5,43 @@ class Parser
|
||||||
{
|
{
|
||||||
public instructions: Instruction[];
|
public instructions: Instruction[];
|
||||||
private variables: { [id: string] : InstructionParameter};
|
private variables: { [id: string] : InstructionParameter};
|
||||||
|
private success: boolean;
|
||||||
|
|
||||||
constructor(source: string)
|
constructor(source: string)
|
||||||
{
|
{
|
||||||
this.instructions = [];
|
this.instructions = [];
|
||||||
this.variables = {};
|
this.variables = {};
|
||||||
|
this.success = false;
|
||||||
|
|
||||||
let lines = source.split(/\r?\n/);
|
let lines = source.split(/\r?\n/);
|
||||||
|
let currentLine = 1;
|
||||||
for(let line of lines)
|
for(let line of lines)
|
||||||
{
|
{
|
||||||
let instr = this.parseInstruction(line);
|
let instr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
instr = this.parseInstruction(line);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
console.error("Error in line " + currentLine);
|
||||||
|
console.error(e);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(instr !== null)
|
if(instr !== null)
|
||||||
if(!instr[0])
|
if(!instr[0])
|
||||||
this.instructions.push(instr[1]);
|
this.instructions.push(instr[1]);
|
||||||
|
|
||||||
|
currentLine++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public good() { return this.success; }
|
||||||
|
|
||||||
private parseInstruction(instruction: string): [boolean, Instruction]
|
private parseInstruction(instruction: string): [boolean, Instruction]
|
||||||
{
|
{
|
||||||
// If the instruction is an empty line, do nothing for now
|
// If the instruction is an empty line, do nothing for now
|
||||||
|
@ -39,16 +60,10 @@ class Parser
|
||||||
// match the pattern "text(text)"
|
// match the pattern "text(text)"
|
||||||
let matches = instruction.match(/[A-Za-z]*\(.*\)/);
|
let matches = instruction.match(/[A-Za-z]*\(.*\)/);
|
||||||
if(matches === null) // no match found
|
if(matches === null) // no match found
|
||||||
{
|
throw new Error("Line does not contain a valid instruction.");
|
||||||
console.error("Invalid syntax");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(matches.length > 1) // more than one match
|
if(matches.length > 1) // more than one match
|
||||||
{
|
throw new Error("Line may only contain one instruction");
|
||||||
console.error("Script may only contain one instruction per line");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let instr = matches[0]; // get the instruction
|
let instr = matches[0]; // get the instruction
|
||||||
let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis
|
let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis
|
||||||
|
@ -68,25 +83,16 @@ class Parser
|
||||||
|
|
||||||
let newInstruction = InstructionFactory.createInstruction(symbol);
|
let newInstruction = InstructionFactory.createInstruction(symbol);
|
||||||
if(newInstruction === null)
|
if(newInstruction === null)
|
||||||
{
|
throw new Error("Unknown instruction: \"" + symbol + "\"");
|
||||||
console.error("Unknown instruction: \"" + symbol + "\"");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let expectedArgs = newInstruction.getParameterCount();
|
let expectedArgs = newInstruction.getParameterCount();
|
||||||
if(expectedArgs !== params.length)
|
if(expectedArgs !== params.length)
|
||||||
{
|
throw new Error("Wrong number of arguments for instruction \"" + symbol + "\". Expected " + expectedArgs + " arguments but received " + params.length + " instead.");
|
||||||
console.error("Wrong number of arguments for instruction \"" + symbol + "\". Expected " + expectedArgs + " arguments but received " + params.length + " instead.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(let param of params)
|
for(let param of params)
|
||||||
{
|
{
|
||||||
if(!this.parseParameter(newInstruction, param))
|
if(!this.parseParameter(newInstruction, param))
|
||||||
{
|
throw new Error("Error during parameter parsing: \"" + param + "\" failed to be parsed.");
|
||||||
console.error("Error during parameter parsing: \"" + param + "\" failed to be parsed.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let assignment = instruction.search(/->/);
|
let assignment = instruction.search(/->/);
|
||||||
|
@ -94,10 +100,7 @@ class Parser
|
||||||
{
|
{
|
||||||
let variableName = instruction.substring(assignment + 2, instruction.length);
|
let variableName = instruction.substring(assignment + 2, instruction.length);
|
||||||
if(variableName in this.variables)
|
if(variableName in this.variables)
|
||||||
{
|
throw new Error("Redefinition of variable \"" + variableName + "\" is not allowed.");
|
||||||
console.error("Redefinition of variable \"" + variableName + "\" is not allowed.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.variables[variableName] = new InstructionParameter(newInstruction);
|
this.variables[variableName] = new InstructionParameter(newInstruction);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue