{"version":3,"file":"parser.mjs","sources":["../../../../../../src/composables/useInputMask/masks/parser.ts"],"sourcesContent":["/* eslint-disable no-use-before-define */\ninterface TokenBase {\n  type: string\n  expect: string\n}\n\ninterface TokenChar extends TokenBase {\n  type: 'char'\n}\n\ninterface TokenRegex extends TokenBase {\n  type: 'regex'\n}\n\ninterface TokenRepeated extends TokenBase {\n  type: 'repeated',\n  tree: Token[]\n  min: number,\n  max: number,\n  content: string\n}\n\ninterface TokenGroup extends TokenBase {\n  type: 'group',\n  tree: Token[]\n}\n\ninterface TokenOrRegex extends TokenBase {\n  type: 'or regex',\n  left: Token[],\n  right: Token[]\n}\n\nexport type Token = TokenChar | TokenRegex | TokenRepeated | TokenGroup | TokenOrRegex\n\nconst or = (...args: RegExp[]) => new RegExp(args.map((r) => r.source).join('|'), 'g')\n\nconst TOKEN_SPLIT_REGEX = or(\n  /(\\{[^}]*\\})/, // Token required to have limits {1, 3}, {1,}, {1}\n  /(\\\\[dws.])/,\n  /(^\\([^)]*\\)$)/, // group like (test)\n  /(\\[[^\\]]*\\])/, // split by [^3]{1}, [a-z], [0-9]{1, 3}\n  /(?:)/, // split for each letter\n)\n\n/**\n * Checks if the symbol contains correct (.)\n *\n * @example\n * `(.)(.)` must be invalid - two groups\n * `((.)(.))` is valid - single group with nested groups\n */\nconst isMaskSingleGroup = (symbol: string) => {\n  if (!symbol.startsWith('(') || !symbol.endsWith(')')) { return false }\n\n  let groupDepth = 0\n  for (let i = 0; i < symbol.length; i++) {\n    const char = symbol[i]\n    if (char === '(') {\n      groupDepth += 1\n    } else if (char === ')') {\n      groupDepth -= 1\n\n      if (groupDepth === 0 && i !== symbol.length - 1) {\n        return false\n      }\n    }\n  }\n\n  return groupDepth === 0\n}\n\n/**\n * Parse raw tokens (strings). Split tokens into groups: char, (), {}, [], etc.\n *\n * @example\n *\n * `(.)(.){1,2}` -> ['(.)', '(.){1,2}']\n * `((.)|(.)){2}text(.)` -> ['((.)|(.)){2}', 'text', '(.)']\n */\nconst parseRawTokens = (symbol: string) => {\n  let group = 0\n  const groups = []\n  let currentChunk = ''\n\n  let i = 0\n\n  while (i < symbol.length) {\n    if (symbol[i] === '(' && symbol[i - 1] !== '\\\\') {\n      if (group === 0 && currentChunk.length > 0) {\n        groups.push(...currentChunk.split(TOKEN_SPLIT_REGEX).filter((v) => v !== '' && v !== undefined))\n        currentChunk = ''\n      }\n      group += 1\n    }\n\n    currentChunk += symbol[i]\n\n    if (symbol[i] === ')' && symbol[i - 1] !== '\\\\') {\n      group -= 1\n\n      if (group === 0 && currentChunk.length > 0) {\n        groups.push(currentChunk)\n        currentChunk = ''\n      }\n    }\n\n    i++\n  }\n\n  if (currentChunk.length > 0) {\n    groups.push(...currentChunk.split(TOKEN_SPLIT_REGEX).filter((v) => v !== '' && v !== undefined))\n  }\n\n  return groups\n    .map((g) => g.replace(/^\\?[:!>]/, '')) // Remove group modifiers\n    .filter((v) => v !== '' && v !== undefined)\n}\n\n// TODO: Maybe add more symbols to support\nconst RESERVED_SLASH_SYMBOLS = ['d', 'D', 'w', 'W', 's', 'S', '.']\n\nconst MAX_REPEATED = 10\n\n/** Build ast of tokens */\nexport const parseTokens = (mask: string, directlyInGroup = false): Token[] => {\n  let tokens: Token[] = []\n\n  // Handle or in group, if single group - treat as directly in group\n  if (isMaskSingleGroup(mask)) {\n    mask = mask.slice(1, -1) // Remove brackets\n    directlyInGroup = true\n  }\n\n  const rawTokens = parseRawTokens(mask)\n\n  for (let i = 0; i < rawTokens.length; i++) {\n    const rawToken = rawTokens[i]\n\n    if (rawToken === '\\\\') {\n      // Ignore \\, it is used in pair with next token\n      continue\n    }\n\n    if (!RESERVED_SLASH_SYMBOLS.includes(rawToken) && rawTokens[i - 1] === '\\\\') {\n      tokens.push({ type: 'char', expect: rawToken })\n      continue\n    }\n\n    if (rawToken === '|') {\n      if (directlyInGroup) {\n        tokens = [{\n          type: 'or regex',\n          expect: mask,\n          left: [...tokens],\n          right: parseTokens(`(${rawTokens.slice(i + 1).join('')})`),\n        }]\n\n        break\n      }\n\n      const prevToken = tokens.pop()!\n      const nextToken = parseTokens(rawTokens[i + 1])\n\n      tokens.push({\n        type: 'or regex',\n        expect: `${prevToken}|${rawTokens[i + 1]}`,\n        left: [prevToken],\n        right: nextToken,\n      })\n\n      continue\n    }\n\n    if (rawToken.startsWith('{') && rawToken.endsWith('}') && rawToken.length > 2) {\n      const [v, min, delimiter, max] = rawToken.split(/\\{(\\d+)(,\\s?)?(\\d+)?\\}$/)\n\n      const prevToken = tokens.pop()!\n\n      tokens.push({\n        type: 'repeated',\n        expect: prevToken.expect + rawToken,\n        tree: [prevToken],\n        min: parseInt(min),\n        max: max ? parseInt(max) : delimiter ? MAX_REPEATED : parseInt(min),\n        content: rawToken,\n      })\n      continue\n    }\n\n    if (rawToken.endsWith('*')) {\n      const prevToken = tokens.pop()!\n      tokens.push({ type: 'repeated', expect: prevToken.expect + rawToken, tree: [prevToken], min: 0, max: MAX_REPEATED, content: prevToken.expect })\n      continue\n    }\n\n    if (rawToken.endsWith('+')) {\n      const prevToken = tokens.pop()!\n      tokens.push({ type: 'repeated', expect: prevToken.expect + rawToken, tree: [prevToken], min: 1, max: MAX_REPEATED, content: prevToken.expect })\n      continue\n    }\n\n    if (rawToken.endsWith('?')) {\n      const prevToken = tokens.pop()!\n      tokens.push({ type: 'repeated', expect: prevToken.expect + rawToken, tree: [prevToken], min: 0, max: 1, content: prevToken.expect })\n      continue\n    }\n\n    if (['$', '^'].includes(rawToken)) {\n      // Ignore start and end of the string - they're not important for masking\n      continue\n    }\n\n    if (rawToken.startsWith('(') && rawToken.endsWith(')')) {\n      const tree = parseTokens(rawToken.slice(1, -1), true)\n      tokens.push({ type: 'group', expect: rawToken, tree })\n      continue\n    }\n\n    if (rawToken.length === 1 && rawToken !== '.') {\n      tokens.push({ type: 'char', expect: rawToken })\n      continue\n    }\n\n    tokens.push({ type: 'regex', expect: rawToken })\n  }\n\n  return tokens\n}\n"],"names":[],"mappings":"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"}