@mojir/lits 2.1.28 → 2.1.29

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.
@@ -4,7 +4,7 @@ export { type LitsFunction, type NativeJsFunction } from './parser/types';
4
4
  export type { Context } from './evaluator/interface';
5
5
  export type { Ast } from './parser/types';
6
6
  export type { SourceCodeInfo } from './tokenizer/token';
7
- export type { Token } from './tokenizer/token';
7
+ export type { Token, TokenType } from './tokenizer/token';
8
8
  export { normalExpressionKeys, specialExpressionKeys } from './builtin';
9
9
  export { Lits } from './Lits/Lits';
10
10
  export { type LitsError, isLitsError } from './errors';
@@ -1,10 +1,11 @@
1
1
  import type { ReservedSymbol } from './reservedNames';
2
2
  import { type SymbolicBinaryOperator, type SymbolicOperator } from './operators';
3
- export declare const tokenTypes: readonly ["LBrace", "LBracket", "RBrace", "RBracket", "LParen", "RParen", "BasePrefixedNumber", "DocString", "MultiLineComment", "Number", "Operator", "RegexpShorthand", "ReservedSymbol", "SingleLineComment", "String", "Symbol", "Whitespace"];
3
+ export declare const tokenTypes: readonly ["LBrace", "LBracket", "RBrace", "RBracket", "LParen", "RParen", "BasePrefixedNumber", "DocString", "Error", "MultiLineComment", "Number", "Operator", "RegexpShorthand", "ReservedSymbol", "SingleLineComment", "String", "Symbol", "Whitespace"];
4
4
  export type TokenType = typeof tokenTypes[number];
5
5
  declare const modifierNames: readonly ["&rest", "&let", "&when", "&while"];
6
6
  export type ModifierName = typeof modifierNames[number];
7
7
  type GenericToken<T extends TokenType, V extends string = string> = [T, V] | [T, V, SourceCodeInfo];
8
+ export type ErrorToken = ['Error', string, SourceCodeInfo | undefined, string];
8
9
  export type LBraceToken = GenericToken<'LBrace', '{'>;
9
10
  export type LBracketToken = GenericToken<'LBracket', '['>;
10
11
  export type LParenToken = GenericToken<'LParen', '('>;
@@ -22,7 +23,7 @@ export type StringToken = GenericToken<'String'>;
22
23
  export type DocStringToken = GenericToken<'DocString'>;
23
24
  export type SymbolToken<T extends string = string> = GenericToken<'Symbol', T>;
24
25
  export type WhitespaceToken = GenericToken<'Whitespace'>;
25
- export type Token = LBraceToken | LBracketToken | LParenToken | RBraceToken | RBracketToken | RParenToken | BasePrefixedNumberToken | DocStringToken | MultiLineCommentToken | NumberToken | OperatorToken | RegexpShorthandToken | ReservedSymbolToken | SingleLineCommentToken | StringToken | SymbolToken | WhitespaceToken;
26
+ export type Token = LBraceToken | LBracketToken | LParenToken | RBraceToken | RBracketToken | RParenToken | BasePrefixedNumberToken | DocStringToken | ErrorToken | MultiLineCommentToken | NumberToken | OperatorToken | RegexpShorthandToken | ReservedSymbolToken | SingleLineCommentToken | StringToken | SymbolToken | WhitespaceToken;
26
27
  export type TokenDescriptor<T extends Token> = [length: number, token?: T];
27
28
  export interface SourceCodeInfo {
28
29
  position: {
@@ -1,5 +1,5 @@
1
- import type { BasePrefixedNumberToken, DocStringToken, LBraceToken, LBracketToken, LParenToken, MultiLineCommentToken, NumberToken, OperatorToken, RBraceToken, RBracketToken, RParenToken, RegexpShorthandToken, ReservedSymbolToken, SingleLineCommentToken, StringToken, SymbolToken, Token, TokenDescriptor, WhitespaceToken } from './token';
2
- export type Tokenizer<T extends Token> = (input: string, position: number) => TokenDescriptor<T>;
1
+ import type { BasePrefixedNumberToken, DocStringToken, ErrorToken, LBraceToken, LBracketToken, LParenToken, MultiLineCommentToken, NumberToken, OperatorToken, RBraceToken, RBracketToken, RParenToken, RegexpShorthandToken, ReservedSymbolToken, SingleLineCommentToken, StringToken, SymbolToken, Token, TokenDescriptor, WhitespaceToken } from './token';
2
+ export type Tokenizer<T extends Token> = (input: string, position: number) => TokenDescriptor<T | ErrorToken>;
3
3
  export declare const NO_MATCH: TokenDescriptor<never>;
4
4
  export declare const tokenizeDocString: Tokenizer<DocStringToken>;
5
5
  export declare const tokenizeWhitespace: Tokenizer<WhitespaceToken>;
@@ -13311,7 +13311,7 @@ var tokenizeDocString = function (input, position) {
13311
13311
  nextThreeChars = input.slice(position + length, position + length + 3);
13312
13312
  }
13313
13313
  if (!char) {
13314
- throw new LitsError("Unclosed doc string at position ".concat(position, "."), undefined);
13314
+ return [length, ['Error', value, undefined, "Unclosed doc string at position ".concat(position)]];
13315
13315
  }
13316
13316
  value += '"""'; // closing quote
13317
13317
  return [length + 3, ['DocString', value]];
@@ -13338,7 +13338,7 @@ var tokenizeString = function (input, position) {
13338
13338
  char = input[position + length];
13339
13339
  }
13340
13340
  if (!char) {
13341
- throw new LitsError("Unclosed string at position ".concat(position, "."), undefined);
13341
+ return [length, ['Error', value, undefined, "Unclosed string at position ".concat(position)]];
13342
13342
  }
13343
13343
  value += '"'; // closing quote
13344
13344
  return [length + 1, ['String', value]];
@@ -13349,16 +13349,20 @@ var tokenizeRegexpShorthand = function (input, position) {
13349
13349
  var _a = __read(tokenizeString(input, position + 1), 2), stringLength = _a[0], token = _a[1];
13350
13350
  if (!token)
13351
13351
  return NO_MATCH;
13352
+ if (token[0] === 'Error') {
13353
+ var errorToken = ['Error', "#".concat(token[1]), undefined, "Unclosed regexp at position ".concat(position)];
13354
+ return [stringLength + 1, errorToken];
13355
+ }
13352
13356
  position += stringLength + 1;
13353
13357
  var length = stringLength + 1;
13354
13358
  var options = '';
13355
13359
  while (input[position] === 'g' || input[position] === 'i') {
13356
- if (options.includes(input[position])) {
13357
- throw new LitsError("Duplicated regexp option \"".concat(input[position], "\" at position ").concat(position, "."), undefined);
13358
- }
13359
13360
  options += input[position];
13360
13361
  length += 1;
13361
13362
  position += 1;
13363
+ if (options.includes(input[position])) {
13364
+ return [length, ['Error', "#".concat(token[1]).concat(options), undefined, "Duplicated regexp option \"".concat(input[position], "\"")]];
13365
+ }
13362
13366
  }
13363
13367
  return [length, ['RegexpShorthand', "#".concat(token[1]).concat(options)]];
13364
13368
  };
@@ -13402,7 +13406,7 @@ var tokenizeNumber = function (input, position) {
13402
13406
  if (i === start) {
13403
13407
  return NO_MATCH;
13404
13408
  }
13405
- throw new LitsError("Invalid number format at position ".concat(i, "."), undefined);
13409
+ return [i - position + 1, ['Error', input.substring(position, i + 1), undefined, "Invalid number format at position ".concat(i + 1)]];
13406
13410
  }
13407
13411
  }
13408
13412
  else if (char === '.') {
@@ -13410,7 +13414,7 @@ var tokenizeNumber = function (input, position) {
13410
13414
  return NO_MATCH;
13411
13415
  }
13412
13416
  if (hasDecimalPoint || hasExponent) {
13413
- throw new LitsError("Invalid number format at position ".concat(i, "."), undefined);
13417
+ return [i - position + 1, ['Error', input.substring(position, i + 1), undefined, "Invalid number format at position ".concat(i + 1)]];
13414
13418
  }
13415
13419
  hasDecimalPoint = true;
13416
13420
  }
@@ -13419,10 +13423,10 @@ var tokenizeNumber = function (input, position) {
13419
13423
  return NO_MATCH;
13420
13424
  }
13421
13425
  if (hasExponent) {
13422
- throw new LitsError("Invalid number format at position ".concat(i, "."), undefined);
13426
+ return [i - position + 1, ['Error', input.substring(position, i + 1), undefined, "Invalid number format at position ".concat(i + 1)]];
13423
13427
  }
13424
13428
  if (input[i - 1] === '.' || input[i - 1] === '+' || input[i - 1] === '-') {
13425
- throw new LitsError("Invalid number format at position ".concat(i, "."), undefined);
13429
+ return [i - position + 1, ['Error', input.substring(position, i + 1), undefined, "Invalid number format at position ".concat(i + 1)]];
13426
13430
  }
13427
13431
  if (input[i + 1] === '+' || input[i + 1] === '-') {
13428
13432
  i += 1;
@@ -13442,7 +13446,7 @@ var tokenizeNumber = function (input, position) {
13442
13446
  }
13443
13447
  var nextChar = input[i];
13444
13448
  if (nextChar && nextChar !== ':' && !postNumberRegExp.test(nextChar)) {
13445
- throw new LitsError("Invalid number format at position ".concat(i, "."), undefined);
13449
+ return [i - position + 1, ['Error', input.substring(position, i + 1), undefined, "Invalid number format at position ".concat(i + 1)]];
13446
13450
  }
13447
13451
  return [length, ['Number', input.substring(position, i)]];
13448
13452
  };
@@ -13492,7 +13496,7 @@ var tokenizeSymbol = function (input, position) {
13492
13496
  var escaping = false;
13493
13497
  while (char !== '\'' || escaping) {
13494
13498
  if (char === undefined)
13495
- throw new LitsError("Unclosed string at position ".concat(position, "."), undefined);
13499
+ return [length_1, ['Error', value, undefined, "Unclosed quoted symbol at position ".concat(position)]];
13496
13500
  length_1 += 1;
13497
13501
  if (escaping) {
13498
13502
  escaping = false;
@@ -13563,7 +13567,7 @@ var tokenizeMultiLineComment = function (input, position) {
13563
13567
  length_2 += 1;
13564
13568
  }
13565
13569
  if (position + length_2 + 1 >= input.length) {
13566
- throw new LitsError('Comment not closed', undefined);
13570
+ return [length_2, ['Error', value, undefined, "Unclosed multi-line comment at position ".concat(position)]];
13567
13571
  }
13568
13572
  value += '*/';
13569
13573
  length_2 += 2;
@@ -13616,9 +13620,6 @@ function tokenize(input, debug, filePath) {
13616
13620
  ? createSourceCodeInfo(input, position, filePath)
13617
13621
  : undefined;
13618
13622
  var tokenDescriptor = getCurrentToken(input, position);
13619
- if (!tokenDescriptor) {
13620
- throw new LitsError("Unrecognized character '".concat(input[position], "'."), sourceCodeInfo);
13621
- }
13622
13623
  var _a = __read(tokenDescriptor, 2), count = _a[0], token = _a[1];
13623
13624
  position += count;
13624
13625
  if (token) {
@@ -13669,7 +13670,7 @@ function getCurrentToken(input, position) {
13669
13670
  }
13670
13671
  finally { if (e_1) throw e_1.error; }
13671
13672
  }
13672
- return null;
13673
+ return [1, ['Error', input[initialPosition], undefined, 'Unrecognized character']];
13673
13674
  }
13674
13675
 
13675
13676
  function isSymbolToken(token, symbolName) {
@@ -13957,6 +13958,11 @@ var Parser = /** @class */ (function () {
13957
13958
  this.parseState.position += 1;
13958
13959
  };
13959
13960
  Parser.prototype.parse = function () {
13961
+ this.tokenStream.tokens.forEach(function (token) {
13962
+ if (token[0] === 'Error') {
13963
+ throw new LitsError(token[3], token[2]);
13964
+ }
13965
+ });
13960
13966
  var nodes = [];
13961
13967
  while (!this.isAtEnd()) {
13962
13968
  nodes.push(this.parseExpression(0, true));
@@ -15023,20 +15029,14 @@ var AutoCompleter = /** @class */ (function () {
15023
15029
  this.suggestions = [];
15024
15030
  this.suggestionIndex = null;
15025
15031
  var partialProgram = this.originalProgram.slice(0, this.originalPosition);
15026
- var tokenStream = null;
15027
- try {
15028
- tokenStream = lits.tokenize(partialProgram);
15029
- }
15030
- catch (_a) {
15031
- // do nothing
15032
- }
15033
- if (!tokenStream) {
15034
- return;
15035
- }
15032
+ var tokenStream = lits.tokenize(partialProgram);
15036
15033
  var lastToken = tokenStream.tokens.at(-1);
15037
15034
  if (!lastToken) {
15038
15035
  return;
15039
15036
  }
15037
+ if (lastToken[0] === 'Error') {
15038
+ return;
15039
+ }
15040
15040
  this.searchString = lastToken[1];
15041
15041
  this.prefixProgram = this.originalProgram.slice(0, this.originalPosition - this.searchString.length);
15042
15042
  this.suffixProgram = this.originalProgram.slice(this.prefixProgram.length + this.searchString.length);