circuitscript 0.0.24 → 0.0.26

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.
Files changed (73) hide show
  1. package/LICENSE +1 -1
  2. package/dist/cjs/BaseVisitor.js +485 -0
  3. package/dist/cjs/SemanticTokenVisitor.js +218 -0
  4. package/dist/cjs/SymbolValidatorVisitor.js +233 -0
  5. package/dist/cjs/antlr/CircuitScriptLexer.js +256 -219
  6. package/dist/cjs/antlr/CircuitScriptParser.js +2891 -2151
  7. package/dist/cjs/antlr/CircuitScriptVisitor.js +4 -3
  8. package/dist/cjs/draw_symbols.js +73 -22
  9. package/dist/cjs/execute.js +70 -78
  10. package/dist/cjs/export.js +91 -5
  11. package/dist/cjs/geometry.js +28 -8
  12. package/dist/cjs/globals.js +1 -2
  13. package/dist/cjs/helpers.js +180 -7
  14. package/dist/cjs/index.js +2 -0
  15. package/dist/cjs/layout.js +8 -0
  16. package/dist/cjs/lexer.js +19 -22
  17. package/dist/cjs/main.js +27 -20
  18. package/dist/cjs/objects/ClassComponent.js +4 -0
  19. package/dist/cjs/objects/ExecutionScope.js +1 -0
  20. package/dist/cjs/objects/types.js +7 -1
  21. package/dist/cjs/parser.js +29 -258
  22. package/dist/cjs/render.js +1 -1
  23. package/dist/cjs/validate.js +81 -0
  24. package/dist/cjs/visitor.js +601 -823
  25. package/dist/esm/BaseVisitor.mjs +486 -0
  26. package/dist/esm/SemanticTokenVisitor.mjs +215 -0
  27. package/dist/esm/SymbolValidatorVisitor.mjs +222 -0
  28. package/dist/esm/antlr/CircuitScriptLexer.mjs +231 -218
  29. package/dist/esm/antlr/CircuitScriptParser.mjs +2852 -2144
  30. package/dist/esm/antlr/CircuitScriptVisitor.mjs +13 -4
  31. package/dist/esm/draw_symbols.mjs +74 -23
  32. package/dist/esm/execute.mjs +70 -75
  33. package/dist/esm/export.mjs +89 -6
  34. package/dist/esm/geometry.mjs +28 -8
  35. package/dist/esm/globals.mjs +1 -2
  36. package/dist/esm/helpers.mjs +171 -9
  37. package/dist/esm/index.mjs +2 -0
  38. package/dist/esm/layout.mjs +8 -0
  39. package/dist/esm/lexer.mjs +10 -10
  40. package/dist/esm/main.mjs +28 -21
  41. package/dist/esm/objects/ClassComponent.mjs +4 -0
  42. package/dist/esm/objects/ExecutionScope.mjs +1 -0
  43. package/dist/esm/objects/types.mjs +6 -0
  44. package/dist/esm/parser.mjs +25 -230
  45. package/dist/esm/render.mjs +2 -2
  46. package/dist/esm/validate.mjs +74 -0
  47. package/dist/esm/visitor.mjs +415 -643
  48. package/dist/types/BaseVisitor.d.ts +66 -0
  49. package/dist/types/SemanticTokenVisitor.d.ts +36 -0
  50. package/dist/types/SymbolValidatorVisitor.d.ts +61 -0
  51. package/dist/types/antlr/CircuitScriptLexer.d.ts +37 -29
  52. package/dist/types/antlr/CircuitScriptParser.d.ts +606 -494
  53. package/dist/types/antlr/CircuitScriptVisitor.d.ts +78 -60
  54. package/dist/types/draw_symbols.d.ts +12 -3
  55. package/dist/types/execute.d.ts +5 -10
  56. package/dist/types/export.d.ts +27 -1
  57. package/dist/types/geometry.d.ts +4 -0
  58. package/dist/types/globals.d.ts +2 -3
  59. package/dist/types/helpers.d.ts +32 -1
  60. package/dist/types/index.d.ts +2 -0
  61. package/dist/types/lexer.d.ts +2 -2
  62. package/dist/types/objects/ClassComponent.d.ts +1 -0
  63. package/dist/types/objects/ExecutionScope.d.ts +4 -1
  64. package/dist/types/objects/types.d.ts +5 -0
  65. package/dist/types/parser.d.ts +15 -28
  66. package/dist/types/validate.d.ts +2 -0
  67. package/dist/types/visitor.d.ts +43 -95
  68. package/fonts/Inter-Bold.ttf +0 -0
  69. package/fonts/Inter-Regular.ttf +0 -0
  70. package/fonts/OpenSans-Regular.ttf +0 -0
  71. package/fonts/Roboto-Regular.ttf +0 -0
  72. package/libs/lib.cst +184 -0
  73. package/package.json +11 -6
@@ -1,9 +1,9 @@
1
- import { CharStream, CommonTokenStream, ErrorListener, ParseTreeVisitor } from 'antlr4';
2
- import CircuitScriptParser, { Atom_exprContext, Create_component_exprContext, Create_graphic_exprContext, Function_def_exprContext, Property_key_exprContext, Sub_exprContext } from './antlr/CircuitScriptParser.mjs';
1
+ import { CircuitScriptParser } from './antlr/CircuitScriptParser.mjs';
3
2
  import { MainLexer } from './lexer.mjs';
4
3
  import { SimpleStopwatch } from './utils.mjs';
4
+ import { CharStream, CommonTokenStream, DefaultErrorStrategy } from 'antlr4ng';
5
5
  export function parseFileWithVisitor(visitor, data) {
6
- const chars = new CharStream(data);
6
+ const chars = CharStream.fromString(data);
7
7
  const lexer = new MainLexer(chars);
8
8
  const lexerTimer = new SimpleStopwatch();
9
9
  const tokens = new CommonTokenStream(lexer);
@@ -11,259 +11,54 @@ export function parseFileWithVisitor(visitor, data) {
11
11
  const lexerTimeTaken = lexerTimer.lap();
12
12
  const parserTimer = new SimpleStopwatch();
13
13
  const parser = new CircuitScriptParser(tokens);
14
- parser.removeErrorListeners();
15
- const errorListener = new CircuitscriptParserErrorListener();
16
- parser.addErrorListener(errorListener);
17
14
  const tree = parser.script();
18
15
  let hasError = false;
19
16
  try {
20
17
  visitor.visit(tree);
21
18
  }
22
19
  catch (err) {
23
- err.print(data);
20
+ console.log(err);
24
21
  hasError = true;
25
22
  }
26
23
  const parserTimeTaken = parserTimer.lap();
27
- const semanticTokenVisitor = new SemanticTokensVisitor(lexer, data);
28
- semanticTokenVisitor.visit(tree);
29
- const semanticTokens = semanticTokenVisitor.semanticTokens;
30
- const parsedTokens = prepareTokens(tokens.tokens, lexer, data);
31
- const finalParsedTokens = [];
32
- parsedTokens.forEach(token => {
33
- const location = `${token.line}_${token.column}`;
34
- if (semanticTokens.has(location)) {
35
- finalParsedTokens.push(semanticTokens.get(location));
36
- }
37
- else {
38
- finalParsedTokens.push(token);
39
- }
40
- });
41
24
  return {
42
25
  tree, parser,
43
- hasParseError: errorListener.hasParseErrors(),
26
+ hasParseError: false,
44
27
  hasError,
45
28
  parserTimeTaken,
46
29
  lexerTimeTaken,
47
- tokens: finalParsedTokens,
48
30
  };
49
31
  }
50
- export class SemanticTokensVisitor extends ParseTreeVisitor {
51
- parsedTokens = [];
52
- lexer;
53
- script;
54
- semanticTokens = new Map();
55
- constructor(lexer, script) {
56
- super();
57
- this.lexer = lexer;
58
- this.script = script;
59
- }
60
- visit(ctx) {
61
- const here = this;
62
- if (Array.isArray(ctx)) {
63
- return ctx.map(function (child) {
64
- try {
65
- here.checkContext(child);
66
- return child.accept(this);
67
- }
68
- catch (err) {
69
- this.handleError(child, err);
70
- }
71
- }, this);
72
- }
73
- else {
74
- try {
75
- this.checkContext(ctx);
76
- return ctx.accept(this);
77
- }
78
- catch (err) {
79
- this.handleError(ctx, err);
80
- }
81
- }
32
+ export class TempErrorStrategy extends DefaultErrorStrategy {
33
+ recover(recognizer, e) {
34
+ throw new Error('Method not implemented.');
82
35
  }
83
- handleError(ctx, err) {
84
- console.log('error!', err);
36
+ reportError(recognizer, e) {
37
+ throw new Error('Method not implemented.');
85
38
  }
86
- checkContext(ctx) {
87
- if (ctx instanceof Function_def_exprContext) {
88
- this.addSemanticToken(this.parseToken(ctx.ID(), ['declaration'], 'function'));
89
- }
90
- else if (ctx instanceof Create_component_exprContext
91
- || ctx instanceof Create_graphic_exprContext) {
92
- this.addSemanticToken(this.parseToken(ctx.Create(), ['defaultLibrary'], 'function'));
93
- }
94
- else if (ctx instanceof Atom_exprContext) {
95
- if (ctx.ID()) {
96
- if (ctx.trailer_expr_list().length > 0) {
97
- this.addSemanticToken(this.parseToken(ctx.ID(), ['declaration'], 'function'));
98
- }
99
- else {
100
- this.addSemanticToken(this.parseToken(ctx.ID(), ['declaration'], 'variable'));
101
- }
102
- }
103
- }
104
- else if (ctx instanceof Property_key_exprContext) {
105
- let useToken = null;
106
- if (ctx.ID()) {
107
- useToken = ctx.ID();
108
- }
109
- else if (ctx.INTEGER_VALUE()) {
110
- useToken = ctx.INTEGER_VALUE();
111
- }
112
- else if (ctx.STRING_VALUE()) {
113
- useToken = ctx.STRING_VALUE();
114
- }
115
- useToken && this.addSemanticToken(this.parseToken(useToken, ['declaration'], 'property'));
116
- }
117
- else if (ctx instanceof Sub_exprContext) {
118
- let useToken = null;
119
- if (ctx.ID()) {
120
- useToken = ctx.ID();
121
- }
122
- else if (ctx.Pin()) {
123
- useToken = ctx.Pin();
124
- }
125
- useToken && this.addSemanticToken(this.parseToken(useToken, ['defaultLibrary'], 'function'));
126
- }
127
- }
128
- addSemanticToken(parsedToken) {
129
- this.semanticTokens.set(parsedToken.line + "_" + parsedToken.column, parsedToken);
39
+ }
40
+ export class CircuitscriptParserErrorListener {
41
+ syntaxErrorCounter = 0;
42
+ onErrorHandler = null;
43
+ constructor(onErrorHandler = null) {
44
+ this.onErrorHandler = onErrorHandler;
130
45
  }
131
- parseToken(node, modifiers, tokenType = null) {
132
- const token = node.symbol;
133
- let stringValue = "";
134
- let textPart = "";
135
- if (this.lexer.symbolicNames[token.type] !== null && this.lexer.symbolicNames[token.type] !== undefined) {
136
- stringValue = this.lexer.symbolicNames[token.type];
137
- if (stringValue !== "NEWLINE") {
138
- textPart = this.script.substring(token.start, token.stop + 1);
139
- }
140
- else {
141
- textPart = token.text.length - 1;
142
- }
143
- }
144
- else if (this.lexer.literalNames[token.type] !== null && this.lexer.literalNames[token.type] !== undefined) {
145
- stringValue = this.lexer.literalNames[token.type];
146
- textPart = this.script.substring(token.start, token.stop + 1);
46
+ syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
47
+ if (this.onErrorHandler) {
48
+ this.onErrorHandler(line, charPositionInLine, msg, e);
147
49
  }
148
50
  else {
149
- stringValue = token._text;
51
+ console.log("Syntax error at line", line, ':', charPositionInLine, ' - ', msg);
150
52
  }
151
- return {
152
- line: token.line,
153
- column: token.column,
154
- length: token.stop - token.start + 1,
155
- tokenType: tokenType !== null ? tokenType : stringValue,
156
- tokenModifiers: modifiers,
157
- textValue: textPart,
158
- };
159
- }
160
- }
161
- function prepareTokens(tokens, lexer, script) {
162
- const parsedTokens = [];
163
- tokens.forEach(item => {
164
- if (item.type !== -1) {
165
- let stringValue = "";
166
- let textPart = "";
167
- if (lexer.symbolicNames[item.type] !== null && lexer.symbolicNames[item.type] !== undefined) {
168
- stringValue = lexer.symbolicNames[item.type];
169
- if (stringValue !== "NEWLINE") {
170
- textPart = script.substring(item.start, item.stop + 1);
171
- }
172
- else {
173
- textPart = item.text.length - 1;
174
- }
175
- }
176
- else if (lexer.literalNames[item.type] !== null && lexer.literalNames[item.type] !== undefined) {
177
- stringValue = lexer.literalNames[item.type];
178
- textPart = script.substring(item.start, item.stop + 1);
179
- }
180
- else {
181
- stringValue = item._text;
182
- }
183
- if (textPart !== 0 && textPart !== '') {
184
- parsedTokens.push({
185
- line: item.line,
186
- column: item.column,
187
- length: item.stop - item.start + 1,
188
- tokenType: resolveTokenType(stringValue),
189
- tokenModifiers: resolveTokenModifiers(stringValue),
190
- textValue: textPart,
191
- });
192
- }
193
- }
194
- });
195
- return parsedTokens;
196
- }
197
- const languageKeywords = [
198
- 'break', 'branch', 'create', 'component',
199
- 'graphic', 'wire', 'pin', 'add', 'at', 'to',
200
- 'point', 'join', 'parallel', 'return', 'def', 'import',
201
- 'true', 'false', 'nc', 'frame',
202
- ];
203
- const operatorKeywords = [
204
- 'at', 'to', 'wire', 'add', 'frame', 'join', 'parallel', 'point'
205
- ];
206
- function resolveTokenType(tokenType) {
207
- if (operatorKeywords.indexOf(tokenType.toLowerCase()) !== -1) {
208
- return 'graphKeyword';
53
+ this.syntaxErrorCounter++;
209
54
  }
210
- else if (languageKeywords.indexOf(tokenType.toLowerCase()) !== -1) {
211
- return 'keyword';
55
+ reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) {
212
56
  }
213
- else {
214
- switch (tokenType) {
215
- case 'INTEGER_VALUE':
216
- case 'NUMERIC_VALUE':
217
- case 'DECIMAL_VALUE':
218
- case 'PERCENTAGE_VALUE':
219
- return 'number';
220
- case 'STRING_VALUE':
221
- return 'string';
222
- case 'ID':
223
- return 'variable';
224
- case 'Define':
225
- return 'keyword';
226
- case 'COMMENT':
227
- return 'comment';
228
- }
229
- return null;
57
+ reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) {
230
58
  }
231
- }
232
- function resolveTokenModifiers(tokenType) {
233
- return [];
234
- }
235
- function dumpTokens(tokens, lexer, scriptData) {
236
- tokens.forEach(item => {
237
- if (item.type !== -1) {
238
- let stringValue = "";
239
- let textPart = "";
240
- if (lexer.symbolicNames[item.type] !== null && lexer.symbolicNames[item.type] !== undefined) {
241
- stringValue = lexer.symbolicNames[item.type];
242
- if (stringValue !== "NEWLINE") {
243
- textPart = scriptData.substring(item.start, item.stop + 1);
244
- }
245
- else {
246
- textPart = item.text.length - 1;
247
- }
248
- }
249
- else if (lexer.literalNames[item.type] !== null && lexer.literalNames[item.type] !== undefined) {
250
- stringValue = lexer.literalNames[item.type];
251
- textPart = scriptData.substring(item.start, item.stop + 1);
252
- }
253
- else {
254
- stringValue = item._text;
255
- }
256
- console.log('line', item.line + ':' + item.column, `\t${stringValue} (${item.type})`.padEnd(30), textPart);
257
- }
258
- });
259
- }
260
- export class CircuitscriptParserErrorListener extends ErrorListener {
261
- syntaxErrorCounter = 0;
262
- syntaxError(recognizer, offendingSymbol, line, column, msg, e) {
263
- console.log("Syntax error at line", line, ':', column, ' - ', msg);
264
- this.syntaxErrorCounter++;
59
+ reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) {
265
60
  }
266
- hasParseErrors() {
61
+ hasSyntaxErrors() {
267
62
  return (this.syntaxErrorCounter > 0);
268
63
  }
269
64
  }
@@ -1,7 +1,7 @@
1
1
  import { SVG, registerWindow } from '@svgdotjs/svg.js';
2
2
  import { RenderFrameType, getBounds } from "./layout.mjs";
3
3
  import { applyFontsToSVG, getCreateSVGWindow } from './sizing.mjs';
4
- import { ParamKeys, bodyColor, junctionColor, junctionSize, wireColor } from './globals.mjs';
4
+ import { ComponentTypes, ParamKeys, bodyColor, junctionColor, junctionSize, wireColor } from './globals.mjs';
5
5
  import { NumericValue } from './objects/ParamDefinition.mjs';
6
6
  import { getBoundsSize } from './utils.mjs';
7
7
  export function generateSVG2(graph) {
@@ -36,7 +36,7 @@ function generateSVGChild(canvas, components, wires, junctions, mergedWires, fra
36
36
  const { symbol = null } = item;
37
37
  if (symbol !== null && symbol) {
38
38
  const extra = {};
39
- if (item.component.parameters.has('__is_net')) {
39
+ if (item.component.typeProp === ComponentTypes.net) {
40
40
  extra.net_name = item.component.parameters.get(ParamKeys.net_name);
41
41
  }
42
42
  else if (item.component.parameters.has('value')) {
@@ -0,0 +1,74 @@
1
+ #! /usr/bin/env node
2
+ import { program } from 'commander';
3
+ import figlet from 'figlet';
4
+ import path from 'path';
5
+ import { readFileSync } from 'fs';
6
+ import { prepareSVGEnvironment } from './sizing.mjs';
7
+ import { getCurrentPath, getScriptText, getSemanticTokens, validateScript } from './helpers.mjs';
8
+ export async function validate() {
9
+ const { filePath } = getCurrentPath();
10
+ const toolSrcPath = filePath;
11
+ const toolDirectory = path.dirname(toolSrcPath) + '/../../';
12
+ const fontsPath = toolDirectory + '/fonts';
13
+ const defaultLibsPath = toolDirectory + '/libs';
14
+ const packageJson = JSON.parse(readFileSync(toolDirectory + 'package.json').toString());
15
+ ;
16
+ const { version } = packageJson;
17
+ program
18
+ .description('generate graphical output from circuitscript files')
19
+ .version(version)
20
+ .option('-i, --input text <input text>', 'Input text directly')
21
+ .option('-f, --input-file <path>', 'Input file')
22
+ .option('-o, --output <path>', 'Output path')
23
+ .option('-c, --current-directory <path>', 'Set current directory')
24
+ .option('-k, --kicad-netlist <filename>', 'Create KiCad netlist')
25
+ .option('-w, --watch', 'Watch for file changes')
26
+ .option('-n, --dump-nets', 'Dump out net information')
27
+ .option('-d, --dump-data', 'Dump data during parsing')
28
+ .option('-s, --stats', 'Show stats during generation');
29
+ program.addHelpText('before', figlet.textSync('circuitscript', {
30
+ font: 'Small Slant'
31
+ }));
32
+ if (process.argv.length < 3) {
33
+ program.help();
34
+ }
35
+ program.parse();
36
+ const options = program.opts();
37
+ const watchFileChanges = options.watch;
38
+ const outputPath = options.output ?? null;
39
+ const dumpNets = options.dumpNets;
40
+ const dumpData = options.dumpData;
41
+ const kicadNetlist = options.kicadNetlist;
42
+ let currentDirectory = options.currentDirectory ?? null;
43
+ if (watchFileChanges) {
44
+ console.log('watching for file changes...');
45
+ }
46
+ await prepareSVGEnvironment(fontsPath);
47
+ let inputFilePath = null;
48
+ let scriptData;
49
+ if (options.input) {
50
+ scriptData = options.input;
51
+ }
52
+ else {
53
+ inputFilePath = options.inputFile;
54
+ const tmpScriptData = getScriptText(inputFilePath);
55
+ if (tmpScriptData === null) {
56
+ throw "File does not exists";
57
+ }
58
+ scriptData = tmpScriptData;
59
+ if (currentDirectory === null) {
60
+ currentDirectory = path.dirname(inputFilePath);
61
+ }
62
+ }
63
+ const scriptOptions = {
64
+ currentDirectory,
65
+ defaultLibsPath,
66
+ dumpNets,
67
+ dumpData,
68
+ kicadNetlistPath: kicadNetlist,
69
+ showStats: options.stats,
70
+ };
71
+ const visitor = validateScript(scriptData, scriptOptions);
72
+ const semanticTokensVisitor = getSemanticTokens(scriptData, scriptOptions);
73
+ }
74
+ validate();