nodalis-compiler 1.0.20 → 1.0.21

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/CHANGELOG.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # Changelog
2
2
 
3
- ## [1.0.20] 2026-03-03
3
+ ## [1.0.21] 2026-03-03
4
4
  - Changed IEC parser to interpret Function Blocks that are actually standard functions to a formal function call.
5
5
  - Fixed nodejs/jint compiles to put executables in a bin folder.
6
+ - Fixed syntax errors with repeat.
6
7
 
7
8
  ## [1.0.17] 2026-02-25
8
9
  - Added support for compilation of multiple ST files as a single project.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodalis-compiler",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "Compiles IEC-61131-3/10 languages into code that can be used as a PLC on multiple platforms.",
5
5
  "icon": "nodalis.png",
6
6
  "main": "src/nodalis.js",
@@ -127,7 +127,7 @@ export function convertExpression(expr, isjsfb = false, jsfbVars = [], isjs=fals
127
127
  if (/^%[IQM][XBWDL]?\d+(\.\d+)?$/i.test(e)) return getReadAddressExpression(e);
128
128
 
129
129
  // Don't wrap literals or operators
130
- if (/^(true|false|null|[+-]?\d+|[+-]?(?:(?:\d+\.\d*|\d*\.\d+)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)|0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-f]+|!|&&|\|\||==|!=|[<>=+\-*/(),&|^])$/i.test(e)) return e;
130
+ if (/^(true|false|null|[+-]?\d+|[+-]?(?:(?:\d+\.\d*|\d*\.\d+)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+)|0[bB][01]+|0[oO][0-7]+|0[xX][0-9a-f]+|!|&&|\|\||==|!=|>=|<=|>|<|=|\+|-|\*|\/|%|\(|\)|,|&|\||\^)$/i.test(e)) return e;
131
131
 
132
132
  // Don't wrap known function expressions (e.g., getBit)
133
133
  if (/^getBit\(/.test(e)) return e;
@@ -292,9 +292,10 @@ function parseStatementsUntil(endTokens) {
292
292
  const body = parseStatements('UNTIL');
293
293
  expect('UNTIL');
294
294
  const condition = [];
295
- while (peek() && peek().value !== ';') {
295
+ while (peek() && peek().value.toUpperCase() !== 'END_REPEAT') {
296
296
  condition.push(consume().value);
297
297
  }
298
+ expect('END_REPEAT');
298
299
  if (peek()?.value === ';') consume();
299
300
  return { type: 'REPEAT', condition, body };
300
301
  }
@@ -72,20 +72,25 @@ while ((match = regex.exec(code)) !== null) {
72
72
  }
73
73
 
74
74
  function normalizeNumericLiteral(value) {
75
- const boolMatch = String(value).match(new RegExp(`^${BOOL_TYPE_PATTERN}#(TRUE|FALSE|1|0)$`, 'i'));
75
+ const literal = String(value);
76
+ const boolMatch = literal.match(new RegExp(`^${BOOL_TYPE_PATTERN}#(TRUE|FALSE|1|0)$`, 'i'));
76
77
  if (boolMatch) {
77
78
  const boolLiteral = boolMatch[1].toUpperCase();
78
79
  if (boolLiteral === 'TRUE' || boolLiteral === '1') return 'TRUE';
79
80
  return 'FALSE';
80
81
  }
81
82
 
82
- const typedValue = String(value).replace(
83
+ const typedValue = literal.replace(
83
84
  new RegExp(`^(?:${INTEGER_TYPE_PATTERN}|${REAL_TYPE_PATTERN}|${BOOL_TYPE_PATTERN})#`, 'i'),
84
85
  ''
85
86
  );
86
87
 
87
88
  const match = typedValue.match(/^(2|8|16)#([0-9a-f_]+)$/i);
88
- if (!match) return typedValue.replace(/_/g, '');
89
+ if (!match) {
90
+ const normalized = typedValue.replace(/_/g, '');
91
+ if (/^[+-]?\d+$/.test(normalized)) return normalizeDecimalIntegerLiteral(normalized);
92
+ return normalized;
93
+ }
89
94
  const radix = match[1];
90
95
  const digits = match[2].replace(/_/g, '');
91
96
  if (radix === '2') return `0b${digits}`;
@@ -93,6 +98,12 @@ function normalizeNumericLiteral(value) {
93
98
  return `0x${digits}`;
94
99
  }
95
100
 
101
+ function normalizeDecimalIntegerLiteral(value) {
102
+ const sign = value.startsWith('-') ? '-' : '';
103
+ const digits = value.replace(/^[+-]?/, '').replace(/^0+(?=\d)/, '');
104
+ return `${sign}${digits || '0'}`;
105
+ }
106
+
96
107
  function getTokenType(value) {
97
108
  const keywords = new Set([
98
109
  'PROGRAM', 'FUNCTION_BLOCK', 'FUNCTION', 'VAR_INPUT', 'VAR_OUTPUT', 'VAR', 'END_VAR',