circuitscript 0.0.22 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/BaseVisitor.js +487 -0
- package/dist/cjs/SemanticTokenVisitor.js +218 -0
- package/dist/cjs/SymbolValidatorVisitor.js +233 -0
- package/dist/cjs/antlr/CircuitScriptLexer.js +302 -0
- package/dist/cjs/antlr/CircuitScriptParser.js +5128 -0
- package/dist/cjs/antlr/CircuitScriptVisitor.js +7 -0
- package/dist/cjs/draw_symbols.js +819 -0
- package/dist/cjs/execute.js +778 -0
- package/{src/export.ts → dist/cjs/export.js} +34 -56
- package/dist/cjs/fonts.js +4 -0
- package/dist/cjs/geometry.js +450 -0
- package/dist/cjs/globals.js +60 -0
- package/dist/cjs/helpers.js +269 -0
- package/dist/cjs/index.js +31 -0
- package/{src/layout.ts → dist/cjs/layout.js} +421 -1002
- package/dist/cjs/lexer.js +111 -0
- package/dist/cjs/logger.js +17 -0
- package/dist/cjs/main.js +82 -0
- package/dist/cjs/objects/ClassComponent.js +145 -0
- package/dist/cjs/objects/ExecutionScope.js +135 -0
- package/dist/cjs/objects/Frame.js +22 -0
- package/{src/objects/Net.ts → dist/cjs/objects/Net.js} +9 -24
- package/dist/cjs/objects/ParamDefinition.js +42 -0
- package/dist/cjs/objects/PinDefinition.js +31 -0
- package/dist/cjs/objects/PinTypes.js +11 -0
- package/dist/cjs/objects/Wire.js +9 -0
- package/dist/cjs/objects/types.js +15 -0
- package/dist/cjs/parser.js +70 -0
- package/dist/cjs/regenerate-tests.js +23 -0
- package/dist/cjs/render.js +155 -0
- package/{src/server.ts → dist/cjs/server.js} +15 -21
- package/dist/cjs/sizing.js +105 -0
- package/{src/utils.ts → dist/cjs/utils.js} +25 -35
- package/dist/cjs/validate.js +81 -0
- package/dist/cjs/visitor.js +844 -0
- package/dist/esm/BaseVisitor.mjs +488 -0
- package/dist/esm/SemanticTokenVisitor.mjs +215 -0
- package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
- package/dist/esm/antlr/CircuitScriptLexer.mjs +276 -0
- package/dist/esm/antlr/CircuitScriptParser.mjs +5038 -0
- package/{build/src/antlr/CircuitScriptVisitor.js → dist/esm/antlr/CircuitScriptVisitor.mjs} +8 -3
- package/{build/src/draw_symbols.js → dist/esm/draw_symbols.mjs} +78 -33
- package/{build/src/execute.js → dist/esm/execute.mjs} +59 -60
- package/{build/src/export.js → dist/esm/export.mjs} +2 -2
- package/{build/src/geometry.js → dist/esm/geometry.mjs} +31 -15
- package/dist/esm/helpers.mjs +252 -0
- package/dist/esm/index.mjs +15 -0
- package/{build/src/layout.js → dist/esm/layout.mjs} +19 -11
- package/{build/src/lexer.js → dist/esm/lexer.mjs} +10 -10
- package/{build/src/main.js → dist/esm/main.mjs} +9 -14
- package/{build/src/objects/ClassComponent.js → dist/esm/objects/ClassComponent.mjs} +6 -3
- package/{build/src/objects/ExecutionScope.js → dist/esm/objects/ExecutionScope.mjs} +1 -0
- package/{build/src/objects/PinDefinition.js → dist/esm/objects/PinDefinition.mjs} +1 -1
- package/dist/esm/objects/types.mjs +12 -0
- package/dist/esm/parser.mjs +64 -0
- package/{build/src/regenerate-tests.js → dist/esm/regenerate-tests.mjs} +1 -1
- package/{build/src/render.js → dist/esm/render.mjs} +7 -24
- package/{build/src/sizing.js → dist/esm/sizing.mjs} +22 -8
- package/{src/main.ts → dist/esm/validate.mjs} +31 -62
- package/dist/esm/visitor.mjs +838 -0
- package/dist/types/BaseVisitor.d.ts +69 -0
- package/dist/types/SemanticTokenVisitor.d.ts +36 -0
- package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
- package/{build/src → dist/types}/antlr/CircuitScriptLexer.d.ts +28 -27
- package/dist/types/antlr/CircuitScriptParser.d.ts +719 -0
- package/{build/src → dist/types}/antlr/CircuitScriptVisitor.d.ts +69 -59
- package/{build/src → dist/types}/draw_symbols.d.ts +11 -2
- package/{build/src → dist/types}/execute.d.ts +6 -9
- package/{build/src → dist/types}/geometry.d.ts +5 -1
- package/dist/types/helpers.d.ts +40 -0
- package/dist/types/index.d.ts +15 -0
- package/{build/src → dist/types}/layout.d.ts +10 -10
- package/{build/src → dist/types}/lexer.d.ts +2 -2
- package/{build/src → dist/types}/objects/ClassComponent.d.ts +2 -2
- package/{build/src → dist/types}/objects/ExecutionScope.d.ts +4 -1
- package/{build/src → dist/types}/objects/PinDefinition.d.ts +1 -1
- package/{build/src → dist/types}/objects/types.d.ts +5 -0
- package/dist/types/parser.d.ts +25 -0
- package/{build/src → dist/types}/render.d.ts +1 -1
- package/{build/src → dist/types}/sizing.d.ts +3 -1
- package/dist/types/validate.d.ts +2 -0
- package/dist/types/visitor.d.ts +80 -0
- package/libs/lib.cst +0 -2
- package/package.json +38 -15
- package/.editorconfig +0 -15
- package/.eslintignore +0 -1
- package/.eslintrc.json +0 -27
- package/.gitlab-ci.yml +0 -81
- package/.prettierignore +0 -8
- package/.prettierrc +0 -16
- package/__tests__/expectedResults.ts +0 -657
- package/__tests__/helpers.ts +0 -82
- package/__tests__/parseScripts.ts +0 -593
- package/__tests__/renderData/script1.cst +0 -58
- package/__tests__/renderData/script1.cst.svg +0 -1
- package/__tests__/renderData/script2.cst +0 -16
- package/__tests__/renderData/script2.cst.svg +0 -1
- package/__tests__/renderData/script3.cst +0 -30
- package/__tests__/renderData/script3.cst.svg +0 -1
- package/__tests__/renderData/script4.cst +0 -54
- package/__tests__/renderData/script4.cst.svg +0 -1
- package/__tests__/renderData/script5.cst +0 -23
- package/__tests__/renderData/script5.cst.svg +0 -1
- package/__tests__/renderData/script6.cst +0 -28
- package/__tests__/renderData/script6.cst.svg +0 -1
- package/__tests__/renderData/script7.cst +0 -26
- package/__tests__/renderData/script7.cst.svg +0 -1
- package/__tests__/renderData/script8.cst +0 -37
- package/__tests__/renderData/script8.cst.svg +0 -1
- package/__tests__/testCLI.ts +0 -68
- package/__tests__/testMathOps.ts +0 -36
- package/__tests__/testMergeWires.ts +0 -141
- package/__tests__/testParse.ts +0 -263
- package/__tests__/testRender.ts +0 -38
- package/build/src/antlr/CircuitScriptLexer.js +0 -287
- package/build/src/antlr/CircuitScriptParser.d.ts +0 -674
- package/build/src/antlr/CircuitScriptParser.js +0 -4841
- package/build/src/helpers.d.ts +0 -1
- package/build/src/helpers.js +0 -73
- package/build/src/objects/types.js +0 -6
- package/build/src/parser.js +0 -69
- package/build/src/visitor.d.ts +0 -133
- package/build/src/visitor.js +0 -1154
- package/documentation.md +0 -238
- package/examples/example_arduino_uno.cst +0 -1146
- package/examples/example_garden_pump.cst +0 -567
- package/examples/lib.cst +0 -185
- package/jest.config.js +0 -23
- package/refresh.html +0 -42
- package/server.cjs +0 -50
- package/src/antlr/CircuitScript.g4 +0 -209
- package/src/antlr/CircuitScriptLexer.ts +0 -317
- package/src/antlr/CircuitScriptParser.ts +0 -4979
- package/src/antlr/CircuitScriptVisitor.ts +0 -420
- package/src/draw_symbols.ts +0 -1085
- package/src/execute.ts +0 -1227
- package/src/fonts.ts +0 -1
- package/src/geometry.ts +0 -638
- package/src/globals.ts +0 -67
- package/src/helpers.ts +0 -114
- package/src/lexer.ts +0 -151
- package/src/logger.ts +0 -17
- package/src/objects/ClassComponent.ts +0 -223
- package/src/objects/ExecutionScope.ts +0 -201
- package/src/objects/Frame.ts +0 -20
- package/src/objects/ParamDefinition.ts +0 -49
- package/src/objects/PinDefinition.ts +0 -49
- package/src/objects/PinTypes.ts +0 -7
- package/src/objects/Wire.ts +0 -19
- package/src/objects/types.ts +0 -66
- package/src/parser.ts +0 -106
- package/src/regenerate-tests.ts +0 -25
- package/src/render.ts +0 -260
- package/src/sizing.ts +0 -96
- package/src/visitor.ts +0 -1691
- package/tsconfig.json +0 -27
- package/tsconfig.release.json +0 -8
- /package/{build/src/fonts.js → dist/esm/fonts.mjs} +0 -0
- /package/{build/src/globals.js → dist/esm/globals.mjs} +0 -0
- /package/{build/src/logger.js → dist/esm/logger.mjs} +0 -0
- /package/{build/src/objects/Frame.js → dist/esm/objects/Frame.mjs} +0 -0
- /package/{build/src/objects/Net.js → dist/esm/objects/Net.mjs} +0 -0
- /package/{build/src/objects/ParamDefinition.js → dist/esm/objects/ParamDefinition.mjs} +0 -0
- /package/{build/src/objects/PinTypes.js → dist/esm/objects/PinTypes.mjs} +0 -0
- /package/{build/src/objects/Wire.js → dist/esm/objects/Wire.mjs} +0 -0
- /package/{build/src/server.js → dist/esm/server.mjs} +0 -0
- /package/{build/src/utils.js → dist/esm/utils.mjs} +0 -0
- /package/{build/src → dist/types}/export.d.ts +0 -0
- /package/{build/src → dist/types}/fonts.d.ts +0 -0
- /package/{build/src → dist/types}/globals.d.ts +0 -0
- /package/{build/src → dist/types}/logger.d.ts +0 -0
- /package/{build/src → dist/types}/main.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Frame.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Net.d.ts +0 -0
- /package/{build/src → dist/types}/objects/ParamDefinition.d.ts +0 -0
- /package/{build/src → dist/types}/objects/PinTypes.d.ts +0 -0
- /package/{build/src → dist/types}/objects/Wire.d.ts +0 -0
- /package/{build/src → dist/types}/regenerate-tests.d.ts +0 -0
- /package/{build/src → dist/types}/server.d.ts +0 -0
- /package/{build/src → dist/types}/utils.d.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Flatten from '@flatten-js/core';
|
|
2
|
-
import { measureTextSize2 } from './sizing.
|
|
3
|
-
import { defaultFont } from './globals.
|
|
4
|
-
import { NumericValue } from './objects/ParamDefinition.
|
|
2
|
+
import { measureTextSize2 } from './sizing.mjs';
|
|
3
|
+
import { defaultFont } from './globals.mjs';
|
|
4
|
+
import { NumericValue } from './objects/ParamDefinition.mjs';
|
|
5
5
|
export class Label extends Flatten.Polygon {
|
|
6
6
|
id;
|
|
7
7
|
text;
|
|
@@ -52,8 +52,12 @@ export class Label extends Flatten.Polygon {
|
|
|
52
52
|
return new Label(id, useText, [x, y], polygon, style, box);
|
|
53
53
|
}
|
|
54
54
|
rotate(angle, origin) {
|
|
55
|
-
const
|
|
56
|
-
return new Label(this.id, this.text, this.anchorPoint,
|
|
55
|
+
const feature = super.rotate(angle, origin);
|
|
56
|
+
return new Label(this.id, this.text, this.anchorPoint, feature, this.style, this.textMeasurementBounds);
|
|
57
|
+
}
|
|
58
|
+
transform(matrix) {
|
|
59
|
+
const feature = super.transform(matrix);
|
|
60
|
+
return new Label(this.id, this.text, this.anchorPoint, feature, this.style, this.textMeasurementBounds);
|
|
57
61
|
}
|
|
58
62
|
getLabelPosition() {
|
|
59
63
|
return this.anchorPoint;
|
|
@@ -103,6 +107,10 @@ export class Geometry {
|
|
|
103
107
|
const angleRads = angleDegrees * Math.PI / 180;
|
|
104
108
|
return feature.rotate(angleRads, Geometry.point(center[0], center[1]));
|
|
105
109
|
}
|
|
110
|
+
static flip(feature, flipX, flipY) {
|
|
111
|
+
const flipMatrix = (new Flatten.Matrix()).scale(flipX === 0 ? 1 : -1, flipY == 0 ? 1 : -1);
|
|
112
|
+
return feature.transform(flipMatrix);
|
|
113
|
+
}
|
|
106
114
|
static groupRotate(features, angle, center) {
|
|
107
115
|
const angleRads = angle * Math.PI / 180;
|
|
108
116
|
const rotateAboutPoint = Geometry.point(center[0], center[1]);
|
|
@@ -110,6 +118,12 @@ export class Geometry {
|
|
|
110
118
|
return feature.rotate(angleRads, rotateAboutPoint);
|
|
111
119
|
});
|
|
112
120
|
}
|
|
121
|
+
static groupFlip(features, flipX, flipY) {
|
|
122
|
+
const flipMatrix = (new Flatten.Matrix()).scale(flipX === 0 ? 1 : -1, flipY == 0 ? 1 : -1);
|
|
123
|
+
return features.map(feature => {
|
|
124
|
+
return feature.transform(flipMatrix);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
113
127
|
static groupBounds(features) {
|
|
114
128
|
let minX = Number.POSITIVE_INFINITY;
|
|
115
129
|
let minY = Number.POSITIVE_INFINITY;
|
|
@@ -171,9 +185,7 @@ export class Geometry {
|
|
|
171
185
|
}
|
|
172
186
|
const startPoint = getArcPointRadians(x, y, radius, item.startAngle);
|
|
173
187
|
const endPoint = getArcPointRadians(x, y, radius, useEndAngle);
|
|
174
|
-
paths.push('M
|
|
175
|
-
+ 'A ' + radius + ' ' + radius + ' 0 1 1 '
|
|
176
|
-
+ endPoint[0] + ' ' + endPoint[1] + extraEnd);
|
|
188
|
+
paths.push('M', startPoint[0], startPoint[1], 'A', radius, radius, 0, 1, 1, endPoint[0], endPoint[1], extraEnd);
|
|
177
189
|
}
|
|
178
190
|
else {
|
|
179
191
|
const coords = Geometry.getCoords(item);
|
|
@@ -183,19 +195,27 @@ export class Geometry {
|
|
|
183
195
|
for (let i = 0; i < coords.length; i++) {
|
|
184
196
|
const [x, y] = coords[i];
|
|
185
197
|
const command = (i === 0) ? 'M' : 'L';
|
|
186
|
-
path.push(`${command}
|
|
198
|
+
path.push(`${command}`, x, y);
|
|
187
199
|
}
|
|
188
200
|
if (isClosedPolygon) {
|
|
189
201
|
path.push('Z');
|
|
190
202
|
}
|
|
191
|
-
paths.push(path
|
|
203
|
+
paths.push(...path);
|
|
192
204
|
}
|
|
193
205
|
});
|
|
194
206
|
return {
|
|
195
|
-
path:
|
|
207
|
+
path: this.roundPathValues(paths),
|
|
196
208
|
isClosedPolygon,
|
|
197
209
|
};
|
|
198
210
|
}
|
|
211
|
+
static roundPathValues(pathItems) {
|
|
212
|
+
return pathItems.map(item => {
|
|
213
|
+
if (typeof item === 'number') {
|
|
214
|
+
return (+item.toFixed(7)).toString();
|
|
215
|
+
}
|
|
216
|
+
return item;
|
|
217
|
+
}).join(" ");
|
|
218
|
+
}
|
|
199
219
|
static angle(dx, dy) {
|
|
200
220
|
const line = new Flatten.Segment(new Flatten.Point(0, 0), new Flatten.Point(dx, dy));
|
|
201
221
|
return line.slope * 180 / Math.PI;
|
|
@@ -418,10 +438,6 @@ export var VerticalAlign;
|
|
|
418
438
|
VerticalAlign["Middle"] = "middle";
|
|
419
439
|
VerticalAlign["Bottom"] = "bottom";
|
|
420
440
|
})(VerticalAlign || (VerticalAlign = {}));
|
|
421
|
-
function getArcPoint(centerX, centerY, radius, angleDegrees) {
|
|
422
|
-
const angleRads = angleDegrees * Math.PI / 180;
|
|
423
|
-
return getArcPointRadians(centerX, centerY, radius, angleRads);
|
|
424
|
-
}
|
|
425
441
|
function getArcPointRadians(centerX, centerY, radius, angleRads) {
|
|
426
442
|
const dx = Math.cos(angleRads);
|
|
427
443
|
const dy = Math.sin(angleRads);
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { generateKiCADNetList } from "./export.mjs";
|
|
3
|
+
import { LayoutEngine } from "./layout.mjs";
|
|
4
|
+
import { SequenceAction } from "./objects/ExecutionScope.mjs";
|
|
5
|
+
import { parseFileWithVisitor } from "./parser.mjs";
|
|
6
|
+
import { generateSVG2 } from "./render.mjs";
|
|
7
|
+
import { SimpleStopwatch } from "./utils.mjs";
|
|
8
|
+
import { ParserVisitor, VisitorExecutionException } from "./visitor.mjs";
|
|
9
|
+
import { createContext } from "this-file";
|
|
10
|
+
import { SymbolValidatorResolveVisitor, SymbolValidatorVisitor } from "./SymbolValidatorVisitor.mjs";
|
|
11
|
+
import { BaseErrorListener, CharStream, CommonTokenStream, DefaultErrorStrategy } from "antlr4ng";
|
|
12
|
+
import { MainLexer } from "./lexer.mjs";
|
|
13
|
+
import { CircuitScriptParser } from "./antlr/CircuitScriptParser.mjs";
|
|
14
|
+
import { prepareTokens, SemanticTokensVisitor } from "./SemanticTokenVisitor.mjs";
|
|
15
|
+
import path from "path";
|
|
16
|
+
export var JSModuleType;
|
|
17
|
+
(function (JSModuleType) {
|
|
18
|
+
JSModuleType["CommonJs"] = "cjs";
|
|
19
|
+
JSModuleType["ESM"] = "mjs";
|
|
20
|
+
})(JSModuleType || (JSModuleType = {}));
|
|
21
|
+
export function prepareFile(textData) {
|
|
22
|
+
const chars = CharStream.fromString(textData);
|
|
23
|
+
const lexer = new MainLexer(chars);
|
|
24
|
+
const lexerTimer = new SimpleStopwatch();
|
|
25
|
+
const tokens = new CommonTokenStream(lexer);
|
|
26
|
+
tokens.fill();
|
|
27
|
+
const lexerTimeTaken = lexerTimer.lap();
|
|
28
|
+
const parser = new CircuitScriptParser(tokens);
|
|
29
|
+
return {
|
|
30
|
+
parser,
|
|
31
|
+
lexer,
|
|
32
|
+
lexerTimeTaken,
|
|
33
|
+
tokens
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function getScriptText(filePath) {
|
|
37
|
+
try {
|
|
38
|
+
return readFileSync(filePath, { encoding: 'utf-8' });
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function getSemanticTokens(scriptData, options) {
|
|
45
|
+
const { parser, lexer, tokens } = prepareFile(scriptData);
|
|
46
|
+
const tree = parser.script();
|
|
47
|
+
const { currentDirectory = null, defaultLibsPath, } = options;
|
|
48
|
+
const visitor = new SemanticTokensVisitor(true, null, currentDirectory, defaultLibsPath, lexer, scriptData);
|
|
49
|
+
parser.removeErrorListeners();
|
|
50
|
+
visitor.onImportFile = (visitor, textData) => {
|
|
51
|
+
let hasError = false;
|
|
52
|
+
let hasParseError = false;
|
|
53
|
+
if (textData !== null) {
|
|
54
|
+
const { parser } = prepareFile(textData);
|
|
55
|
+
const tree = parser.script();
|
|
56
|
+
try {
|
|
57
|
+
visitor.visit(tree);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.log('Error while parsing: ', err);
|
|
61
|
+
hasParseError = true;
|
|
62
|
+
hasError = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log('File does not exist');
|
|
67
|
+
hasError = true;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
hasError, hasParseError
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
visitor.visit(tree);
|
|
74
|
+
const semanticTokens = visitor.getTokens();
|
|
75
|
+
const parsedTokens = prepareTokens(tokens.getTokens(), lexer, scriptData);
|
|
76
|
+
const finalParsedTokens = [];
|
|
77
|
+
parsedTokens.forEach(token => {
|
|
78
|
+
const location = `${token.line}_${token.column}`;
|
|
79
|
+
if (semanticTokens.has(location)) {
|
|
80
|
+
finalParsedTokens.push(semanticTokens.get(location));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
finalParsedTokens.push(token);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
visitor,
|
|
88
|
+
parsedTokens: finalParsedTokens
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
class TokenErrorListener extends BaseErrorListener {
|
|
92
|
+
syntaxError(recognizer, offendingSymbol, line, column, msg, e) {
|
|
93
|
+
console.log(msg);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export class ParseErrorStrategy extends DefaultErrorStrategy {
|
|
97
|
+
reportUnwantedToken(recognizer) {
|
|
98
|
+
if (this.inErrorRecoveryMode(recognizer)) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.beginErrorCondition(recognizer);
|
|
102
|
+
const t = recognizer.getCurrentToken();
|
|
103
|
+
const tokenName = this.getTokenErrorDisplay(t);
|
|
104
|
+
const msg = "extraneous input " + tokenName;
|
|
105
|
+
recognizer.notifyErrorListeners(msg, t, null);
|
|
106
|
+
this.endErrorCondition(recognizer);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export function validateScript(scriptData, options) {
|
|
110
|
+
const { parser } = prepareFile(scriptData);
|
|
111
|
+
parser.removeErrorListeners();
|
|
112
|
+
parser.errorHandler = new ParseErrorStrategy();
|
|
113
|
+
parser.addErrorListener(new TokenErrorListener());
|
|
114
|
+
const tree = parser.script();
|
|
115
|
+
const { currentDirectory = null, defaultLibsPath, } = options;
|
|
116
|
+
const visitor = new SymbolValidatorVisitor(true, null, currentDirectory, defaultLibsPath);
|
|
117
|
+
visitor.onImportFile = (visitor, textData) => {
|
|
118
|
+
let hasError = false;
|
|
119
|
+
let hasParseError = false;
|
|
120
|
+
if (textData !== null) {
|
|
121
|
+
const { parser } = prepareFile(textData);
|
|
122
|
+
const tree = parser.script();
|
|
123
|
+
try {
|
|
124
|
+
visitor.visit(tree);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
console.log('got an error while parsing tree: ', err);
|
|
128
|
+
hasParseError = true;
|
|
129
|
+
hasError = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
console.log('file does not exist!');
|
|
134
|
+
hasError = true;
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
hasError, hasParseError
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
visitor.visit(tree);
|
|
141
|
+
const symbolTable = visitor.getSymbols();
|
|
142
|
+
symbolTable.clearUndefined();
|
|
143
|
+
const visitorResolver = new SymbolValidatorResolveVisitor(true, null, currentDirectory, defaultLibsPath);
|
|
144
|
+
visitorResolver.setSymbols(visitor.getSymbols());
|
|
145
|
+
visitorResolver.onImportFile = visitor.onImportFile;
|
|
146
|
+
visitorResolver.visit(tree);
|
|
147
|
+
return visitorResolver;
|
|
148
|
+
}
|
|
149
|
+
export function renderScript(scriptData, outputPath, options) {
|
|
150
|
+
const { currentDirectory = null, defaultLibsPath, dumpNets = false, dumpData = false, kicadNetlistPath = null, showStats = false } = options;
|
|
151
|
+
const onErrorHandler = (line, column, message, error) => {
|
|
152
|
+
if (error instanceof VisitorExecutionException) {
|
|
153
|
+
console.log('Error', line, column, message, error.errorMessage);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const visitor = new ParserVisitor(true, onErrorHandler, currentDirectory, defaultLibsPath);
|
|
157
|
+
visitor.onImportFile = (visitor, fileData) => {
|
|
158
|
+
const { hasError, hasParseError } = parseFileWithVisitor(visitor, fileData);
|
|
159
|
+
return { hasError, hasParseError };
|
|
160
|
+
};
|
|
161
|
+
visitor.log('reading file');
|
|
162
|
+
visitor.log('done reading file');
|
|
163
|
+
const { tree, parser, hasParseError, hasError, parserTimeTaken, lexerTimeTaken } = parseFileWithVisitor(visitor, scriptData);
|
|
164
|
+
showStats && console.log('Lexing took:', lexerTimeTaken);
|
|
165
|
+
showStats && console.log('Parsing took:', parserTimeTaken);
|
|
166
|
+
dumpNets && console.log(visitor.dumpNets());
|
|
167
|
+
dumpData && writeFileSync('dump/tree.lisp', tree.toStringTree(null, parser));
|
|
168
|
+
dumpData && writeFileSync('dump/raw-parser.txt', visitor.logger.dump());
|
|
169
|
+
if (hasError || hasParseError) {
|
|
170
|
+
console.log('Error while parsing');
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
visitor.annotateComponents();
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
console.log('Error during annotation: ', err);
|
|
178
|
+
}
|
|
179
|
+
if (kicadNetlistPath) {
|
|
180
|
+
const kicadNetList = generateKiCADNetList(visitor.getNetList());
|
|
181
|
+
writeFileSync(kicadNetlistPath, kicadNetList);
|
|
182
|
+
console.log('Generated KiCad netlist file');
|
|
183
|
+
}
|
|
184
|
+
const { sequence, nets } = visitor.getGraph();
|
|
185
|
+
const tmpSequence = sequence.map(item => {
|
|
186
|
+
const tmp = [...item];
|
|
187
|
+
const action = tmp[0];
|
|
188
|
+
if (action === SequenceAction.Wire) {
|
|
189
|
+
tmp[2] = tmp[2].map(item2 => {
|
|
190
|
+
return [item2.direction, item2.value].join(",");
|
|
191
|
+
}).join(" ");
|
|
192
|
+
}
|
|
193
|
+
else if (action === SequenceAction.Frame) {
|
|
194
|
+
tmp[1] = item[1].frameId;
|
|
195
|
+
}
|
|
196
|
+
else if (action !== SequenceAction.WireJump) {
|
|
197
|
+
tmp[1] = item[1].instanceName;
|
|
198
|
+
}
|
|
199
|
+
return tmp.join(" | ");
|
|
200
|
+
});
|
|
201
|
+
dumpData && writeFileSync('dump/raw-sequence.txt', tmpSequence.join('\n'));
|
|
202
|
+
let svgOutput = null;
|
|
203
|
+
try {
|
|
204
|
+
const layoutEngine = new LayoutEngine();
|
|
205
|
+
const layoutTimer = new SimpleStopwatch();
|
|
206
|
+
const graph = layoutEngine.runLayout(sequence, nets);
|
|
207
|
+
layoutEngine.printWarnings();
|
|
208
|
+
showStats && console.log('Layout took:', layoutTimer.lap());
|
|
209
|
+
dumpData && writeFileSync('dump/raw-layout.txt', layoutEngine.logger.dump());
|
|
210
|
+
const generateSvgTimer = new SimpleStopwatch();
|
|
211
|
+
svgOutput = generateSVG2(graph);
|
|
212
|
+
showStats && console.log('Render took:', generateSvgTimer.lap());
|
|
213
|
+
if (outputPath) {
|
|
214
|
+
writeFileSync(outputPath, svgOutput);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
console.log('Error during render: ', err);
|
|
219
|
+
}
|
|
220
|
+
return svgOutput;
|
|
221
|
+
}
|
|
222
|
+
export function detectJSModuleType() {
|
|
223
|
+
if (typeof __filename === 'undefined' &&
|
|
224
|
+
typeof __dirname === 'undefined') {
|
|
225
|
+
return JSModuleType.ESM;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
return JSModuleType.CommonJs;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const context = createContext();
|
|
232
|
+
export function getCurrentPath() {
|
|
233
|
+
const filename = context.filename;
|
|
234
|
+
return { filePath: filename };
|
|
235
|
+
}
|
|
236
|
+
function getToolsPath() {
|
|
237
|
+
const { filePath } = getCurrentPath();
|
|
238
|
+
return path.normalize(path.dirname(filePath) + '/../../');
|
|
239
|
+
}
|
|
240
|
+
export function getFontsPath() {
|
|
241
|
+
const toolsPath = getToolsPath();
|
|
242
|
+
return path.normalize(toolsPath + "fonts");
|
|
243
|
+
}
|
|
244
|
+
export function getDefaultLibsPath() {
|
|
245
|
+
const toolsPath = getToolsPath();
|
|
246
|
+
return path.normalize(toolsPath + "libs");
|
|
247
|
+
}
|
|
248
|
+
export function getPackageVersion() {
|
|
249
|
+
const packageJson = JSON.parse(readFileSync(getToolsPath() + 'package.json').toString());
|
|
250
|
+
const { version } = packageJson;
|
|
251
|
+
return version;
|
|
252
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './draw_symbols.mjs';
|
|
2
|
+
export * from './execute.mjs';
|
|
3
|
+
export * from './export.mjs';
|
|
4
|
+
export * from './geometry.mjs';
|
|
5
|
+
export * from './globals.mjs';
|
|
6
|
+
export * from './helpers.mjs';
|
|
7
|
+
export * from './layout.mjs';
|
|
8
|
+
export * from './lexer.mjs';
|
|
9
|
+
export * from './logger.mjs';
|
|
10
|
+
export * from './parser.mjs';
|
|
11
|
+
export * from './render.mjs';
|
|
12
|
+
export * from './utils.mjs';
|
|
13
|
+
export * from './visitor.mjs';
|
|
14
|
+
export * from './sizing.mjs';
|
|
15
|
+
export * from './objects/types.mjs';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { SymbolCustom, SymbolDrawing, SymbolFactory, SymbolPlaceholder, SymbolText } from "./draw_symbols.
|
|
3
|
-
import { FrameAction, SequenceAction } from "./objects/ExecutionScope.
|
|
4
|
-
import { GlobalNames, ParamKeys } from './globals.
|
|
5
|
-
import { NumericValue } from './objects/ParamDefinition.
|
|
6
|
-
import { Geometry } from './geometry.
|
|
7
|
-
import { Logger } from './logger.
|
|
8
|
-
import { Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.
|
|
9
|
-
import { getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, toNearestGrid } from './utils.
|
|
1
|
+
import { Graph, alg } from '@dagrejs/graphlib';
|
|
2
|
+
import { SymbolCustom, SymbolDrawing, SymbolFactory, SymbolPlaceholder, SymbolText } from "./draw_symbols.mjs";
|
|
3
|
+
import { FrameAction, SequenceAction } from "./objects/ExecutionScope.mjs";
|
|
4
|
+
import { GlobalNames, ParamKeys } from './globals.mjs';
|
|
5
|
+
import { NumericValue } from './objects/ParamDefinition.mjs';
|
|
6
|
+
import { Geometry } from './geometry.mjs';
|
|
7
|
+
import { Logger } from './logger.mjs';
|
|
8
|
+
import { Frame, FrameParamKeys, FramePlotDirection } from './objects/Frame.mjs';
|
|
9
|
+
import { getBoundsSize, printBounds, resizeBounds, resizeToNearestGrid, toNearestGrid } from './utils.mjs';
|
|
10
10
|
export class LayoutEngine {
|
|
11
11
|
logger;
|
|
12
12
|
placeSubgraphVersion = 2;
|
|
@@ -350,7 +350,7 @@ export class LayoutEngine {
|
|
|
350
350
|
generateLayoutGraph(sequence, nets) {
|
|
351
351
|
let previousNode = null;
|
|
352
352
|
let previousPin = null;
|
|
353
|
-
const graph = new
|
|
353
|
+
const graph = new Graph({
|
|
354
354
|
directed: false,
|
|
355
355
|
compound: true,
|
|
356
356
|
});
|
|
@@ -393,6 +393,14 @@ export class LayoutEngine {
|
|
|
393
393
|
didSetAngle = true;
|
|
394
394
|
tmpSymbol.angle = component.parameters.get('angle');
|
|
395
395
|
}
|
|
396
|
+
if (component.parameters.has('flipX')) {
|
|
397
|
+
tmpSymbol.flipX =
|
|
398
|
+
component.parameters.get('flipX');
|
|
399
|
+
}
|
|
400
|
+
if (component.parameters.has('flipY')) {
|
|
401
|
+
tmpSymbol.flipY =
|
|
402
|
+
component.parameters.get('flipY');
|
|
403
|
+
}
|
|
396
404
|
if (tmpSymbol instanceof SymbolCustom && widthProp) {
|
|
397
405
|
tmpSymbol.bodyWidth = widthProp;
|
|
398
406
|
}
|
|
@@ -498,7 +506,7 @@ export class LayoutEngine {
|
|
|
498
506
|
graph.setEdge(node1, node2, edgeValue);
|
|
499
507
|
}
|
|
500
508
|
sizeSubGraphs(graph) {
|
|
501
|
-
const subGraphs =
|
|
509
|
+
const subGraphs = alg.components(graph);
|
|
502
510
|
const subGraphsStarts = [];
|
|
503
511
|
this.print('===== placing subgraphs =====');
|
|
504
512
|
this.print('number of subgraphs: ', subGraphs.length);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CommonToken } from "
|
|
2
|
-
import CircuitScriptParser from "./antlr/CircuitScriptParser.
|
|
3
|
-
import CircuitScriptLexer from "./antlr/CircuitScriptLexer.
|
|
1
|
+
import { CommonToken } from "antlr4ng";
|
|
2
|
+
import { CircuitScriptParser } from "./antlr/CircuitScriptParser.mjs";
|
|
3
|
+
import { CircuitScriptLexer } from "./antlr/CircuitScriptLexer.mjs";
|
|
4
4
|
export class MainLexer extends CircuitScriptLexer {
|
|
5
5
|
tokens;
|
|
6
6
|
indents;
|
|
@@ -22,7 +22,7 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
22
22
|
this.tokens.push(token);
|
|
23
23
|
}
|
|
24
24
|
nextToken() {
|
|
25
|
-
if (this.
|
|
25
|
+
if (this.inputStream.LA(1) === CircuitScriptParser.EOF && this.indents.length) {
|
|
26
26
|
this.tokens = this.tokens.filter(function (val) {
|
|
27
27
|
return val.type !== CircuitScriptParser.EOF;
|
|
28
28
|
});
|
|
@@ -40,20 +40,20 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
40
40
|
return this.commonToken(CircuitScriptParser.DEDENT, "");
|
|
41
41
|
}
|
|
42
42
|
getCharIndex() {
|
|
43
|
-
return this.
|
|
43
|
+
return this.inputStream.index;
|
|
44
44
|
}
|
|
45
45
|
commonToken(type, text) {
|
|
46
46
|
const stop = this.getCharIndex() - 1;
|
|
47
47
|
const start = text.length ? stop - text.length + 1 : stop;
|
|
48
|
-
const token =
|
|
49
|
-
let tokenTypeString;
|
|
48
|
+
const token = CommonToken.fromSource([this, this.inputStream], type, 0, start, stop);
|
|
49
|
+
let tokenTypeString = null;
|
|
50
50
|
if (type === CircuitScriptParser.INDENT) {
|
|
51
51
|
tokenTypeString = "indent";
|
|
52
52
|
}
|
|
53
53
|
else if (type === CircuitScriptParser.DEDENT) {
|
|
54
54
|
tokenTypeString = "dedent";
|
|
55
55
|
}
|
|
56
|
-
if (tokenTypeString) {
|
|
56
|
+
if (tokenTypeString !== null) {
|
|
57
57
|
token.text = tokenTypeString;
|
|
58
58
|
}
|
|
59
59
|
return token;
|
|
@@ -82,8 +82,8 @@ export class MainLexer extends CircuitScriptLexer {
|
|
|
82
82
|
onNewLine() {
|
|
83
83
|
const newLine = this.text.replace(/[^\r\n]+/g, '');
|
|
84
84
|
const spaces = this.text.replace(/[\r\n]+/g, '');
|
|
85
|
-
const next = this.
|
|
86
|
-
const nextnext = this.
|
|
85
|
+
const next = this.inputStream.LA(1);
|
|
86
|
+
const nextnext = this.inputStream.LA(2);
|
|
87
87
|
if (this.opened > 0 || (nextnext != -1 &&
|
|
88
88
|
(next === 13 || next === 10 || next === 35))) {
|
|
89
89
|
this.skip();
|
|
@@ -2,18 +2,13 @@
|
|
|
2
2
|
import { program } from 'commander';
|
|
3
3
|
import figlet from 'figlet';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
5
|
import { readFileSync, watch } from 'fs';
|
|
7
|
-
import {
|
|
8
|
-
import { renderScript } from './helpers.
|
|
6
|
+
import { prepareSVGEnvironment } from './sizing.mjs';
|
|
7
|
+
import { getDefaultLibsPath, getFontsPath, getPackageVersion, renderScript } from './helpers.mjs';
|
|
9
8
|
export default async function main() {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const defaultLibsPath = toolDirectory + '/libs';
|
|
14
|
-
const packageJson = JSON.parse(readFileSync(toolDirectory + 'package.json').toString());
|
|
15
|
-
;
|
|
16
|
-
const { version } = packageJson;
|
|
9
|
+
const fontsPath = getFontsPath();
|
|
10
|
+
const defaultLibsPath = getDefaultLibsPath();
|
|
11
|
+
const version = getPackageVersion();
|
|
17
12
|
program
|
|
18
13
|
.description('generate graphical output from circuitscript files')
|
|
19
14
|
.version(version)
|
|
@@ -43,7 +38,7 @@ export default async function main() {
|
|
|
43
38
|
if (watchFileChanges) {
|
|
44
39
|
console.log('watching for file changes...');
|
|
45
40
|
}
|
|
46
|
-
await
|
|
41
|
+
await prepareSVGEnvironment(fontsPath);
|
|
47
42
|
let inputFilePath = null;
|
|
48
43
|
let scriptData;
|
|
49
44
|
if (options.input) {
|
|
@@ -56,7 +51,7 @@ export default async function main() {
|
|
|
56
51
|
currentDirectory = path.dirname(inputFilePath);
|
|
57
52
|
}
|
|
58
53
|
}
|
|
59
|
-
const
|
|
54
|
+
const scriptOptions = {
|
|
60
55
|
currentDirectory,
|
|
61
56
|
defaultLibsPath,
|
|
62
57
|
dumpNets,
|
|
@@ -64,7 +59,7 @@ export default async function main() {
|
|
|
64
59
|
kicadNetlistPath: kicadNetlist,
|
|
65
60
|
showStats: options.stats,
|
|
66
61
|
};
|
|
67
|
-
const output = renderScript(scriptData, outputPath,
|
|
62
|
+
const output = renderScript(scriptData, outputPath, scriptOptions);
|
|
68
63
|
if (outputPath === null && output) {
|
|
69
64
|
console.log(output);
|
|
70
65
|
}
|
|
@@ -72,7 +67,7 @@ export default async function main() {
|
|
|
72
67
|
watch(inputFilePath, event => {
|
|
73
68
|
if (event === 'change') {
|
|
74
69
|
const scriptData = readFileSync(inputFilePath, { encoding: 'utf-8' });
|
|
75
|
-
renderScript(scriptData, outputPath,
|
|
70
|
+
renderScript(scriptData, outputPath, scriptOptions);
|
|
76
71
|
console.log('done');
|
|
77
72
|
}
|
|
78
73
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SymbolDrawingCommands } from '../draw_symbols.
|
|
2
|
-
import { PinDefinition, PinIdType } from './PinDefinition.
|
|
3
|
-
import { PinTypes } from './PinTypes.
|
|
1
|
+
import { SymbolDrawingCommands } from '../draw_symbols.mjs';
|
|
2
|
+
import { PinDefinition, PinIdType } from './PinDefinition.mjs';
|
|
3
|
+
import { PinTypes } from './PinTypes.mjs';
|
|
4
4
|
export class ClassComponent {
|
|
5
5
|
instanceName;
|
|
6
6
|
numPins;
|
|
@@ -129,6 +129,9 @@ export class ClassComponent {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
for (const [key, value] of this.parameters) {
|
|
132
|
+
if (key === 'flipX' || key === 'flipY' || key === 'angle') {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
132
135
|
component.parameters.set(key, value);
|
|
133
136
|
}
|
|
134
137
|
for (const [key, value] of this.pins) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class UndeclaredReference {
|
|
2
|
+
reference;
|
|
3
|
+
constructor(reference) {
|
|
4
|
+
this.reference = reference;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export var ParseSymbolType;
|
|
8
|
+
(function (ParseSymbolType) {
|
|
9
|
+
ParseSymbolType["Variable"] = "variable";
|
|
10
|
+
ParseSymbolType["Function"] = "function";
|
|
11
|
+
ParseSymbolType["Undefined"] = "undefined";
|
|
12
|
+
})(ParseSymbolType || (ParseSymbolType = {}));
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CircuitScriptParser } from './antlr/CircuitScriptParser.mjs';
|
|
2
|
+
import { MainLexer } from './lexer.mjs';
|
|
3
|
+
import { SimpleStopwatch } from './utils.mjs';
|
|
4
|
+
import { CharStream, CommonTokenStream, DefaultErrorStrategy } from 'antlr4ng';
|
|
5
|
+
export function parseFileWithVisitor(visitor, data) {
|
|
6
|
+
const chars = CharStream.fromString(data);
|
|
7
|
+
const lexer = new MainLexer(chars);
|
|
8
|
+
const lexerTimer = new SimpleStopwatch();
|
|
9
|
+
const tokens = new CommonTokenStream(lexer);
|
|
10
|
+
tokens.fill();
|
|
11
|
+
const lexerTimeTaken = lexerTimer.lap();
|
|
12
|
+
const parserTimer = new SimpleStopwatch();
|
|
13
|
+
const parser = new CircuitScriptParser(tokens);
|
|
14
|
+
const tree = parser.script();
|
|
15
|
+
let hasError = false;
|
|
16
|
+
try {
|
|
17
|
+
visitor.visit(tree);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
console.log(err);
|
|
21
|
+
hasError = true;
|
|
22
|
+
}
|
|
23
|
+
const parserTimeTaken = parserTimer.lap();
|
|
24
|
+
return {
|
|
25
|
+
tree, parser,
|
|
26
|
+
hasParseError: false,
|
|
27
|
+
hasError,
|
|
28
|
+
parserTimeTaken,
|
|
29
|
+
lexerTimeTaken,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export class TempErrorStrategy extends DefaultErrorStrategy {
|
|
33
|
+
recover(recognizer, e) {
|
|
34
|
+
throw new Error('Method not implemented.');
|
|
35
|
+
}
|
|
36
|
+
reportError(recognizer, e) {
|
|
37
|
+
throw new Error('Method not implemented.');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export class CircuitscriptParserErrorListener {
|
|
41
|
+
syntaxErrorCounter = 0;
|
|
42
|
+
onErrorHandler = null;
|
|
43
|
+
constructor(onErrorHandler = null) {
|
|
44
|
+
this.onErrorHandler = onErrorHandler;
|
|
45
|
+
}
|
|
46
|
+
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
|
|
47
|
+
if (this.onErrorHandler) {
|
|
48
|
+
this.onErrorHandler(line, charPositionInLine, msg, e);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log("Syntax error at line", line, ':', charPositionInLine, ' - ', msg);
|
|
52
|
+
}
|
|
53
|
+
this.syntaxErrorCounter++;
|
|
54
|
+
}
|
|
55
|
+
reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) {
|
|
56
|
+
}
|
|
57
|
+
reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) {
|
|
58
|
+
}
|
|
59
|
+
reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) {
|
|
60
|
+
}
|
|
61
|
+
hasSyntaxErrors() {
|
|
62
|
+
return (this.syntaxErrorCounter > 0);
|
|
63
|
+
}
|
|
64
|
+
}
|