@hyperfixi/core 2.9.1 → 2.9.3

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 (49) hide show
  1. package/dist/bundle-generator/index.js +6 -0
  2. package/dist/bundle-generator/index.mjs +6 -0
  3. package/dist/bundle-generator/parser-templates.d.ts +1 -1
  4. package/dist/chunks/{bridge-BYhqTOnL.js → bridge-DwtNLKK3.js} +2 -2
  5. package/dist/chunks/browser-modular-6HT1r2AH.js +2 -0
  6. package/dist/chunks/{index-DXgJaDj-.js → index-B8jwvuj_.js} +2 -2
  7. package/dist/commands/index.js +133 -74
  8. package/dist/commands/index.mjs +133 -74
  9. package/dist/hyperfixi-browser-classic-i18n.js +1 -1
  10. package/dist/hyperfixi-browser-minimal.js +1 -1
  11. package/dist/hyperfixi-browser-standard.js +1 -1
  12. package/dist/hyperfixi-browser.js +1 -1
  13. package/dist/hyperfixi-classic-i18n.js +1 -1
  14. package/dist/hyperfixi-hx-v4.js +1 -1
  15. package/dist/hyperfixi-hx.js +1 -1
  16. package/dist/hyperfixi-hybrid-complete.js +1 -1
  17. package/dist/hyperfixi-hybrid-hx.js +1 -1
  18. package/dist/hyperfixi-minimal.js +1 -1
  19. package/dist/hyperfixi-multilingual.js +1 -1
  20. package/dist/hyperfixi-standard.js +1 -1
  21. package/dist/hyperfixi.js +1 -1
  22. package/dist/hyperfixi.mjs +1 -1
  23. package/dist/index.js +233 -79
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.mjs +233 -79
  26. package/dist/lokascript-browser-classic-i18n.js +1 -1
  27. package/dist/lokascript-browser-minimal.js +1 -1
  28. package/dist/lokascript-browser-standard.js +1 -1
  29. package/dist/lokascript-browser.js +1 -1
  30. package/dist/lokascript-hybrid-complete.js +1 -1
  31. package/dist/lokascript-hybrid-hx.js +1 -1
  32. package/dist/lokascript-multilingual.js +1 -1
  33. package/dist/parser/command-parsers/utility-commands.d.ts +1 -1
  34. package/dist/parser/full-parser.js +133 -74
  35. package/dist/parser/full-parser.mjs +133 -74
  36. package/dist/parser/hybrid/index.js +3 -0
  37. package/dist/parser/hybrid/index.mjs +3 -0
  38. package/dist/parser/hybrid/parser-core.js +3 -0
  39. package/dist/parser/hybrid/parser-core.mjs +3 -0
  40. package/dist/parser/hybrid-parser.js +3 -0
  41. package/dist/parser/hybrid-parser.mjs +3 -0
  42. package/dist/reference/index.js +1 -0
  43. package/dist/reference/index.mjs +1 -0
  44. package/dist/registry/index.js +133 -74
  45. package/dist/registry/index.mjs +133 -74
  46. package/dist/runtime/runtime-base.d.ts +2 -1
  47. package/dist/types/core.d.ts +1 -0
  48. package/package.json +6 -6
  49. package/dist/chunks/browser-modular-D2BHzZFB.js +0 -2
@@ -4140,13 +4140,13 @@ function tokenize(input) {
4140
4140
  continue;
4141
4141
  }
4142
4142
  if (char === '{') {
4143
- addToken(tokenizer, TokenKind.OPERATOR, '{');
4144
4143
  advance(tokenizer);
4144
+ addToken(tokenizer, TokenKind.OPERATOR, '{');
4145
4145
  continue;
4146
4146
  }
4147
4147
  if (char === '}') {
4148
- addToken(tokenizer, TokenKind.OPERATOR, '}');
4149
4148
  advance(tokenizer);
4149
+ addToken(tokenizer, TokenKind.OPERATOR, '}');
4150
4150
  continue;
4151
4151
  }
4152
4152
  if (char === '[') {
@@ -4162,24 +4162,24 @@ function tokenize(input) {
4162
4162
  prevToken.value === ']') &&
4163
4163
  !isEventCondition;
4164
4164
  if (isMemberAccess) {
4165
- addToken(tokenizer, TokenKind.OPERATOR, '[');
4166
4165
  advance(tokenizer);
4166
+ addToken(tokenizer, TokenKind.OPERATOR, '[');
4167
4167
  }
4168
4168
  else {
4169
4169
  if (isEventCondition) {
4170
- addToken(tokenizer, TokenKind.SYMBOL, '[');
4171
4170
  advance(tokenizer);
4171
+ addToken(tokenizer, TokenKind.SYMBOL, '[');
4172
4172
  }
4173
4173
  else {
4174
- addToken(tokenizer, TokenKind.OPERATOR, '[');
4175
4174
  advance(tokenizer);
4175
+ addToken(tokenizer, TokenKind.OPERATOR, '[');
4176
4176
  }
4177
4177
  }
4178
4178
  continue;
4179
4179
  }
4180
4180
  if (char === ']') {
4181
- addToken(tokenizer, TokenKind.OPERATOR, ']');
4182
4181
  advance(tokenizer);
4182
+ addToken(tokenizer, TokenKind.OPERATOR, ']');
4183
4183
  continue;
4184
4184
  }
4185
4185
  if (char === '$') {
@@ -5808,7 +5808,6 @@ const MULTI_WORD_PATTERNS = [
5808
5808
  keywords: ['a', 'an', 'from', 'called'],
5809
5809
  syntax: 'make (a|an) <type> [from <args>] [called <name>]',
5810
5810
  },
5811
- { command: 'send', keywords: ['to'], syntax: 'send <event> to <target>' },
5812
5811
  { command: 'throw', keywords: [], syntax: 'throw <error>' },
5813
5812
  ];
5814
5813
  function getMultiWordPattern(commandName) {
@@ -6109,7 +6108,13 @@ function parseTriggerCommand(ctx, identifierNode) {
6109
6108
  finalArgs.push(ctx.createIdentifier(keyword));
6110
6109
  continue;
6111
6110
  }
6112
- finalArgs.push(ctx.parsePrimary());
6111
+ const before = ctx.savePosition();
6112
+ const expr = ctx.parsePrimary();
6113
+ if (expr)
6114
+ finalArgs.push(expr);
6115
+ if (ctx.savePosition() === before) {
6116
+ ctx.advance();
6117
+ }
6113
6118
  }
6114
6119
  return CommandNodeBuilder.fromIdentifier(identifierNode)
6115
6120
  .withArgs(...finalArgs)
@@ -6328,11 +6333,64 @@ function parseRepeatCommand(ctx, commandToken) {
6328
6333
  }
6329
6334
  return builder.endingAt(ctx.getPosition()).build();
6330
6335
  }
6336
+ function parseIfBranchCommands(ctx, stopAtElse) {
6337
+ const commands = [];
6338
+ const atTerminator = () => ctx.check(KEYWORDS.END) || (stopAtElse && ctx.check(KEYWORDS.ELSE));
6339
+ while (!ctx.isAtEnd() && !atTerminator()) {
6340
+ if (isComment(ctx.peek())) {
6341
+ ctx.advance();
6342
+ continue;
6343
+ }
6344
+ if (!ctx.checkIsCommand() && !ctx.isCommand(ctx.peek().value))
6345
+ break;
6346
+ ctx.advance();
6347
+ const cmd = ctx.parseCommand();
6348
+ if (cmd) {
6349
+ commands.push(cmd);
6350
+ }
6351
+ if (ctx.check(KEYWORDS.THEN) || ctx.check(KEYWORDS.AND) || ctx.check(',')) {
6352
+ ctx.advance();
6353
+ }
6354
+ }
6355
+ return commands;
6356
+ }
6357
+ const OPERAND_INTRODUCERS = new Set([
6358
+ 'is',
6359
+ 'am',
6360
+ 'are',
6361
+ 'not',
6362
+ 'no',
6363
+ 'and',
6364
+ 'or',
6365
+ '==',
6366
+ '===',
6367
+ '!=',
6368
+ '!==',
6369
+ '<',
6370
+ '>',
6371
+ '<=',
6372
+ '>=',
6373
+ '+',
6374
+ '-',
6375
+ '*',
6376
+ '/',
6377
+ 'mod',
6378
+ ]);
6379
+ function isBodyCommandStart(ctx, prevToken, token) {
6380
+ if (prevToken === null) {
6381
+ return false;
6382
+ }
6383
+ if (OPERAND_INTRODUCERS.has(prevToken.value?.toLowerCase?.() ?? '')) {
6384
+ return false;
6385
+ }
6386
+ return ctx.checkIsCommand() || ctx.isCommand(token.value?.toLowerCase());
6387
+ }
6331
6388
  function parseIfCommand(ctx, commandToken) {
6332
6389
  const args = [];
6333
6390
  let hasThen = false;
6334
6391
  const savedPosForThen = ctx.savePosition();
6335
6392
  const maxThenLookahead = 500;
6393
+ let prevForThen = null;
6336
6394
  for (let i = 0; i < maxThenLookahead && !ctx.isAtEnd(); i++) {
6337
6395
  const token = ctx.peek();
6338
6396
  if (token.value === KEYWORDS.THEN) {
@@ -6345,6 +6403,14 @@ function parseIfCommand(ctx, commandToken) {
6345
6403
  token.value === KEYWORDS.ON) {
6346
6404
  break;
6347
6405
  }
6406
+ if (token.line !== undefined &&
6407
+ token.line !== commandToken.line &&
6408
+ isBodyCommandStart(ctx, prevForThen, token)) {
6409
+ break;
6410
+ }
6411
+ if (!isComment(token)) {
6412
+ prevForThen = token;
6413
+ }
6348
6414
  ctx.advance();
6349
6415
  }
6350
6416
  ctx.restorePosition(savedPosForThen);
@@ -6353,9 +6419,14 @@ function parseIfCommand(ctx, commandToken) {
6353
6419
  const savedPosition = ctx.savePosition();
6354
6420
  const ifStatementLine = commandToken.line;
6355
6421
  const maxLookahead = 100;
6422
+ let firstCommandOnIfLine = false;
6423
+ let prevToken = null;
6356
6424
  while (!ctx.isAtEnd() && ctx.current - savedPosition < maxLookahead) {
6357
6425
  const token = ctx.peek();
6358
6426
  const tokenValue = token.value?.toLowerCase();
6427
+ if (firstCommandOnIfLine && token.line !== undefined && token.line !== ifStatementLine) {
6428
+ break;
6429
+ }
6359
6430
  if (tokenValue === KEYWORDS.BEHAVIOR ||
6360
6431
  tokenValue === KEYWORDS.DEF ||
6361
6432
  tokenValue === KEYWORDS.ON) {
@@ -6367,11 +6438,15 @@ function parseIfCommand(ctx, commandToken) {
6367
6438
  }
6368
6439
  break;
6369
6440
  }
6370
- if (ctx.checkIsCommand() || ctx.isCommand(tokenValue)) {
6441
+ if (isBodyCommandStart(ctx, prevToken, token)) {
6371
6442
  if (token.line !== undefined && token.line !== ifStatementLine) {
6372
6443
  hasImplicitMultiLineEnd = true;
6373
6444
  break;
6374
6445
  }
6446
+ firstCommandOnIfLine = true;
6447
+ }
6448
+ if (!isComment(token)) {
6449
+ prevToken = token;
6375
6450
  }
6376
6451
  ctx.advance();
6377
6452
  }
@@ -6386,11 +6461,12 @@ function parseIfCommand(ctx, commandToken) {
6386
6461
  const conditionTokens = [];
6387
6462
  const maxIterations = 20;
6388
6463
  let iterations = 0;
6464
+ let firstConditionParse = true;
6389
6465
  while (!ctx.isAtEnd() &&
6390
- !ctx.checkIsCommand() &&
6391
- !ctx.isCommand(ctx.peek().value) &&
6392
6466
  !ctx.check(KEYWORDS.THEN) &&
6467
+ (firstConditionParse || (!ctx.checkIsCommand() && !ctx.isCommand(ctx.peek().value))) &&
6393
6468
  iterations < maxIterations) {
6469
+ firstConditionParse = false;
6394
6470
  const beforePos = ctx.savePosition();
6395
6471
  conditionTokens.push(ctx.parseLogicalAnd());
6396
6472
  if (ctx.savePosition() === beforePos) {
@@ -6417,22 +6493,8 @@ function parseIfCommand(ctx, commandToken) {
6417
6493
  }
6418
6494
  args.push(condition);
6419
6495
  if (isMultiLine) {
6420
- if (hasThen) {
6421
- ctx.advance();
6422
- }
6423
- const thenCommands = [];
6424
- while (!ctx.isAtEnd() && !ctx.check(KEYWORDS.ELSE) && !ctx.check(KEYWORDS.END)) {
6425
- if (ctx.checkIsCommand() || ctx.isCommand(ctx.peek().value)) {
6426
- ctx.advance();
6427
- const cmd = ctx.parseCommand();
6428
- if (cmd) {
6429
- thenCommands.push(cmd);
6430
- }
6431
- }
6432
- else {
6433
- break;
6434
- }
6435
- }
6496
+ consumeOptionalKeyword(ctx, KEYWORDS.THEN);
6497
+ const thenCommands = parseIfBranchCommands(ctx, true);
6436
6498
  if (thenCommands.length === 0 && ctx.isAtEnd()) {
6437
6499
  throw new Error("Expected command after 'then' in if statement - incomplete conditional");
6438
6500
  }
@@ -6458,19 +6520,7 @@ function parseIfCommand(ctx, commandToken) {
6458
6520
  consumedElseIf = true;
6459
6521
  }
6460
6522
  else {
6461
- const elseCommands = [];
6462
- while (!ctx.isAtEnd() && !ctx.check(KEYWORDS.END)) {
6463
- if (ctx.checkIsCommand() || ctx.isCommand(ctx.peek().value)) {
6464
- ctx.advance();
6465
- const cmd = ctx.parseCommand();
6466
- if (cmd) {
6467
- elseCommands.push(cmd);
6468
- }
6469
- }
6470
- else {
6471
- break;
6472
- }
6473
- }
6523
+ const elseCommands = parseIfBranchCommands(ctx, false);
6474
6524
  args.push(createBlock(elseCommands, {
6475
6525
  start: commandToken.start,
6476
6526
  end: ctx.getPosition().end,
@@ -7292,21 +7342,6 @@ const GO_KEYWORDS = new Set([
7292
7342
  'back',
7293
7343
  'forward',
7294
7344
  ]);
7295
- const GO_URL_STOP = new Set([
7296
- 'in',
7297
- 'then',
7298
- 'and',
7299
- 'else',
7300
- 'end',
7301
- 'otherwise',
7302
- 'when',
7303
- 'where',
7304
- 'catch',
7305
- 'finally',
7306
- ]);
7307
- function isGoURLTerminator(ctx) {
7308
- return ctx.isAtEnd() || GO_URL_STOP.has(ctx.peek().value);
7309
- }
7310
7345
  function stringNode(value, tok) {
7311
7346
  return {
7312
7347
  type: 'string',
@@ -7328,7 +7363,7 @@ function parseGoCommand(ctx, identifierNode) {
7328
7363
  continue;
7329
7364
  }
7330
7365
  if (isNakedURLStart(ctx)) {
7331
- const url = parseBareURLPath(ctx, isGoURLTerminator);
7366
+ const url = parseBareURLPath(ctx);
7332
7367
  if (url) {
7333
7368
  args.push(url);
7334
7369
  continue;
@@ -7468,13 +7503,6 @@ function parseMultiWordCommand(ctx, commandToken, commandName) {
7468
7503
  }
7469
7504
  return builder.build();
7470
7505
  }
7471
- function isFetchURLTerminator(ctx) {
7472
- if (ctx.isAtEnd())
7473
- return true;
7474
- const val = ctx.peek().value;
7475
- return (['as', 'with', '{', 'then', 'end', 'else', 'otherwise', ')'].includes(val) ||
7476
- isCommandBoundary(ctx));
7477
- }
7478
7506
  function isNakedURLStart(ctx) {
7479
7507
  const tok = ctx.peek();
7480
7508
  if (tok.value === '/')
@@ -7485,23 +7513,50 @@ function isNakedURLStart(ctx) {
7485
7513
  }
7486
7514
  return false;
7487
7515
  }
7488
- function parseBareURLPath(ctx, isTerminator = isFetchURLTerminator) {
7516
+ const URL_HARD_STOPS = new Set(['{', ')']);
7517
+ function parseBareURLPath(ctx) {
7489
7518
  const startPos = ctx.savePosition();
7519
+ const firstTok = ctx.peek();
7490
7520
  let path = '';
7491
- while (!ctx.isAtEnd() && !isTerminator(ctx)) {
7492
- path += ctx.advance().value;
7521
+ let prev = null;
7522
+ while (!ctx.isAtEnd()) {
7523
+ const tok = ctx.peek();
7524
+ if (prev && tok.start !== prev.end)
7525
+ break;
7526
+ if (tok.value === '$' && ctx.peekAt(1)?.value === '{') {
7527
+ ctx.advance();
7528
+ let last = ctx.advance();
7529
+ let depth = 1;
7530
+ while (!ctx.isAtEnd() && depth > 0) {
7531
+ last = ctx.advance();
7532
+ if (last.value === '{')
7533
+ depth++;
7534
+ else if (last.value === '}')
7535
+ depth--;
7536
+ }
7537
+ path += ctx.getInputSlice(tok.start, last.end);
7538
+ prev = last;
7539
+ continue;
7540
+ }
7541
+ if (URL_HARD_STOPS.has(tok.value))
7542
+ break;
7543
+ prev = ctx.advance();
7544
+ path += prev.value;
7493
7545
  }
7494
7546
  if (!path || path === '/') {
7495
7547
  ctx.restorePosition(startPos);
7496
7548
  return null;
7497
7549
  }
7498
- return {
7499
- type: 'literal',
7500
- value: path,
7501
- raw: path,
7502
- start: startPos,
7503
- end: ctx.savePosition(),
7550
+ const span = {
7551
+ start: firstTok.start,
7552
+ end: prev ? prev.end : firstTok.end,
7553
+ line: firstTok.line,
7554
+ column: firstTok.column,
7504
7555
  };
7556
+ if (path.includes('${')) {
7557
+ return { type: 'templateLiteral', value: path, ...span };
7558
+ }
7559
+ return { type: 'literal', value: path, raw: path, ...span };
7505
7560
  }
7506
7561
  function parseFetchCommand(ctx, commandToken) {
7507
7562
  const modifiers = {};
@@ -7732,10 +7787,10 @@ function parseTellCommand(ctx, identifierNode) {
7732
7787
  catch {
7733
7788
  break;
7734
7789
  }
7735
- if (ctx.match(KEYWORDS.AND)) {
7790
+ if (ctx.match(KEYWORDS.AND) || ctx.match(KEYWORDS.THEN)) {
7736
7791
  continue;
7737
7792
  }
7738
- if (ctx.check(KEYWORDS.THEN) || ctx.check(KEYWORDS.ELSE) || ctx.check(KEYWORDS.END)) {
7793
+ if (ctx.check(KEYWORDS.ELSE) || ctx.check(KEYWORDS.END)) {
7739
7794
  break;
7740
7795
  }
7741
7796
  if (ctx.checkIsCommand()) {
@@ -7938,6 +7993,7 @@ class Parser {
7938
7993
  const result = this.parseInternal();
7939
7994
  if (this.errors.length > 0) {
7940
7995
  result.errors = [...this.errors];
7996
+ result.recovered = true;
7941
7997
  }
7942
7998
  return result;
7943
7999
  }
@@ -9969,6 +10025,9 @@ class Parser {
9969
10025
  this.advance();
9970
10026
  const cmd = this.parseCommand();
9971
10027
  commands.push(cmd);
10028
+ if (this.match('then', 'and', ',')) {
10029
+ continue;
10030
+ }
9972
10031
  }
9973
10032
  else {
9974
10033
  break;