first stable parser
This commit is contained in:
parent
d01cf5790b
commit
79c54f3c0d
|
@ -1,2 +1,2 @@
|
||||||
point(3, 4) -> A
|
[point(3, 4) -> A]
|
||||||
line(A, point(7, 8))
|
line(A, point(7, 8))
|
|
@ -34,6 +34,10 @@ class Geometry extends HTMLElement
|
||||||
let content = loadScript(sourceFile);
|
let content = loadScript(sourceFile);
|
||||||
|
|
||||||
let parser = new Parser(content);
|
let parser = new Parser(content);
|
||||||
|
for(let instr of parser.instructions)
|
||||||
|
{
|
||||||
|
console.log(instr.eval());
|
||||||
|
}
|
||||||
|
|
||||||
this.attachShadow({mode: "open"});
|
this.attachShadow({mode: "open"});
|
||||||
let canvas = document.createElement("canvas");
|
let canvas = document.createElement("canvas");
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/// <reference path="../vector.ts" />
|
||||||
|
|
||||||
enum InstructionType
|
enum InstructionType
|
||||||
{
|
{
|
||||||
Point,
|
Point,
|
||||||
|
@ -5,7 +7,7 @@ enum InstructionType
|
||||||
Circle
|
Circle
|
||||||
}
|
}
|
||||||
|
|
||||||
class Instruction
|
abstract class Instruction
|
||||||
{
|
{
|
||||||
public fn: InstructionType;
|
public fn: InstructionType;
|
||||||
public params :Parameter[];
|
public params :Parameter[];
|
||||||
|
@ -15,4 +17,35 @@ class Instruction
|
||||||
this.fn = type;
|
this.fn = type;
|
||||||
this.params = [];
|
this.params = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PointInstruction extends Instruction
|
||||||
|
{
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
super(InstructionType.Point);
|
||||||
|
}
|
||||||
|
|
||||||
|
eval()
|
||||||
|
{
|
||||||
|
return new Vector2D(this.params[0].eval(), this.params[1].eval());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LineInstruction extends Instruction
|
||||||
|
{
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
super(InstructionType.Line);
|
||||||
|
}
|
||||||
|
|
||||||
|
eval()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
this.params[0].eval(),
|
||||||
|
this.params[1].eval()
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -33,3 +33,20 @@ class NumberParameter extends Parameter
|
||||||
return this.val;
|
return this.val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class InstructionParameter extends Parameter
|
||||||
|
{
|
||||||
|
public instr: Instruction;
|
||||||
|
|
||||||
|
constructor(instr: Instruction)
|
||||||
|
{
|
||||||
|
super(ParameterType.Identifier);
|
||||||
|
|
||||||
|
this.instr = instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
eval()
|
||||||
|
{
|
||||||
|
return this.instr.eval();
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,38 +3,53 @@
|
||||||
|
|
||||||
class Parser
|
class Parser
|
||||||
{
|
{
|
||||||
private instructions: Instruction[];
|
public instructions: Instruction[];
|
||||||
|
private variables: { [id: string] : InstructionParameter};
|
||||||
|
|
||||||
constructor(source: string)
|
constructor(source: string)
|
||||||
{
|
{
|
||||||
this.instructions = [];
|
this.instructions = [];
|
||||||
|
this.variables = {};
|
||||||
|
|
||||||
let lines = source.split(/\r?\n/);
|
let lines = source.split(/\r?\n/);
|
||||||
for(let line of lines)
|
for(let line of lines)
|
||||||
this.parseInstruction(line);
|
{
|
||||||
|
let instr = this.parseInstruction(line);
|
||||||
|
if(!instr[0])
|
||||||
|
this.instructions.push(instr[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseInstruction(instruction: string): boolean
|
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
|
||||||
if(instruction === "")
|
if(instruction === "")
|
||||||
return false;
|
return null;
|
||||||
|
|
||||||
|
let hidden = false;
|
||||||
|
if(instruction[0] === "[" && instruction[instruction.length - 1] === "]")
|
||||||
|
{
|
||||||
|
hidden = true;
|
||||||
|
instruction = instruction.substring(1, instruction.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction = instruction.split(" ").join(""); // Remove spaces
|
||||||
|
|
||||||
// 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
|
||||||
{
|
{
|
||||||
console.error("Invalid syntax");
|
console.error("Invalid syntax");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(matches.length > 1) // more than one match
|
if(matches.length > 1) // more than one match
|
||||||
{
|
{
|
||||||
console.error("Script may only contain one instruction per line");
|
console.error("Script may only contain one instruction per line");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let instr = matches[0]; // get the instruction
|
let instr = matches[0]; // get the instruction
|
||||||
instr = instr.split(" ").join("");
|
|
||||||
let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis
|
let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,25 +65,86 @@ class Parser
|
||||||
}
|
}
|
||||||
params.push(paramlist);
|
params.push(paramlist);
|
||||||
|
|
||||||
this.instructions.push(new Instruction(InstructionType.Point));
|
let newInstruction;
|
||||||
for(let param of params)
|
switch(symbol)
|
||||||
{
|
{
|
||||||
if(!this.parseParameter(param))
|
case "point":
|
||||||
{
|
{
|
||||||
console.error("Error during parameter parsing");
|
newInstruction = new PointInstruction();
|
||||||
return false;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "line":
|
||||||
|
{
|
||||||
|
newInstruction = new LineInstruction();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
console.error("Unknown instruction \"" + symbol + "\"");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
for(let param of params)
|
||||||
|
{
|
||||||
|
if(!this.parseParameter(newInstruction, param))
|
||||||
|
{
|
||||||
|
console.error("Error during parameter parsing: \"" + param + "\" failed to be parsed.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let assignment = instruction.search(/->/);
|
||||||
|
if(assignment !== -1)
|
||||||
|
{
|
||||||
|
let variableName = instruction.substring(assignment + 2, instruction.length);
|
||||||
|
|
||||||
|
if(variableName in this.variables)
|
||||||
|
{
|
||||||
|
console.error("Redefinition of variable \"" + variableName + "\" is not allowed.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.variables[variableName] = new InstructionParameter(newInstruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [hidden, newInstruction];
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseParameter(parameter: string): boolean
|
private parseParameter(instr: Instruction, parameter: string): boolean
|
||||||
{
|
{
|
||||||
let match = parameter.search(/\d*\.?\d*$/);
|
let match = parameter.match(/\d*\.?\d*$/);
|
||||||
if(match === 0)
|
if(match !== null && match[0] === parameter && match.index === 0)
|
||||||
{
|
{
|
||||||
this.instructions[this.instructions.length - 1].params.push(new NumberParameter(4));
|
let val = parseFloat(parameter);
|
||||||
|
let paramObj = new NumberParameter(val);
|
||||||
|
|
||||||
|
instr.params.push(paramObj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = parameter.match(/[A-Za-z]/)
|
||||||
|
if(match !== null && match[0] === parameter && match.index === 0)
|
||||||
|
{
|
||||||
|
let paramObj = this.variables[parameter];
|
||||||
|
if(paramObj === undefined)
|
||||||
|
{
|
||||||
|
console.error("Variable \"" + parameter + "\" is not defined");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instr.params.push(paramObj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = parameter.match(/[A-Za-z]*\(.*\)/)
|
||||||
|
if(match !== null && match[0] === parameter && match.index === 0)
|
||||||
|
{
|
||||||
|
let paramObj = new InstructionParameter(this.parseInstruction(parameter)[1]);
|
||||||
|
|
||||||
|
instr.params.push(paramObj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue