From ecdac9bfa807be3ffe0c98971e09a340aa8b1516 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Fri, 26 Nov 2021 22:41:52 +0100 Subject: [PATCH 01/19] added grammar to docs --- src/doc/syntax.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/doc/syntax.md b/src/doc/syntax.md index 14005e0..78a0092 100644 --- a/src/doc/syntax.md +++ b/src/doc/syntax.md @@ -13,4 +13,12 @@ circle(A, len(AB)) ## 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 +* `Circle circle(Point center, radius)` draws a circle at `center` and `radius` + +## Grammar +``` +instruction ::= identifier({parameter, }) +parameter ::= instruction | identifier | number +identifier ::= (A-Za-z) +number ::= (0-9)[.(0-9)] +``` \ No newline at end of file From 8140a023052a54a071b1af492a31d768f103fbf0 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Fri, 26 Nov 2021 22:53:04 +0100 Subject: [PATCH 02/19] ammended grammar --- src/doc/syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/syntax.md b/src/doc/syntax.md index 78a0092..c01cdf1 100644 --- a/src/doc/syntax.md +++ b/src/doc/syntax.md @@ -17,7 +17,7 @@ circle(A, len(AB)) ## Grammar ``` -instruction ::= identifier({parameter, }) +instruction ::= identifier({parameter, }) [-> identifer] parameter ::= instruction | identifier | number identifier ::= (A-Za-z) number ::= (0-9)[.(0-9)] From 9636514dfc709314cd802fa90836ff38baa20427 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Fri, 26 Nov 2021 22:55:12 +0100 Subject: [PATCH 03/19] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 6526241f5e9a9c46f0342d33b1fca2a7bea3e7ce Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Fri, 26 Nov 2021 23:07:28 +0100 Subject: [PATCH 04/19] compile to one single file --- src/geometry.ts | 7 ++----- src/shapeStyle.ts | 22 ++++++++++++---------- src/shapes.ts | 42 +++++++++++++++++++++--------------------- src/vector.ts | 17 ++++++++++------- tsconfig.json | 2 +- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/geometry.ts b/src/geometry.ts index 58abec9..13ef2e0 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -1,6 +1,3 @@ -import { Vector2D } from "./vector.js" -import * as shape from "./shapes.js" - function loadScript(filepath: string): string { var result = null; @@ -76,8 +73,8 @@ class Geometry extends HTMLElement private redraw() { - shape.line(this.context, new Vector2D(), new Vector2D(300, 300)); - shape.circle(this.context, new Vector2D(150, 150), 100); + Shape.line(this.context, new Util.Vector2D(), new Util.Vector2D(300, 300)); + Shape.circle(this.context, new Util.Vector2D(150, 150), 100); } } diff --git a/src/shapeStyle.ts b/src/shapeStyle.ts index 174eaab..dabedcf 100644 --- a/src/shapeStyle.ts +++ b/src/shapeStyle.ts @@ -1,14 +1,16 @@ - -export class ShapeStyle +module Util { - public strokeWidth: number; - public strokeColor: string; - public fillColor: string; - - constructor() + export class ShapeStyle { - this.strokeWidth = 1; - this.strokeColor = '#000000'; - this.fillColor = '#00000000'; + public strokeWidth: number; + public strokeColor: string; + public fillColor: string; + + constructor() + { + this.strokeWidth = 1; + this.strokeColor = '#000000'; + this.fillColor = '#00000000'; + } } } \ No newline at end of file diff --git a/src/shapes.ts b/src/shapes.ts index 29454ff..c79f31a 100644 --- a/src/shapes.ts +++ b/src/shapes.ts @@ -1,26 +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()) +module Shape { - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); + export function line(ctx: CanvasRenderingContext2D, from: Util.Vector2D , to: Util.Vector2D, style: Util.ShapeStyle = new Util.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(); -} + 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); + export function circle(ctx: CanvasRenderingContext2D, center: Util.Vector2D, radius: number, style: Util.ShapeStyle = new Util.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(); + 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 699eb8e..510867e 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -1,11 +1,14 @@ -export class Vector2D +module Util { - public x: number; - public y: number; - - constructor(x: number = 0, y: number = 0) + export class Vector2D { - this.x = x; - this.y = y; + public x: number; + public y: number; + + constructor(x: number = 0, y: number = 0) + { + this.x = x; + this.y = y; + } } } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 90de336..2ad2c5c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es6", - // "outFile": "./out/lauchpioos.js", + "outFile": "./out/geometry.js", "outDir": "./out", "sourceRoot": "./src", "rootDir": "./src", From ff9e140f1ea3b75990a1672640eba02fe4b1c981 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 03:20:55 +0100 Subject: [PATCH 05/19] added constructor --- src/geometry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geometry.ts b/src/geometry.ts index 13ef2e0..4a91c84 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -20,7 +20,7 @@ class Geometry extends HTMLElement constructor() { super(); - + console.log("constructor") if(!this.hasAttribute("src")) { return; From 191cc6af5902c349cbb5ef9d4c9aad426f3042f6 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 03:23:39 +0100 Subject: [PATCH 06/19] changed var to let --- src/geometry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geometry.ts b/src/geometry.ts index 4a91c84..b1f3932 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -1,7 +1,7 @@ function loadScript(filepath: string): string { - var result = null; - var xmlhttp = new XMLHttpRequest(); + let result = null; + let xmlhttp = new XMLHttpRequest(); xmlhttp.open("GET", filepath, false); xmlhttp.send(); if (xmlhttp.status==200) { From 04b3c0c2cabdb0ce070652b7c892184064de041b Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 05:36:37 +0100 Subject: [PATCH 07/19] merge all ts files into one js file --- src/geometry.ts | 8 ++++---- src/shapeStyle.ts | 3 +-- src/shapes.ts | 8 ++++---- src/vector.ts | 2 +- tsconfig.json | 3 +-- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/geometry.ts b/src/geometry.ts index 58abec9..abd0c9a 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -1,5 +1,5 @@ -import { Vector2D } from "./vector.js" -import * as shape from "./shapes.js" +/// +/// function loadScript(filepath: string): string { @@ -76,8 +76,8 @@ class Geometry extends HTMLElement private redraw() { - shape.line(this.context, new Vector2D(), new Vector2D(300, 300)); - shape.circle(this.context, new Vector2D(150, 150), 100); + line(this.context, new Vector2D(), new Vector2D(300, 300)); + circle(this.context, new Vector2D(150, 150), 100); } } diff --git a/src/shapeStyle.ts b/src/shapeStyle.ts index 174eaab..3f2ef5f 100644 --- a/src/shapeStyle.ts +++ b/src/shapeStyle.ts @@ -1,5 +1,4 @@ - -export class ShapeStyle +class ShapeStyle { public strokeWidth: number; public strokeColor: string; diff --git a/src/shapes.ts b/src/shapes.ts index 29454ff..374e40f 100644 --- a/src/shapes.ts +++ b/src/shapes.ts @@ -1,7 +1,7 @@ -import { Vector2D } from "./vector.js" -import { ShapeStyle } from "./shapeStyle.js"; +/// +/// -export function line(ctx: CanvasRenderingContext2D, from: Vector2D , to: Vector2D, style: ShapeStyle = new ShapeStyle()) +function line(ctx: CanvasRenderingContext2D, from: Vector2D , to: Vector2D, style: ShapeStyle = new ShapeStyle()) { ctx.beginPath(); ctx.moveTo(from.x, from.y); @@ -12,7 +12,7 @@ export function line(ctx: CanvasRenderingContext2D, from: Vector2D , to: Vector2 ctx.stroke(); } -export function circle(ctx: CanvasRenderingContext2D, center: Vector2D, radius: number, style: ShapeStyle = new ShapeStyle()) +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); diff --git a/src/vector.ts b/src/vector.ts index 699eb8e..64a8fdb 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -1,4 +1,4 @@ -export class Vector2D +class Vector2D { public x: number; public y: number; diff --git a/tsconfig.json b/tsconfig.json index 90de336..2adc248 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,7 @@ { "compilerOptions": { "target": "es6", - // "outFile": "./out/lauchpioos.js", - "outDir": "./out", + "outFile": "./out/geometry.js", "sourceRoot": "./src", "rootDir": "./src", "sourceMap": true From d01cf5790b6b114d61132cdcdce038788b12dc0a Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 20:54:04 +0100 Subject: [PATCH 08/19] started working on parser --- examples/test.gs | 5 +-- src/geometry.ts | 29 +-------------- src/parser/instruction.ts | 18 +++++++++ src/parser/parameter.ts | 35 ++++++++++++++++++ src/parser/parser.ts | 77 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 src/parser/instruction.ts create mode 100644 src/parser/parameter.ts create mode 100644 src/parser/parser.ts diff --git a/examples/test.gs b/examples/test.gs index 7c0d49b..1b5f447 100644 --- a/examples/test.gs +++ b/examples/test.gs @@ -1,3 +1,2 @@ -point(3 | 4) - -point(6 | 7) \ No newline at end of file +point(3, 4) -> A +line(A, point(7, 8)) \ No newline at end of file diff --git a/src/geometry.ts b/src/geometry.ts index 63f76b6..7443bb0 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -1,5 +1,6 @@ /// /// +/// function loadScript(filepath: string): string { @@ -32,33 +33,7 @@ class Geometry extends HTMLElement let sourceFile = this.getAttribute("src"); let content = loadScript(sourceFile); - let lines = content.split("\n"); - for(let line of lines) - { - 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; - } - } - } + let parser = new Parser(content); this.attachShadow({mode: "open"}); let canvas = document.createElement("canvas"); diff --git a/src/parser/instruction.ts b/src/parser/instruction.ts new file mode 100644 index 0000000..1a381f6 --- /dev/null +++ b/src/parser/instruction.ts @@ -0,0 +1,18 @@ +enum InstructionType +{ + Point, + Line, + Circle +} + +class Instruction +{ + public fn: InstructionType; + public params :Parameter[]; + + constructor(type: InstructionType) + { + this.fn = type; + this.params = []; + } +} \ No newline at end of file diff --git a/src/parser/parameter.ts b/src/parser/parameter.ts new file mode 100644 index 0000000..ec2fd56 --- /dev/null +++ b/src/parser/parameter.ts @@ -0,0 +1,35 @@ +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; + } +} diff --git a/src/parser/parser.ts b/src/parser/parser.ts new file mode 100644 index 0000000..9f10096 --- /dev/null +++ b/src/parser/parser.ts @@ -0,0 +1,77 @@ +/// +/// + +class Parser +{ + private instructions: Instruction[]; + + constructor(source: string) + { + this.instructions = []; + let lines = source.split(/\r?\n/); + for(let line of lines) + this.parseInstruction(line); + } + + private parseInstruction(instruction: string): boolean + { + // If the instruction is an empty line, do nothing for now + if(instruction === "") + return false; + + // match the pattern "text(text)" + let matches = instruction.match(/[A-Za-z]*\(.*\)/); + if(matches === null) // no match found + { + console.error("Invalid syntax"); + return false; + } + + if(matches.length > 1) // more than one match + { + console.error("Script may only contain one instruction per line"); + return false; + } + + let instr = matches[0]; // get the instruction + instr = instr.split(" ").join(""); + 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 + + 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); + + this.instructions.push(new Instruction(InstructionType.Point)); + for(let param of params) + { + if(!this.parseParameter(param)) + { + console.error("Error during parameter parsing"); + return false; + } + } + + return true; + } + + private parseParameter(parameter: string): boolean + { + let match = parameter.search(/\d*\.?\d*$/); + if(match === 0) + { + this.instructions[this.instructions.length - 1].params.push(new NumberParameter(4)); + return true; + } + + return false; + } +} From 79c54f3c0dad6fd8490e8bb70a5b1320c3606a71 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 22:30:20 +0100 Subject: [PATCH 09/19] first stable parser --- examples/test.gs | 2 +- src/geometry.ts | 4 ++ src/parser/instruction.ts | 35 +++++++++++- src/parser/parameter.ts | 17 ++++++ src/parser/parser.ts | 110 ++++++++++++++++++++++++++++++++------ 5 files changed, 149 insertions(+), 19 deletions(-) diff --git a/examples/test.gs b/examples/test.gs index 1b5f447..fa68652 100644 --- a/examples/test.gs +++ b/examples/test.gs @@ -1,2 +1,2 @@ -point(3, 4) -> A +[point(3, 4) -> A] line(A, point(7, 8)) \ No newline at end of file diff --git a/src/geometry.ts b/src/geometry.ts index 7443bb0..64da89e 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -34,6 +34,10 @@ class Geometry extends HTMLElement let content = loadScript(sourceFile); let parser = new Parser(content); + for(let instr of parser.instructions) + { + console.log(instr.eval()); + } this.attachShadow({mode: "open"}); let canvas = document.createElement("canvas"); diff --git a/src/parser/instruction.ts b/src/parser/instruction.ts index 1a381f6..67f49c6 100644 --- a/src/parser/instruction.ts +++ b/src/parser/instruction.ts @@ -1,3 +1,5 @@ +/// + enum InstructionType { Point, @@ -5,7 +7,7 @@ enum InstructionType Circle } -class Instruction +abstract class Instruction { public fn: InstructionType; public params :Parameter[]; @@ -15,4 +17,35 @@ class Instruction this.fn = type; 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() + ]; + } } \ No newline at end of file diff --git a/src/parser/parameter.ts b/src/parser/parameter.ts index ec2fd56..efce571 100644 --- a/src/parser/parameter.ts +++ b/src/parser/parameter.ts @@ -33,3 +33,20 @@ class NumberParameter extends Parameter 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 index 9f10096..2a74445 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -3,38 +3,53 @@ class Parser { - private instructions: Instruction[]; + public instructions: Instruction[]; + private variables: { [id: string] : InstructionParameter}; constructor(source: string) { this.instructions = []; + this.variables = {}; + let lines = source.split(/\r?\n/); 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(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)" let matches = instruction.match(/[A-Za-z]*\(.*\)/); if(matches === null) // no match found { console.error("Invalid syntax"); - return false; + return null; } if(matches.length > 1) // more than one match { console.error("Script may only contain one instruction per line"); - return false; + return null; } let instr = matches[0]; // get the instruction - instr = instr.split(" ").join(""); let paranthesisPos = instr.search(/\(/); // Find the position of the first opening paranthesis @@ -50,25 +65,86 @@ class Parser } params.push(paramlist); - this.instructions.push(new Instruction(InstructionType.Point)); - for(let param of params) + let newInstruction; + switch(symbol) { - if(!this.parseParameter(param)) + case "point": { - console.error("Error during parameter parsing"); - return false; + newInstruction = new PointInstruction(); + 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*$/); - if(match === 0) + let match = parameter.match(/\d*\.?\d*$/); + 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; } From 0b637d6870660dc4baa567aa67aa214507ac12f1 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 22:59:21 +0100 Subject: [PATCH 10/19] Update syntax.md --- src/doc/syntax.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/doc/syntax.md b/src/doc/syntax.md index c01cdf1..b66f171 100644 --- a/src/doc/syntax.md +++ b/src/doc/syntax.md @@ -1,15 +1,21 @@ # Syntax ``` -point(3 | 4) -> A -point(6 | 7) -> B +[point(3, 4) -> A] +point(6, 7) -> B line(A, B) -> AB -line(0 | 0, 100 | 100) +line(point(0, 0), point(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. + ## 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`. @@ -21,4 +27,4 @@ instruction ::= identifier({parameter, }) [-> identifer] parameter ::= instruction | identifier | number identifier ::= (A-Za-z) number ::= (0-9)[.(0-9)] -``` \ No newline at end of file +``` From 253513f62b0d67e2e0ee5d2fb419984734738720 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sat, 27 Nov 2021 23:02:34 +0100 Subject: [PATCH 11/19] Update syntax.md --- src/doc/syntax.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/doc/syntax.md b/src/doc/syntax.md index b66f171..a8039d7 100644 --- a/src/doc/syntax.md +++ b/src/doc/syntax.md @@ -16,11 +16,6 @@ These variables are immutable. Objects do not exist in this script, in fact, var Lines in brackets `[]` are "hidden". They are parsed, but will not be rendered. -## 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` - ## Grammar ``` instruction ::= identifier({parameter, }) [-> identifer] From 01165d43fb1e27472c2100ec2b7b838fcbdb291d Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sun, 28 Nov 2021 02:20:12 +0100 Subject: [PATCH 12/19] added functions to parser --- examples/test.gs | 11 ++++++++-- examples/test.gs.disable | 9 ++++++++ src/doc/todo.md | 9 ++++++++ src/parser/instruction.ts | 44 +++++++++++++++++++++++++++++++++++---- src/parser/parser.ts | 29 +++++++++++++++++++++----- 5 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 examples/test.gs.disable create mode 100644 src/doc/todo.md diff --git a/examples/test.gs b/examples/test.gs index fa68652..291c48a 100644 --- a/examples/test.gs +++ b/examples/test.gs @@ -1,2 +1,9 @@ -[point(3, 4) -> A] -line(A, point(7, 8)) \ No newline at end of file +point(0.2378, -34.389) -> A +point(2.5, 0) -> B +[point(-1, 3) -> C] + +line(A, B) -> AB +line(B, C) +line(C, A) + +circle(A, len(AB)) \ No newline at end of file diff --git a/examples/test.gs.disable b/examples/test.gs.disable new file mode 100644 index 0000000..8b2a065 --- /dev/null +++ b/examples/test.gs.disable @@ -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) diff --git a/src/doc/todo.md b/src/doc/todo.md new file mode 100644 index 0000000..e11c816 --- /dev/null +++ b/src/doc/todo.md @@ -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 \ No newline at end of file diff --git a/src/parser/instruction.ts b/src/parser/instruction.ts index 67f49c6..d0ee0fd 100644 --- a/src/parser/instruction.ts +++ b/src/parser/instruction.ts @@ -4,28 +4,32 @@ enum InstructionType { Point, Line, - Circle + Circle, + Length } abstract class Instruction { public fn: InstructionType; public params :Parameter[]; + private argc: number; - constructor(type: InstructionType) + constructor(type: InstructionType, argc: number) { this.fn = type; + this.argc = argc; this.params = []; } abstract eval(); + public getParameterCount(): number { return this.argc; } } class PointInstruction extends Instruction { constructor() { - super(InstructionType.Point); + super(InstructionType.Point, 2); } eval() @@ -38,7 +42,7 @@ class LineInstruction extends Instruction { constructor() { - super(InstructionType.Line); + super(InstructionType.Line, 2); } eval() @@ -48,4 +52,36 @@ class LineInstruction extends Instruction this.params[1].eval() ]; } +} + +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)); + } } \ No newline at end of file diff --git a/src/parser/parser.ts b/src/parser/parser.ts index 2a74445..ee57532 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -15,8 +15,9 @@ class Parser for(let line of lines) { let instr = this.parseInstruction(line); - if(!instr[0]) - this.instructions.push(instr[1]); + if(instr !== null) + if(!instr[0]) + this.instructions.push(instr[1]); } } @@ -80,6 +81,18 @@ class Parser break; } + case "circle": + { + newInstruction = new CircleInstruction(); + break; + } + + case "len": + { + newInstruction = new LengthInstruction(); + break; + } + default: { 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) { if(!this.parseParameter(newInstruction, param)) @@ -100,7 +120,6 @@ class Parser 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."); @@ -115,7 +134,7 @@ class Parser 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) { let val = parseFloat(parameter); @@ -125,7 +144,7 @@ class Parser return true; } - match = parameter.match(/[A-Za-z]/) + match = parameter.match(/[A-Za-z]*/) if(match !== null && match[0] === parameter && match.index === 0) { let paramObj = this.variables[parameter]; From 74527f68d6c3550eb29e3f7ac48d3b891d9fb07d Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sun, 28 Nov 2021 07:40:44 +0100 Subject: [PATCH 13/19] Update syntax.md --- src/doc/syntax.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/doc/syntax.md b/src/doc/syntax.md index a8039d7..173f3ac 100644 --- a/src/doc/syntax.md +++ b/src/doc/syntax.md @@ -4,7 +4,7 @@ [point(3, 4) -> A] point(6, 7) -> B -line(A, B) -> AB +line[color=red, weight=4](A, B) -> AB line(point(0, 0), point(100, 100)) circle(A, len(AB)) @@ -16,6 +16,12 @@ These variables are immutable. Objects do not exist in this script, in fact, var 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] From f105e32af51580a7ab309940ca29f30a077f21de Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sun, 28 Nov 2021 15:28:50 +0100 Subject: [PATCH 14/19] refactored instruction creation --- src/parser/instructionFactory.ts | 19 ++++++++++++++++ src/parser/parser.ts | 37 +++++--------------------------- 2 files changed, 24 insertions(+), 32 deletions(-) create mode 100644 src/parser/instructionFactory.ts diff --git a/src/parser/instructionFactory.ts b/src/parser/instructionFactory.ts new file mode 100644 index 0000000..e1e9d5a --- /dev/null +++ b/src/parser/instructionFactory.ts @@ -0,0 +1,19 @@ +/// + +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/parser.ts b/src/parser/parser.ts index ee57532..2bce9b4 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -1,5 +1,5 @@ /// -/// +/// class Parser { @@ -66,38 +66,11 @@ class Parser } params.push(paramlist); - let newInstruction; - switch(symbol) + let newInstruction = InstructionFactory.createInstruction(symbol); + if(newInstruction === null) { - case "point": - { - newInstruction = new PointInstruction(); - break; - } - - case "line": - { - newInstruction = new LineInstruction(); - break; - } - - case "circle": - { - newInstruction = new CircleInstruction(); - break; - } - - case "len": - { - newInstruction = new LengthInstruction(); - break; - } - - default: - { - console.error("Unknown instruction \"" + symbol + "\""); - return null; - } + console.error("Unknown instruction: \"" + symbol + "\""); + return null; } let expectedArgs = newInstruction.getParameterCount(); From b43f547ae5ef7abf0211a53d48ee0def1c678cd4 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sun, 28 Nov 2021 15:39:57 +0100 Subject: [PATCH 15/19] improved error handling --- src/geometry.ts | 6 +++++ src/parser/parser.ts | 53 +++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/geometry.ts b/src/geometry.ts index 64da89e..d59cac6 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -34,6 +34,12 @@ class Geometry extends HTMLElement let content = loadScript(sourceFile); let parser = new Parser(content); + if(!parser.good()) + { + console.error("Failed to create parser for script " + sourceFile); + return; + } + for(let instr of parser.instructions) { console.log(instr.eval()); diff --git a/src/parser/parser.ts b/src/parser/parser.ts index 2bce9b4..f09b7aa 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -5,22 +5,43 @@ class Parser { public instructions: Instruction[]; private variables: { [id: string] : InstructionParameter}; + private success: boolean; constructor(source: string) { this.instructions = []; this.variables = {}; + this.success = false; let lines = source.split(/\r?\n/); + let currentLine = 1; 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[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 @@ -39,16 +60,10 @@ class Parser // match the pattern "text(text)" let matches = instruction.match(/[A-Za-z]*\(.*\)/); if(matches === null) // no match found - { - console.error("Invalid syntax"); - return null; - } + throw new Error("Line does not contain a valid instruction."); if(matches.length > 1) // more than one match - { - console.error("Script may only contain one instruction per line"); - return null; - } + 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 @@ -68,25 +83,16 @@ class Parser let newInstruction = InstructionFactory.createInstruction(symbol); if(newInstruction === null) - { - console.error("Unknown instruction: \"" + symbol + "\""); - return null; - } + throw new Error("Unknown instruction: \"" + symbol + "\""); 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; - } + throw new Error("Wrong number of arguments for instruction \"" + symbol + "\". Expected " + expectedArgs + " arguments but received " + params.length + " instead."); for(let param of params) { if(!this.parseParameter(newInstruction, param)) - { - console.error("Error during parameter parsing: \"" + param + "\" failed to be parsed."); - return null; - } + throw new Error("Error during parameter parsing: \"" + param + "\" failed to be parsed."); } let assignment = instruction.search(/->/); @@ -94,10 +100,7 @@ class Parser { let variableName = instruction.substring(assignment + 2, instruction.length); if(variableName in this.variables) - { - console.error("Redefinition of variable \"" + variableName + "\" is not allowed."); - return null; - } + throw new Error("Redefinition of variable \"" + variableName + "\" is not allowed."); this.variables[variableName] = new InstructionParameter(newInstruction); } From ee6fc7b02d60ca518726a1080e649f74b91280fa Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sun, 28 Nov 2021 15:46:47 +0100 Subject: [PATCH 16/19] added comments --- src/parser/instruction.ts | 5 +++-- src/parser/parser.ts | 30 ++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/parser/instruction.ts b/src/parser/instruction.ts index d0ee0fd..764a139 100644 --- a/src/parser/instruction.ts +++ b/src/parser/instruction.ts @@ -10,19 +10,20 @@ enum InstructionType abstract class Instruction { - public fn: InstructionType; + private type: InstructionType; public params :Parameter[]; private argc: number; constructor(type: InstructionType, argc: number) { - this.fn = type; + 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 diff --git a/src/parser/parser.ts b/src/parser/parser.ts index f09b7aa..3dd1fb5 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -1,16 +1,24 @@ /// /// +/** + * @brief Turns a .gs script into a list of instructions to be passed to the renderer + */ class Parser { - public instructions: Instruction[]; - private variables: { [id: string] : InstructionParameter}; + 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.variables = {}; + this.macros = {}; this.success = false; let lines = source.split(/\r?\n/); @@ -30,6 +38,7 @@ class Parser 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]); @@ -48,6 +57,7 @@ class Parser if(instruction === "") return null; + // Handle [] syntax. Lines in [] will be processed but not rendered let hidden = false; if(instruction[0] === "[" && instruction[instruction.length - 1] === "]") { @@ -72,6 +82,7 @@ class Parser 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) @@ -81,28 +92,32 @@ class Parser } 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.variables) + if(variableName in this.macros) throw new Error("Redefinition of variable \"" + variableName + "\" is not allowed."); - this.variables[variableName] = new InstructionParameter(newInstruction); + this.macros[variableName] = new InstructionParameter(newInstruction); } return [hidden, newInstruction]; @@ -110,6 +125,7 @@ class Parser 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) { @@ -120,10 +136,11 @@ class Parser 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.variables[parameter]; + let paramObj = this.macros[parameter]; if(paramObj === undefined) { console.error("Variable \"" + parameter + "\" is not defined"); @@ -134,6 +151,7 @@ class Parser return true; } + // Parameter is another instruction match = parameter.match(/[A-Za-z]*\(.*\)/) if(match !== null && match[0] === parameter && match.index === 0) { From 097931d2924a255c5873e5bdeb247d5a37ff1b58 Mon Sep 17 00:00:00 2001 From: epioos <46408068+epioos@users.noreply.github.com> Date: Tue, 30 Nov 2021 00:26:32 +0100 Subject: [PATCH 17/19] addes shape classes --- src/shapes.ts | 70 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/shapes.ts b/src/shapes.ts index 29454ff..ea26817 100644 --- a/src/shapes.ts +++ b/src/shapes.ts @@ -1,26 +1,64 @@ import { Vector2D } from "./vector.js" import { ShapeStyle } from "./shapeStyle.js"; -export function line(ctx: CanvasRenderingContext2D, from: Vector2D , to: Vector2D, style: ShapeStyle = new ShapeStyle()) +abstract class Shape { - ctx.beginPath(); - ctx.moveTo(from.x, from.y); - ctx.lineTo(to.x, to.y); + protected ctx: CanvasRenderingContext2D + protected style: ShapeStyle - ctx.lineWidth = style.strokeWidth; - ctx.strokeStyle = style.strokeColor; - ctx.stroke(); + constructor(ctx) { + this.ctx = ctx + this.style = new ShapeStyle() + } + + abstract draw() } -export function circle(ctx: CanvasRenderingContext2D, center: Vector2D, radius: number, style: ShapeStyle = new ShapeStyle()) +class Line extends Shape { - ctx.beginPath(); - ctx.arc(center.x, center.y, radius, 0, 2 * Math.PI, false); + private from: Vector2D + private to: Vector2D - ctx.fillStyle = style.fillColor; - ctx.fill(); - - ctx.lineWidth = style.strokeWidth; - ctx.strokeStyle = style.strokeColor; - ctx.stroke(); + 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 From d06c2c60786196fef33a213e6d50f7bedf16a175 Mon Sep 17 00:00:00 2001 From: epioos <46408068+epioos@users.noreply.github.com> Date: Tue, 30 Nov 2021 00:57:09 +0100 Subject: [PATCH 18/19] added polygon class --- src/geometry.ts | 23 ++++++++++++++++++++--- src/gfx/polygon.ts | 30 ++++++++++++++++++++++++++++++ src/{ => gfx}/shapes.ts | 4 ++-- 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 src/gfx/polygon.ts rename src/{ => gfx}/shapes.ts (93%) diff --git a/src/geometry.ts b/src/geometry.ts index 64da89e..4d13b06 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -1,5 +1,5 @@ /// -/// +/// /// function loadScript(filepath: string): string @@ -17,6 +17,7 @@ function loadScript(filepath: string): string class Geometry extends HTMLElement { + private shapes: Shape[]; private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; private sourceFile: string; @@ -50,13 +51,29 @@ class Geometry extends HTMLElement this.shadowRoot.append(this.canvas); + + this.shapes = [] + this.shapes.push(new Circle(this.context, new Vector2D(150, 150), 100)) + this.shapes.push(new Line(this.context, new Vector2D(), new Vector2D(300, 300))) + + this.shapes.push(new Polygon(this.context, + [ + new Vector2D(150, 150), + new Vector2D(150, 250), + new Vector2D(250, 250), + new Vector2D(250, 150), + new Vector2D(300, 300), + new Vector2D(250, 350), + ])) this.redraw(); } private redraw() { - line(this.context, new Vector2D(), new Vector2D(300, 300)); - circle(this.context, new Vector2D(150, 150), 100); + for (let shape of this.shapes) + { + shape.draw() + } } } diff --git a/src/gfx/polygon.ts b/src/gfx/polygon.ts new file mode 100644 index 0000000..5ce58d4 --- /dev/null +++ b/src/gfx/polygon.ts @@ -0,0 +1,30 @@ +/// + +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/shapes.ts b/src/gfx/shapes.ts similarity index 93% rename from src/shapes.ts rename to src/gfx/shapes.ts index 4d2fd2d..4131d79 100644 --- a/src/shapes.ts +++ b/src/gfx/shapes.ts @@ -1,5 +1,5 @@ -/// -/// +/// +/// abstract class Shape { From a502abf05190cbb4b1be9130287e19581a25d2bb Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Tue, 30 Nov 2021 14:08:50 +0100 Subject: [PATCH 19/19] basic parser to renderer pipeline --- examples/test.gs | 9 +++++---- src/geometry.ts | 38 +++++++++++++++++++++----------------- src/parser/instruction.ts | 2 +- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/examples/test.gs b/examples/test.gs index 291c48a..49f1677 100644 --- a/examples/test.gs +++ b/examples/test.gs @@ -1,9 +1,10 @@ -point(0.2378, -34.389) -> A -point(2.5, 0) -> B -[point(-1, 3) -> C] +point(200, 300) -> A +point(400, 300) -> B +[point(300, 128) -> C] line(A, B) -> AB line(B, C) line(C, A) -circle(A, len(AB)) \ No newline at end of file +circle(A, len(AB)) +circle(B, len(AB)) \ No newline at end of file diff --git a/src/geometry.ts b/src/geometry.ts index 08a7dfc..584b633 100644 --- a/src/geometry.ts +++ b/src/geometry.ts @@ -41,14 +41,9 @@ class Geometry extends HTMLElement return; } - for(let instr of parser.instructions) - { - console.log(instr.eval()); - } - this.attachShadow({mode: "open"}); let canvas = document.createElement("canvas"); - canvas.width = 500; + canvas.width = 700; canvas.height = 500; let context = canvas.getContext("2d"); @@ -59,18 +54,27 @@ class Geometry extends HTMLElement this.shapes = [] - this.shapes.push(new Circle(this.context, new Vector2D(150, 150), 100)) - this.shapes.push(new Line(this.context, new Vector2D(), new Vector2D(300, 300))) + 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.shapes.push(new Polygon(this.context, - [ - new Vector2D(150, 150), - new Vector2D(150, 250), - new Vector2D(250, 250), - new Vector2D(250, 150), - new Vector2D(300, 300), - new Vector2D(250, 350), - ])) this.redraw(); } diff --git a/src/parser/instruction.ts b/src/parser/instruction.ts index 764a139..87848b9 100644 --- a/src/parser/instruction.ts +++ b/src/parser/instruction.ts @@ -59,7 +59,7 @@ class CircleInstruction extends Instruction { constructor() { - super(InstructionType.Line, 2); + super(InstructionType.Circle, 2); } eval()