{
  "version": 3,
  "sources": ["../../../src/optimizer/transforms/optionalize.ts"],
  "sourcesContent": ["import type {AlternativeElementNode} from '../../parser/parse.js';\nimport type {Visitor} from '../../traverser/traverse.js';\nimport {isAlternativeContainer, isQuantifiable} from '../../parser/node-utils.js';\nimport {createQuantifier} from '../../parser/parse.js';\nimport {throwIfNullish} from '../../utils.js';\nimport {isAllowedSimpleNode, isNodeEqual} from './extract-prefix.js';\n\n/**\nCombine adjacent alternatives with only an added last node as the difference.\n*/\nconst optionalize: Visitor = {\n  '*'({node}) {\n    if (!isAlternativeContainer(node) || node.body.length < 2) {\n      return;\n    }\n    const {body} = node;\n    const newAlts = [body[0]];\n    let lastAltKept = body[0];\n    for (let i = 1; i < body.length; i++) {\n      // NOTE: Anytime we `continue` we don't keep this alt\n      const alt = body[i];\n      const altKids = alt.body;\n      const prevAltKids = lastAltKept.body;\n      const lengthDiff = Math.abs(altKids.length - prevAltKids.length);\n      if (!lengthDiff) {\n        if (isNodeArrayEqual(altKids, prevAltKids)) {\n          continue;\n        }\n      } else if (lengthDiff === 1) {\n        const isPrevAltLonger = !!(prevAltKids.length > altKids.length);\n        const altKidsToCompare = isPrevAltLonger ? altKids : altKids.slice(0, -1);\n        const prevAltKidsToCompare = isPrevAltLonger ? prevAltKids.slice(0, -1) : prevAltKids;\n        if (isNodeArrayEqual(altKidsToCompare, prevAltKidsToCompare)) {\n          if (isPrevAltLonger) {\n            const prevAltLastKid = throwIfNullish(prevAltKids.at(-1));\n            if (isQuantifiable(prevAltLastKid)) {\n              // Avoid chaining quantifiers since e.g. chained greedy `?` is `?{0,1}` and can\n              // lengthen the pattern\n              if (prevAltLastKid.type === 'Quantifier') {\n                if (!prevAltLastKid.min) {\n                  continue;\n                } else if (prevAltLastKid.min === 1 && prevAltLastKid.kind !== 'lazy') {\n                  prevAltLastKid.min = 0;\n                  continue;\n                }\n              } else {\n                // Put the prev alt's extra last node in a greedy `?`\n                prevAltKids.pop();\n                prevAltKids.push(createQuantifier('greedy', 0, 1, prevAltLastKid));\n                continue;\n              }\n            }\n          } else if (\n            // Don't apply if last alt empty since that would lengthen e.g. `(|a|b)` to `(a??|b)`\n            prevAltKids.length > 0 ||\n            // Unless there are two alts since e.g. `(?:|a)` to `(?:a??)` enables group unwrapping\n            body.length === 2\n          ) {\n            const altLastKid = throwIfNullish(altKids.at(-1));\n            if (isQuantifiable(altLastKid)) {\n              if (altLastKid.type === 'Quantifier') {\n                if (altLastKid.kind === 'possessive') {\n                  // No-op since possessive quantifiers can't also be lazy\n                } else if (altLastKid.min <= 1 && altLastKid.kind === 'lazy') {\n                  altLastKid.min = 0;\n                  prevAltKids.push(altLastKid);\n                  continue;\n                } else if (!altLastKid.min && altLastKid.max === 1) {\n                  altLastKid.kind = 'lazy';\n                  prevAltKids.push(altLastKid);\n                  continue;\n                }\n              } else {\n                // Put this alt's extra last node in a lazy `??` then add it to the prev alt\n                prevAltKids.push(createQuantifier('lazy', 0, 1, altLastKid));\n                continue;\n              }\n            }\n          }\n        }\n      }\n      newAlts.push(alt);\n      lastAltKept = alt;\n    }\n    node.body = newAlts;\n  },\n};\n\n// Returns `false` if the arrays contain a node type it doesn't know how to compare, or doesn't\n// want to compare (e.g. with capturing groups, which can't be removed)\nfunction isNodeArrayEqual(a: Array<AlternativeElementNode>, b: Array<AlternativeElementNode>) {\n  if (a.length !== b.length) {\n    return false;\n  }\n  for (let i = 0; i < a.length; i++) {\n    if (!isAllowedSimpleNode(a[i]) || !isAllowedSimpleNode(b[i])) {\n      return false;\n    }\n    if (!isNodeEqual(a[i], b[i])) {\n      return false;\n    }\n  }\n  return true;\n}\n\nexport {\n  optionalize,\n};\n"],
  "mappings": "aAEA,OAAQ,0BAAAA,EAAwB,kBAAAC,MAAqB,6BACrD,OAAQ,oBAAAC,MAAuB,wBAC/B,OAAQ,kBAAAC,MAAqB,iBAC7B,OAAQ,uBAAAC,EAAqB,eAAAC,MAAkB,sBAK/C,MAAMC,EAAuB,CAC3B,IAAI,CAAC,KAAAC,CAAI,EAAG,CACV,GAAI,CAACP,EAAuBO,CAAI,GAAKA,EAAK,KAAK,OAAS,EACtD,OAEF,KAAM,CAAC,KAAAC,CAAI,EAAID,EACTE,EAAU,CAACD,EAAK,CAAC,CAAC,EACxB,IAAIE,EAAcF,EAAK,CAAC,EACxB,QAASG,EAAI,EAAGA,EAAIH,EAAK,OAAQG,IAAK,CAEpC,MAAMC,EAAMJ,EAAKG,CAAC,EACZE,EAAUD,EAAI,KACdE,EAAcJ,EAAY,KAC1BK,EAAa,KAAK,IAAIF,EAAQ,OAASC,EAAY,MAAM,EAC/D,GAAKC,GAIE,GAAIA,IAAe,EAAG,CAC3B,MAAMC,EAAqBF,EAAY,OAASD,EAAQ,OAClDI,EAAmBD,EAAkBH,EAAUA,EAAQ,MAAM,EAAG,EAAE,EAClEK,EAAuBF,EAAkBF,EAAY,MAAM,EAAG,EAAE,EAAIA,EAC1E,GAAIK,EAAiBF,EAAkBC,CAAoB,GACzD,GAAIF,EAAiB,CACnB,MAAMI,EAAiBjB,EAAeW,EAAY,GAAG,EAAE,CAAC,EACxD,GAAIb,EAAemB,CAAc,EAG/B,GAAIA,EAAe,OAAS,aAC1B,GAAKA,EAAe,KAEb,GAAIA,EAAe,MAAQ,GAAKA,EAAe,OAAS,OAAQ,CACrEA,EAAe,IAAM,EACrB,QACF,MAJE,cAKG,CAELN,EAAY,IAAI,EAChBA,EAAY,KAAKZ,EAAiB,SAAU,EAAG,EAAGkB,CAAc,CAAC,EACjE,QACF,CAEJ,SAEEN,EAAY,OAAS,GAErBN,EAAK,SAAW,EAChB,CACA,MAAMa,EAAalB,EAAeU,EAAQ,GAAG,EAAE,CAAC,EAChD,GAAIZ,EAAeoB,CAAU,EAC3B,GAAIA,EAAW,OAAS,cACtB,GAAIA,EAAW,OAAS,cAEjB,GAAIA,EAAW,KAAO,GAAKA,EAAW,OAAS,OAAQ,CAC5DA,EAAW,IAAM,EACjBP,EAAY,KAAKO,CAAU,EAC3B,QACF,SAAW,CAACA,EAAW,KAAOA,EAAW,MAAQ,EAAG,CAClDA,EAAW,KAAO,OAClBP,EAAY,KAAKO,CAAU,EAC3B,QACF,OACK,CAELP,EAAY,KAAKZ,EAAiB,OAAQ,EAAG,EAAGmB,CAAU,CAAC,EAC3D,QACF,CAEJ,EAEJ,UAvDMF,EAAiBN,EAASC,CAAW,EACvC,SAuDJL,EAAQ,KAAKG,CAAG,EAChBF,EAAcE,CAChB,CACAL,EAAK,KAAOE,CACd,CACF,EAIA,SAASU,EAAiBG,EAAkCC,EAAkC,CAC5F,GAAID,EAAE,SAAWC,EAAE,OACjB,MAAO,GAET,QAASZ,EAAI,EAAGA,EAAIW,EAAE,OAAQX,IAI5B,GAHI,CAACP,EAAoBkB,EAAEX,CAAC,CAAC,GAAK,CAACP,EAAoBmB,EAAEZ,CAAC,CAAC,GAGvD,CAACN,EAAYiB,EAAEX,CAAC,EAAGY,EAAEZ,CAAC,CAAC,EACzB,MAAO,GAGX,MAAO,EACT,CAEA,OACEL,KAAA",
  "names": ["isAlternativeContainer", "isQuantifiable", "createQuantifier", "throwIfNullish", "isAllowedSimpleNode", "isNodeEqual", "optionalize", "node", "body", "newAlts", "lastAltKept", "i", "alt", "altKids", "prevAltKids", "lengthDiff", "isPrevAltLonger", "altKidsToCompare", "prevAltKidsToCompare", "isNodeArrayEqual", "prevAltLastKid", "altLastKid", "a", "b"]
}
