diff --git a/README.md b/README.md
index 364eaa9..14b8967 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
# lauchpioos
-Under construction
+A JavaScript geometry sketching library.
diff --git a/examples/test.gs b/examples/test.gs
index 49f1677..7c0d49b 100644
--- a/examples/test.gs
+++ b/examples/test.gs
@@ -1,10 +1,3 @@
-point(200, 300) -> A
-point(400, 300) -> B
-[point(300, 128) -> C]
+point(3 | 4)
-line(A, B) -> AB
-line(B, C)
-line(C, A)
-
-circle(A, len(AB))
-circle(B, len(AB))
\ No newline at end of file
+point(6 | 7)
\ No newline at end of file
diff --git a/examples/test.gs.disable b/examples/test.gs.disable
deleted file mode 100644
index 8b2a065..0000000
--- a/examples/test.gs.disable
+++ /dev/null
@@ -1,9 +0,0 @@
-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)
diff --git a/src/doc/syntax.md b/src/doc/syntax.md
index 173f3ac..14005e0 100644
--- a/src/doc/syntax.md
+++ b/src/doc/syntax.md
@@ -1,31 +1,16 @@
# Syntax
```
-[point(3, 4) -> A]
-point(6, 7) -> B
+point(3 | 4) -> A
+point(6 | 7) -> B
-line[color=red, weight=4](A, B) -> AB
-line(point(0, 0), point(100, 100))
+line(A, B) -> AB
+line(0 | 0, 100 | 100)
circle(A, len(AB))
```
-## Behaviour
-Every line is one instruction. It is possible to assign instructions names to re-use them later.
-These variables are immutable. Objects do not exist in this script, in fact, variables are more similar to C-style macros than actual variables.
-
-Lines in brackets `[]` are "hidden". They are parsed, but will not be rendered.
-
-It is possible to add an optional set of parameters in front of each parameter list, in order to specify the appearance of the element.
-
-## Primitives vs Functions
-Primitives (e.g. `point`, `line`) and Functions (e.g. `len`, `intersection`) are syntactically indistinguishable.
-Both can be used as parameters or instructions and can be assigned to variables. The only difference is that Primitives generate a visual output (unless they are surrounded by square brackets)
-
-## Grammar
-```
-instruction ::= identifier({parameter, }) [-> identifer]
-parameter ::= instruction | identifier | number
-identifier ::= (A-Za-z)
-number ::= (0-9)[.(0-9)]
-```
+## Primitives
+* `Point point(x, y)` is a 2D point. It returns an element of type `Point`
+* `Line line(Point from, Point to)` is a straight line. It returns an element of type `Line`.
+* `Circle circle(Point center, radius)` draws a circle at `center` and `radius`
\ No newline at end of file
diff --git a/src/doc/todo.md b/src/doc/todo.md
deleted file mode 100644
index e11c816..0000000
--- a/src/doc/todo.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# TODO (Parser)
-* Type checking
-* Ignore case in instruction names
-* Implement remaining functions
-* Abort parsing on error
-
-# TODO (Renderer)
-* Implement shape classes
-* Render shape classes
\ No newline at end of file
diff --git a/src/geometry.ts b/src/geometry.ts
index 584b633..58abec9 100644
--- a/src/geometry.ts
+++ b/src/geometry.ts
@@ -1,11 +1,10 @@
-///
-///
-///
+import { Vector2D } from "./vector.js"
+import * as shape from "./shapes.js"
function loadScript(filepath: string): string
{
- let result = null;
- let xmlhttp = new XMLHttpRequest();
+ var result = null;
+ var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filepath, false);
xmlhttp.send();
if (xmlhttp.status==200) {
@@ -17,7 +16,6 @@ function loadScript(filepath: string): string
class Geometry extends HTMLElement
{
- private shapes: Shape[];
private canvas: HTMLCanvasElement;
private context: CanvasRenderingContext2D;
private sourceFile: string;
@@ -25,7 +23,7 @@ class Geometry extends HTMLElement
constructor()
{
super();
- console.log("constructor")
+
if(!this.hasAttribute("src"))
{
return;
@@ -34,16 +32,37 @@ class Geometry extends HTMLElement
let sourceFile = this.getAttribute("src");
let content = loadScript(sourceFile);
- let parser = new Parser(content);
- if(!parser.good())
+ let lines = content.split("\n");
+ for(let line of lines)
{
- console.error("Failed to create parser for script " + sourceFile);
- return;
+ if(line === "\r")
+ {
+ console.log("empty");
+ continue;
+ }
+
+ let instruction = line.split("(")[0];
+
+ switch(instruction)
+ {
+ case instruction:
+ {
+ let coords = line.split("(")[1].split("|");
+ console.log(coords);
+ break;
+ }
+
+ default:
+ {
+ console.log("something else");
+ break;
+ }
+ }
}
this.attachShadow({mode: "open"});
let canvas = document.createElement("canvas");
- canvas.width = 700;
+ canvas.width = 500;
canvas.height = 500;
let context = canvas.getContext("2d");
@@ -52,38 +71,13 @@ class Geometry extends HTMLElement
this.shadowRoot.append(this.canvas);
-
- this.shapes = []
- for(let instruction of parser.instructions)
- {
- let value = instruction.eval();
- switch(instruction.getType())
- {
- case InstructionType.Line:
- {
- console.log("New line " + value)
- this.shapes.push(new Line(this.context, new Vector2D(value[0].x, value[0].y), new Vector2D(value[1].x, value[1].y)));
- break;
- }
-
- case InstructionType.Circle:
- {
- console.log("New circle " + value)
- this.shapes.push(new Circle(this.context, new Vector2D(value[0].x, value[0].y), value[1]));
- break;
- }
- }
- }
-
this.redraw();
}
private redraw()
{
- for (let shape of this.shapes)
- {
- shape.draw()
- }
+ shape.line(this.context, new Vector2D(), new Vector2D(300, 300));
+ shape.circle(this.context, new Vector2D(150, 150), 100);
}
}
diff --git a/src/gfx/polygon.ts b/src/gfx/polygon.ts
deleted file mode 100644
index 5ce58d4..0000000
--- a/src/gfx/polygon.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-///
-
-class Polygon extends Shape
-{
- private points: Vector2D[]
-
-
- constructor(ctx, points) {
- super(ctx);
- if (points.length <3)
- {
- console.error("cant draw polygon, need min 3 points")
- }
- this.points = points
- }
-
- public draw()
- {
- let last_element = this.points[this.points.length-1]
- this.ctx.beginPath();
- this.ctx.moveTo(last_element.x, last_element.y);
- for (let point of this.points)
- {
- this.ctx.lineTo(point.x, point.y);
- }
- this.ctx.lineWidth = this.style.strokeWidth;
- this.ctx.strokeStyle = this.style.strokeColor;
- this.ctx.stroke();
- }
-}
\ No newline at end of file
diff --git a/src/gfx/shapes.ts b/src/gfx/shapes.ts
deleted file mode 100644
index 4131d79..0000000
--- a/src/gfx/shapes.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-///
-///
-
-abstract class Shape
-{
- protected ctx: CanvasRenderingContext2D
- protected style: ShapeStyle
-
- constructor(ctx) {
- this.ctx = ctx
- this.style = new ShapeStyle()
- }
-
- abstract draw()
-}
-
-class Line extends Shape
-{
- private from: Vector2D
- private to: Vector2D
-
- constructor(ctx,from, to) {
- super(ctx)
- this.from = from
- this.to = to
- }
-
- public draw()
- {
- this.ctx.beginPath();
- this.ctx.moveTo(this.from.x, this.from.y);
- this.ctx.lineTo(this.to.x, this.to.y);
-
- this.ctx.lineWidth = this.style.strokeWidth;
- this.ctx.strokeStyle = this.style.strokeColor;
- this.ctx.stroke();
- }
-}
-
-class Circle extends Shape
-{
-
- private center: Vector2D
- private radius: number
-
- constructor(ctx,center, radius) {
- super(ctx)
- this.center = center
- this.radius = radius
- }
-
- public draw()
- {
- this.ctx.beginPath();
- this.ctx.arc(this.center.x, this.center.y, this.radius, 0, 2 * Math.PI, false);
-
- this.ctx.fillStyle = this.style.fillColor;
- this.ctx.fill();
-
- this.ctx.lineWidth = this.style.strokeWidth;
- this.ctx.strokeStyle = this.style.strokeColor;
- this.ctx.stroke();
- }
-}
\ No newline at end of file
diff --git a/src/parser/instruction.ts b/src/parser/instruction.ts
deleted file mode 100644
index 87848b9..0000000
--- a/src/parser/instruction.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-///
-
-enum InstructionType
-{
- Point,
- Line,
- Circle,
- Length
-}
-
-abstract class Instruction
-{
- private type: InstructionType;
- public params :Parameter[];
- private argc: number;
-
- constructor(type: InstructionType, argc: number)
- {
- this.type = type;
- this.argc = argc;
- this.params = [];
- }
-
- abstract eval();
- public getParameterCount(): number { return this.argc; }
- public getType(): InstructionType { return this.type; }
-}
-
-class PointInstruction extends Instruction
-{
- constructor()
- {
- super(InstructionType.Point, 2);
- }
-
- eval()
- {
- return new Vector2D(this.params[0].eval(), this.params[1].eval());
- }
-}
-
-class LineInstruction extends Instruction
-{
- constructor()
- {
- super(InstructionType.Line, 2);
- }
-
- eval()
- {
- return [
- this.params[0].eval(),
- this.params[1].eval()
- ];
- }
-}
-
-class CircleInstruction extends Instruction
-{
- constructor()
- {
- super(InstructionType.Circle, 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));
- }
-}
\ No newline at end of file
diff --git a/src/parser/instructionFactory.ts b/src/parser/instructionFactory.ts
deleted file mode 100644
index e1e9d5a..0000000
--- a/src/parser/instructionFactory.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-///
-
-abstract class InstructionFactory
-{
- private static symbolDict: { [name: string] : Function } = {
- "point": (): PointInstruction => { return new PointInstruction(); },
- "line": (): LineInstruction => { return new LineInstruction(); },
- "circle": (): CircleInstruction => { return new CircleInstruction(); },
- "len": (): LengthInstruction => { return new LengthInstruction(); }
- }
-
- public static createInstruction(name: string): Instruction
- {
- if(!(name in InstructionFactory.symbolDict))
- return null;
-
- return InstructionFactory.symbolDict[name]();
- }
-}
\ No newline at end of file
diff --git a/src/parser/parameter.ts b/src/parser/parameter.ts
deleted file mode 100644
index efce571..0000000
--- a/src/parser/parameter.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-enum ParameterType
-{
- Instruction,
- Identifier,
- Number
-}
-
-abstract class Parameter
-{
- public type: ParameterType;
-
- constructor(type: ParameterType)
- {
- this.type = type;
- }
-
- abstract eval();
-}
-
-class NumberParameter extends Parameter
-{
- public val: number;
-
- constructor(val: number)
- {
- super(ParameterType.Number);
-
- this.val = val;
- }
-
- eval()
- {
- return this.val;
- }
-}
-
-class InstructionParameter extends Parameter
-{
- public instr: Instruction;
-
- constructor(instr: Instruction)
- {
- super(ParameterType.Identifier);
-
- this.instr = instr;
- }
-
- eval()
- {
- return this.instr.eval();
- }
-}
\ No newline at end of file
diff --git a/src/parser/parser.ts b/src/parser/parser.ts
deleted file mode 100644
index 3dd1fb5..0000000
--- a/src/parser/parser.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-///
-///
-
-/**
- * @brief Turns a .gs script into a list of instructions to be passed to the renderer
- */
-class Parser
-{
- public instructions: Instruction[];
- private macros: { [id: string] : InstructionParameter};
- private success: boolean;
-
- /**
- * Parses each line of the script and turns them into instructions or adds them to the macro list
- *
- * @param source The source code of the script
- */
- constructor(source: string)
- {
- this.instructions = [];
- this.macros = {};
- this.success = false;
-
- let lines = source.split(/\r?\n/);
- let currentLine = 1;
- for(let line of lines)
- {
- let instr;
- try
- {
- instr = this.parseInstruction(line);
- }
- catch(e)
- {
- console.error("Error in line " + currentLine);
- console.error(e);
-
- return;
- }
-
- // If the instruction is null it means that the instruction was a function and not a primitive
- if(instr !== null)
- if(!instr[0])
- this.instructions.push(instr[1]);
-
- currentLine++;
- }
-
- this.success = true;
- }
-
- public good() { return this.success; }
-
- private parseInstruction(instruction: string): [boolean, Instruction]
- {
- // If the instruction is an empty line, do nothing for now
- if(instruction === "")
- return null;
-
- // Handle [] syntax. Lines in [] will be processed but not rendered
- 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)"
- let matches = instruction.match(/[A-Za-z]*\(.*\)/);
- if(matches === null) // no match found
- throw new Error("Line does not contain a valid instruction.");
-
- if(matches.length > 1) // more than one match
- throw new Error("Line may only contain one instruction");
-
- let instr = matches[0]; // get the instruction
- let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis
-
-
- let symbol = instr.substr(0, paranthesisPos); // get function name
- let paramlist = instr.substring(paranthesisPos + 1, instr.length - 1); // get parameter list
-
- // Construct the parameter list
- let match;
- let params = [];
- while((match = paramlist.search(/,(?![^\(]*\))/)) !== -1)
- {
- params.push(paramlist.substring(0, match));
- paramlist = paramlist.substring(match + 1, paramlist.length);
- }
- params.push(paramlist);
-
- // Create appropriate instruction
- let newInstruction = InstructionFactory.createInstruction(symbol);
- if(newInstruction === null)
- throw new Error("Unknown instruction: \"" + symbol + "\"");
-
- // Check that the number of arguments passed to the function is correct
- let expectedArgs = newInstruction.getParameterCount();
- if(expectedArgs !== params.length)
- throw new Error("Wrong number of arguments for instruction \"" + symbol + "\". Expected " + expectedArgs + " arguments but received " + params.length + " instead.");
-
- // Parse the individual parameters
- for(let param of params)
- {
- if(!this.parseParameter(newInstruction, param))
- throw new Error("Error during parameter parsing: \"" + param + "\" failed to be parsed.");
- }
-
- // In case there is an assignment, add the instruction to the macro list
- let assignment = instruction.search(/->/);
- if(assignment !== -1)
- {
- let variableName = instruction.substring(assignment + 2, instruction.length);
- if(variableName in this.macros)
- throw new Error("Redefinition of variable \"" + variableName + "\" is not allowed.");
-
- this.macros[variableName] = new InstructionParameter(newInstruction);
- }
-
- return [hidden, newInstruction];
- }
-
- private parseParameter(instr: Instruction, parameter: string): boolean
- {
- // Parameter is a number
- let match = parameter.match(/-?\d*\.?\d*$/);
- if(match !== null && match[0] === parameter && match.index === 0)
- {
- let val = parseFloat(parameter);
- let paramObj = new NumberParameter(val);
-
- instr.params.push(paramObj);
- return true;
- }
-
- // Parameter is an identifier (macro)
- match = parameter.match(/[A-Za-z]*/)
- if(match !== null && match[0] === parameter && match.index === 0)
- {
- let paramObj = this.macros[parameter];
- if(paramObj === undefined)
- {
- console.error("Variable \"" + parameter + "\" is not defined");
- return false;
- }
-
- instr.params.push(paramObj);
- return true;
- }
-
- // Parameter is another instruction
- 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 false;
- }
-}
diff --git a/src/shapeStyle.ts b/src/shapeStyle.ts
index 3f2ef5f..174eaab 100644
--- a/src/shapeStyle.ts
+++ b/src/shapeStyle.ts
@@ -1,4 +1,5 @@
-class ShapeStyle
+
+export class ShapeStyle
{
public strokeWidth: number;
public strokeColor: string;
diff --git a/src/shapes.ts b/src/shapes.ts
new file mode 100644
index 0000000..29454ff
--- /dev/null
+++ b/src/shapes.ts
@@ -0,0 +1,26 @@
+import { Vector2D } from "./vector.js"
+import { ShapeStyle } from "./shapeStyle.js";
+
+export function line(ctx: CanvasRenderingContext2D, from: Vector2D , to: Vector2D, style: ShapeStyle = new ShapeStyle())
+{
+ ctx.beginPath();
+ ctx.moveTo(from.x, from.y);
+ ctx.lineTo(to.x, to.y);
+
+ ctx.lineWidth = style.strokeWidth;
+ ctx.strokeStyle = style.strokeColor;
+ ctx.stroke();
+}
+
+export function circle(ctx: CanvasRenderingContext2D, center: Vector2D, radius: number, style: ShapeStyle = new ShapeStyle())
+{
+ ctx.beginPath();
+ ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI, false);
+
+ ctx.fillStyle = style.fillColor;
+ ctx.fill();
+
+ ctx.lineWidth = style.strokeWidth;
+ ctx.strokeStyle = style.strokeColor;
+ ctx.stroke();
+}
\ No newline at end of file
diff --git a/src/vector.ts b/src/vector.ts
index 64a8fdb..699eb8e 100644
--- a/src/vector.ts
+++ b/src/vector.ts
@@ -1,4 +1,4 @@
-class Vector2D
+export class Vector2D
{
public x: number;
public y: number;
diff --git a/tsconfig.json b/tsconfig.json
index 2adc248..90de336 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,8 @@
{
"compilerOptions": {
"target": "es6",
- "outFile": "./out/geometry.js",
+ // "outFile": "./out/lauchpioos.js",
+ "outDir": "./out",
"sourceRoot": "./src",
"rootDir": "./src",
"sourceMap": true