added functions to parser

This commit is contained in:
Lauchmelder 2021-11-28 02:20:12 +01:00
parent 79c54f3c0d
commit 01165d43fb
5 changed files with 91 additions and 11 deletions

View file

@ -1,2 +1,9 @@
[point(3, 4) -> A] point(0.2378, -34.389) -> A
line(A, point(7, 8)) point(2.5, 0) -> B
[point(-1, 3) -> C]
line(A, B) -> AB
line(B, C)
line(C, A)
circle(A, len(AB))

9
examples/test.gs.disable Normal file
View file

@ -0,0 +1,9 @@
point(-1, 0) -> A
point(1, 0) -> B
line(A, B) -> AB
len(AB) -> length
circle(A, len(AB)) -> circleA
circle(B, len(AB)) -> circleB
intersection(circleA, circleB, 0) -> C
line(A, C)
line(B, C)

9
src/doc/todo.md Normal file
View file

@ -0,0 +1,9 @@
# TODO (Parser)
* Type checking
* Ignore case in instruction names
* Implement remaining functions
* Abort parsing on error
# TODO (Renderer)
* Implement shape classes
* Render shape classes

View file

@ -4,28 +4,32 @@ enum InstructionType
{ {
Point, Point,
Line, Line,
Circle Circle,
Length
} }
abstract class Instruction abstract class Instruction
{ {
public fn: InstructionType; public fn: InstructionType;
public params :Parameter[]; public params :Parameter[];
private argc: number;
constructor(type: InstructionType) constructor(type: InstructionType, argc: number)
{ {
this.fn = type; this.fn = type;
this.argc = argc;
this.params = []; this.params = [];
} }
abstract eval(); abstract eval();
public getParameterCount(): number { return this.argc; }
} }
class PointInstruction extends Instruction class PointInstruction extends Instruction
{ {
constructor() constructor()
{ {
super(InstructionType.Point); super(InstructionType.Point, 2);
} }
eval() eval()
@ -38,7 +42,7 @@ class LineInstruction extends Instruction
{ {
constructor() constructor()
{ {
super(InstructionType.Line); super(InstructionType.Line, 2);
} }
eval() eval()
@ -49,3 +53,35 @@ class LineInstruction extends Instruction
]; ];
} }
} }
class CircleInstruction extends Instruction
{
constructor()
{
super(InstructionType.Line, 2);
}
eval()
{
return [
this.params[0].eval(),
this.params[1].eval()
];
}
}
class LengthInstruction extends Instruction
{
constructor()
{
super(InstructionType.Line, 1);
}
eval()
{
let line = this.params[0].eval();
let dx = line[1].x - line[0].x;
let dy = line[1].y - line[0].y;
return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
}
}

View file

@ -15,8 +15,9 @@ class Parser
for(let line of lines) for(let line of lines)
{ {
let instr = this.parseInstruction(line); let instr = this.parseInstruction(line);
if(!instr[0]) if(instr !== null)
this.instructions.push(instr[1]); if(!instr[0])
this.instructions.push(instr[1]);
} }
} }
@ -80,6 +81,18 @@ class Parser
break; break;
} }
case "circle":
{
newInstruction = new CircleInstruction();
break;
}
case "len":
{
newInstruction = new LengthInstruction();
break;
}
default: default:
{ {
console.error("Unknown instruction \"" + symbol + "\""); console.error("Unknown instruction \"" + symbol + "\"");
@ -87,6 +100,13 @@ class Parser
} }
} }
let expectedArgs = newInstruction.getParameterCount();
if(expectedArgs !== params.length)
{
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))
@ -100,7 +120,6 @@ class Parser
if(assignment !== -1) if(assignment !== -1)
{ {
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)
{ {
console.error("Redefinition of variable \"" + variableName + "\" is not allowed."); console.error("Redefinition of variable \"" + variableName + "\" is not allowed.");
@ -115,7 +134,7 @@ class Parser
private parseParameter(instr: Instruction, parameter: string): boolean private parseParameter(instr: Instruction, parameter: string): boolean
{ {
let match = parameter.match(/\d*\.?\d*$/); let match = parameter.match(/-?\d*\.?\d*$/);
if(match !== null && match[0] === parameter && match.index === 0) if(match !== null && match[0] === parameter && match.index === 0)
{ {
let val = parseFloat(parameter); let val = parseFloat(parameter);
@ -125,7 +144,7 @@ class Parser
return true; return true;
} }
match = parameter.match(/[A-Za-z]/) match = parameter.match(/[A-Za-z]*/)
if(match !== null && match[0] === parameter && match.index === 0) if(match !== null && match[0] === parameter && match.index === 0)
{ {
let paramObj = this.variables[parameter]; let paramObj = this.variables[parameter];