{"version":3,"sources":["../src/core/run.ts","../src/core/tryRun.ts","../src/core/grammar.ts","../src/parsers/any.ts","../src/parsers/defer.ts","../src/parsers/eof.ts","../src/utils/unicode.ts","../src/parsers/string.ts","../src/combinators/choice.ts","../src/combinators/error.ts","../src/parsers/eol.ts","../src/parsers/regexp.ts","../src/parsers/letter.ts","../src/parsers/noneOf.ts","../src/parsers/nothing.ts","../src/parsers/numbers.ts","../src/parsers/oneOf.ts","../src/parsers/rest.ts","../src/parsers/whitespace.ts"],"names":["run","parser","input","ParserError","res","tryRun","result","grammar","init","key","any","pos","nextPos","value","defer","deferred","eof","size","string","bytes","index","high","low","match","slice","span","ustring","choice","ps","first","rest","nextResult","error","expected","EOL_UNIX","EOL_NON_UNIX","eol","regexp","rs","re","LETTER_RE","LETTERS_RE","letter","letters","noneOf","chars","charset","char","nothing","_","HEXADECIMAL_RE","BINARY_RE","OCTAL_RE","WHOLE_RE","INTEGER_RE","FLOAT_RE","hex","binary","octal","whole","integer","float","oneOf","WHITESPACE_REQUIRED_RE","whitespace"],"mappings":"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","sourcesContent":["import type { Parser, Result } from '@types'\n\n/** @internal */\ninterface Runnable<T> {\n  with(input: string): Result<T>\n}\n\n/**\n * Runs a parser with provided input.\n *\n * @param parser - Parser to run\n *\n * @returns Parser result\n */\nexport function run<T>(parser: Parser<T>): Runnable<T> {\n  return {\n    with(input) {\n      return parser.parse(input, 0)\n    }\n  }\n}\n","import type { Failure, Parser, Span, Success } from '@types'\n\n/** @internal */\ninterface Runnable<T> {\n  with(input: string): Success<T>\n}\n\n/** @internal */\ntype ErrorResult = Omit<Failure, 'isOk'>\n\nexport class ParserError extends Error {\n  readonly name = 'ParserError'\n\n  readonly span: Span\n  readonly pos: number\n\n  constructor(res: ErrorResult) {\n    super(res.expected)\n\n    this.span = res.span\n    this.pos = res.pos\n  }\n}\n\n/**\n * Runs a parser with provided input, throwing on failure.\n *\n * @param parser - Parser to run\n * @throws {@link ParserError} Parser error with `message` (`expected`) `span`, and `pos`\n *\n * @returns Parser result\n */\nexport function tryRun<T>(parser: Parser<T>): Runnable<T> {\n  return {\n    with(input) {\n      const result = parser.parse(input, 0)\n\n      switch (result.isOk) {\n        case true: {\n          return result\n        }\n\n        case false: {\n          throw new ParserError(result)\n        }\n      }\n    }\n  }\n}\n","import type { Parser } from '@lib/types'\n\n/**\n * This type extracts the return-types from the parser initializers.\n */\nexport type Grammar<T> = {\n  [P in keyof T]: T[P] extends () => unknown ? ReturnType<T[P]> : never\n}\n\n/**\n * This type injects the initialized parser types into `this`, allowing for\n * type-safe self-contained and mutually recursive grammars.\n */\nexport type GrammarInit<T> = T & ThisType<Grammar<T>>\n\n/**\n * This defines the input to the `grammar` function - the parser initializers.\n */\nexport type GrammarType = {\n  [name: string]: () => Parser<unknown>\n}\n\n/**\n * This is a utility function to simplify the creation of a self-contained grammar.\n *\n * Similarly to `defer`, this allows for the creation of mutually recursive parsers,\n * but lets you define all of the component parsers within a single call.\n *\n * The function takes an object with parser initializers, and returns an object with\n * all of those parsers initialized. Within the parser initializers, use `this` to\n * reference other initialized parsers, as in the example below.\n *\n * The properties of the resulting object are just regular parsers - you can freely\n * destructure these, pass them around individually, or compose them with other\n * grammars, parsers or combinators as needed.\n *\n * @example\n *\n * ```typescript\n * interface NumberNode {\n *   type: 'number'\n *   value: number\n * }\n *\n * interface ListNode {\n *   type: 'list'\n *   value: Array<NumberNode | ListNode>\n * }\n *\n * const tupleGrammar = grammar({\n *   tupleNumber(): Parser<NumberNode> {\n *     return map(integer(), (value, span) => ({ type: 'number', span, value }))\n *   },\n *   tupleList(): Parser<ListNode> {\n *     return map(\n *       takeMid(\n *         string('('),\n *         sepBy(choice(this.tupleList, this.tupleNumber), string(',')),\n *         string(')')\n *       ),\n *       (value, span) => ({ type: 'list', span, value })\n *     )\n *   }\n * })\n *\n * const result = run(tupleGrammar.tupleList).with('(1,2,(3,4))')\n * ```\n */\nexport function grammar<T extends GrammarType>(init: GrammarInit<T>): Grammar<T> {\n  const grammar = {} as { [key: string]: Parser<unknown> }\n\n  for (const key in init) {\n    grammar[key] = {\n      // istanbul ignore next\n      parse() {\n        throw new Error(`internal error`) // this line should never execute\n      }\n    }\n  }\n\n  for (const key in init) {\n    grammar[key].parse = init[key].apply(grammar).parse\n  }\n\n  return grammar as Grammar<T>\n}\n","import type { Parser } from '@types'\n\n/**\n * Parses any single character from the input and returns it. Fails at the end of input.\n *\n * @returns A single parsed character.\n */\nexport function any(): Parser<string> {\n  return {\n    parse(input, pos) {\n      if (input.length === pos) {\n        return {\n          isOk: false,\n          span: [pos, pos],\n          pos,\n          expected: 'any @ reached the end of input'\n        }\n      }\n\n      const nextPos = pos + 1\n      const value = input.substring(pos, nextPos)\n\n      return {\n        isOk: true,\n        span: [pos, nextPos],\n        pos: nextPos,\n        value\n      }\n    }\n  }\n}\n","import type { Parser } from '@types'\n\n/**\n * Intersection type to add a method for deferred parser definition.\n *\n * @internal\n */\ntype Deferred<T> = Parser<T> & {\n  with(parser: Parser<T>): void\n}\n\n/**\n * This is a special parser that has an additional `with` method, which should be used to define the\n * parser. This parser is tailored for creating mutually recursive parsers.\n *\n * @example\n *\n * ```typescript\n * interface NumberNode {\n *   type: 'number'\n *   value: number\n * }\n *\n * interface ListNode {\n *   type: 'list'\n *   value: Array<NumberNode | ListNode>\n * }\n *\n * // Here we create 'dummies'\n *\n * const TupleList = defer<ListNode>()\n * const TupleNumber = defer<NumberNode>()\n *\n * // And below we actually define parsers\n *\n * TupleNumber.with(\n *   map(\n *     int(),\n *     (value) => ({ type: 'number', value })\n *   )\n * )\n *\n * TupleList.with(\n *   map(\n *     takeMid(\n *       string('('),\n *       sepBy(choice(TupleList, TupleNumber), string(',')),\n *       string(')')\n *     ),\n *     (value) => ({ type: 'list', value })\n *   )\n * )\n *\n * console.log(\n *   run(TupleList).with('(1,2,(3,(4,5)))')\n * )\n * ```\n */\nexport function defer<T>(): Deferred<T> {\n  let deferred: Parser<T> | null = null\n\n  return {\n    with(parser): void {\n      deferred = parser\n    },\n\n    parse(input, pos) {\n      if (deferred) {\n        return deferred.parse(input, pos)\n      }\n\n      throw new Error('Deferred parser was not initialized')\n    }\n  }\n}\n","import type { Parser } from '@types'\n\n/**\n * Only succeeds at the end of the input.\n *\n * @returns `null`\n */\nexport function eof(): Parser<null> {\n  return {\n    parse(input, pos) {\n      switch (pos === input.length) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, pos],\n            pos: input.length,\n            value: null\n          }\n        }\n\n        case false: {\n          return {\n            isOk: false,\n            span: [pos, pos],\n            pos,\n            expected: 'end of input'\n          }\n        }\n      }\n    }\n  }\n}\n","/**\n * Iterates over a given Unicode string and counts its length in bytes.\n *\n * Covers Basic Multilingual Plane with all 163 blocks in range from `0x0000` to `0xFFFF`.\n *\n * @internal\n */\nexport function size(string: string): number {\n  const size = string.length\n  let bytes = 0\n\n  for (let index = 0; index < size; index++) {\n    const high = string.charCodeAt(index)\n\n    switch (true) {\n      // [0x0000, 0x007F] - [Basic Latin]\n      case high < 0x0080: {\n        bytes += 1\n        break\n      }\n\n      // [0x0080, 0x07FF] - [Latin-1 Supplement, NKo]\n      case high < 0x0800: {\n        bytes += 2\n        break\n      }\n\n      // [0x0800, 0xD7FF] - [Samaritan, Hangul Jamo Extended-B]\n      case high < 0xd800: {\n        bytes += 3\n        break\n      }\n\n      // [0xD800, 0xDBFF] - [High Surrogates, High Private Use Surrogates]\n      case high < 0xdc00: {\n        // Stepping into low surrogates territory. Here we should be using **two** code points.\n        const low = string.charCodeAt(++index)\n\n        // Followed by: [0xDC00, 0xDFFF] - [Low Surrogates]\n        if (index < size && low >= 0xdc00 && low <= 0xdfff) {\n          bytes += 4\n          break\n        } else {\n          throw new Error('Malformed Unicode string with missing or invalid low surrogate.')\n        }\n      }\n\n      // [0xDC00, 0xDFFF] - [Low Surrogates], but if we somehow get here, then the string is\n      // malformed, because here we get only **one** code point.\n      case high < 0xe000: {\n        throw new Error('Malformed Unicode string with invalid high surrogate.')\n      }\n\n      // [0xE000, 0xFFFF] - [Private Use Area, Specials]\n      default: {\n        bytes += 3\n        break\n      }\n    }\n  }\n\n  return bytes\n}\n","import type { Parser, Span } from '@types'\nimport { size } from '@utils/unicode'\n\n/**\n * Parses an *ASCII* string. For parsing Unicode strings, consider using `ustring`.\n *\n * @param match - String to parse\n *\n * @returns Parsed string\n */\nexport function string(match: string): Parser<string> {\n  return {\n    parse(input, pos) {\n      const nextPos = Math.min(pos + match.length, input.length)\n      const slice = input.substring(pos, nextPos)\n      const span: Span = [pos, nextPos]\n\n      switch (slice === match) {\n        case true: {\n          return {\n            isOk: true,\n            span,\n            pos: nextPos,\n            value: match\n          }\n        }\n\n        case false: {\n          return {\n            isOk: false,\n            span,\n            pos: nextPos,\n            expected: match\n          }\n        }\n      }\n    }\n  }\n}\n\n/**\n * Parses a Unicode string. For parsing ASCII-only strings, consider using `string`.\n *\n * @param match - String to parse\n *\n * @returns Parsed string\n */\nexport function ustring(match: string): Parser<string> {\n  return {\n    parse(input, pos) {\n      const nextPos = Math.min(pos + size(match), input.length)\n      const slice = input.substring(pos, nextPos)\n      const span: Span = [pos, nextPos]\n\n      switch (slice === match) {\n        case true: {\n          return {\n            isOk: true,\n            span,\n            pos: nextPos,\n            value: match\n          }\n        }\n\n        case false: {\n          return {\n            isOk: false,\n            span,\n            pos: nextPos,\n            expected: match\n          }\n        }\n      }\n    }\n  }\n}\n","import type { Parser, ToUnion } from '@types'\n\n/**\n * Applies `ps` parsers in order until one of them succeeds.\n *\n * @param ps - Parsers to apply\n *\n * @returns Value of the succeeding parser\n */\nexport function choice<T extends Array<Parser<unknown>>>(...ps: T): Parser<ToUnion<T>>\nexport function choice<T>(...ps: Array<Parser<T>>): Parser<T> {\n  return {\n    parse(input, pos) {\n      // It's \"guaranteed\" by type system that there will be at least two parsers, so I'm not gonna\n      // bother checking for `ps` length and asserting it, because it would hit performance.\n      const [first, ...rest] = ps\n\n      // Run the first parser to infer the type.\n      let nextResult = first.parse(input, pos)\n\n      // Test other alternatives if the first one fails.\n      if (!nextResult.isOk) {\n        for (const parser of rest) {\n          const result = parser.parse(input, pos)\n\n          switch (result.isOk) {\n            case true: {\n              return result\n            }\n\n            case false: {\n              if (!nextResult || nextResult.pos < result.pos) {\n                nextResult = result\n              }\n            }\n          }\n        }\n      }\n\n      return nextResult\n    }\n  }\n}\n","import type { Parser } from '@types'\n\n/**\n * Replaces `parser`'s error message with `expected`.\n *\n * @param parser - Parser of which error message should be replaced\n * @param expected - New error message\n *\n * @returns Unchanged `parser`'s result or failure with new error message\n */\nexport function error<T>(parser: Parser<T>, expected: string): Parser<T> {\n  return {\n    parse(input, pos) {\n      const result = parser.parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return result\n        }\n\n        case false: {\n          return {\n            isOk: false,\n            span: [pos, result.pos],\n            pos: result.pos,\n            expected\n          }\n        }\n      }\n    }\n  }\n}\n","import { string } from './string'\n\nimport { choice, error } from '@combinators'\nimport type { Parser } from '@types'\n\nconst EOL_UNIX = '\\n'\nconst EOL_NON_UNIX = '\\r\\n'\n\n/**\n * Only succeeds at the end of the line, either `\\n` or `\\r\\n`.\n *\n * @returns Matched line break character\n */\nexport function eol(): Parser<string> {\n  return error(choice(string(EOL_UNIX), string(EOL_NON_UNIX)), 'end of line')\n}\n","import type { Parser } from '@types'\n\n/**\n * Parses a string that matches a provided `re` regular expression. Returns the matched string, or\n * fails with an `expected` message.\n *\n * The regular expression must obey two simple rules:\n *\n * - It *does* use `g` flag. Flags like u and i are allowed and can be added if needed.\n * - It *doesn't* use `^` and `$` to match at the beginning or at the end of the text.\n *\n * If `g` flag is missing, it will be automatically injected. It's still better to always provide it\n * to avoid small performance penalty and clearly document the intention.\n *\n * @param rs - Regular expression\n * @param expected - Error message if the regular expression does not match input\n *\n * @returns Matched string\n */\nexport function regexp(rs: RegExp, expected: string): Parser<string> {\n  const re = rs.global ? rs : new RegExp(rs.source, rs.flags + 'g')\n\n  return {\n    parse(input, pos) {\n      // Reset RegExp index, because we abuse the 'g' flag.\n      re.lastIndex = pos\n\n      // `.exec` is actually a little bit faster than `.test`.\n      const result = re.exec(input)\n\n      if (result && result.index === pos) {\n        const [match] = result\n        const index = pos + match.length\n\n        return {\n          isOk: true,\n          span: [pos, index],\n          pos: index,\n          value: match\n        }\n      } else {\n        return {\n          isOk: false,\n          // TODO: Can this be improved? Zero-length span for this parser doesn't look helpful.\n          span: [pos, pos],\n          pos,\n          expected\n        }\n      }\n    }\n  }\n}\n","import { regexp } from './regexp'\n\nimport type { Parser } from '@types'\n\nconst LETTER_RE = /\\p{Letter}/gu\nconst LETTERS_RE = /\\p{Letter}+/gu\n\n/**\n * Parses a single alphabetical character. Unicode friendly.\n *\n * @returns Matched character.\n */\nexport function letter(): Parser<string> {\n  return regexp(LETTER_RE, 'letter')\n}\n\n/**\n * Parses a sequence of alphabetical characters. Unicode friendly.\n *\n * @returns Matched characters as a string.\n */\nexport function letters(): Parser<string> {\n  return regexp(LETTERS_RE, 'letters')\n}\n","import type { Parser } from '@types'\n\n/**\n * Ensures that none of the characters in the given string matches the current character.\n *\n * @param chars - A string of characters that current character should not match\n *\n * @returns Current character\n */\nexport function noneOf(chars: string): Parser<string> {\n  const charset = [...chars]\n\n  return {\n    parse(input, pos) {\n      if (input.length === pos) {\n        return {\n          isOk: false,\n          span: [pos, pos],\n          pos,\n          expected: 'noneOf @ reached the end of input'\n        }\n      }\n\n      const nextPos = pos + 1\n      const char = input.substring(pos, nextPos)\n\n      if (!charset.includes(char)) {\n        return {\n          isOk: true,\n          span: [pos, nextPos],\n          pos: nextPos,\n          value: char\n        }\n      }\n\n      return {\n        isOk: false,\n        span: [pos, pos],\n        pos: nextPos,\n        expected: `none of: ${charset.join(', ')}`\n      }\n    }\n  }\n}\n","import type { Parser } from '@types'\n\n/**\n * Simply resolves to `null`.\n *\n * @returns `null`.\n */\nexport function nothing(): Parser<null> {\n  return {\n    parse(_, pos) {\n      return {\n        isOk: true,\n        span: [pos, pos],\n        pos,\n        value: null\n      }\n    }\n  }\n}\n","import { regexp } from './regexp'\n\nimport type { Parser } from '@types'\n\nconst HEXADECIMAL_RE = /0[xX][0-9a-fA-F]+/g\nconst BINARY_RE = /0[bB][01]+/g\nconst OCTAL_RE = /0[oO][0-8]+/g\nconst WHOLE_RE = /(0|[1-9][0-9]*)/g\nconst INTEGER_RE = /-?(0|[1-9][0-9]*)/g\nconst FLOAT_RE = /-?[0-9]+\\.[0-9]+/g\n\n/**\n * Parses a hexadecimal number prefixed with `0x` or `0X`, e.g. `0xFF`, `0XFF`, `0xff`.\n *\n * @returns Parsed hexadecimal number as a decimal one\n */\nexport function hex(): Parser<number> {\n  return {\n    parse(input, pos) {\n      const result = regexp(HEXADECIMAL_RE, 'hexadecimal number').parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, result.pos],\n            pos: result.pos,\n            value: parseInt(result.value.slice(2), 16)\n          }\n        }\n\n        case false: {\n          return result\n        }\n      }\n    }\n  }\n}\n\n/**\n * Parses a binary number prefixed with `0b` or `0B`, e.g. `0b101`, `0B101`.\n *\n * @returns Parsed binary number as a decimal one\n */\nexport function binary(): Parser<number> {\n  return {\n    parse(input, pos) {\n      const result = regexp(BINARY_RE, 'binary number').parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, result.pos],\n            pos: result.pos,\n            value: parseInt(result.value.slice(2), 2)\n          }\n        }\n\n        case false: {\n          return result\n        }\n      }\n    }\n  }\n}\n\n/**\n * Parses an octal number prefixed with `0o` or `0O`, e.g. `0o420`, `0O420`.\n *\n * @returns Parsed octal number as a decimal one\n */\nexport function octal(): Parser<number> {\n  return {\n    parse(input, pos) {\n      const result = regexp(OCTAL_RE, 'octal number').parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, result.pos],\n            pos: result.pos,\n            value: parseInt(result.value.slice(2), 8)\n          }\n        }\n\n        case false: {\n          return result\n        }\n      }\n    }\n  }\n}\n\n/**\n * Parses a positive whole number without leading zeros, e.g. `0`, `7`, `420`.\n *\n * @returns Parsed whole number\n */\nexport function whole(): Parser<number> {\n  return {\n    parse(input, pos) {\n      const result = regexp(WHOLE_RE, 'whole number').parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, result.pos],\n            pos: result.pos,\n            value: parseInt(result.value, 10)\n          }\n        }\n\n        case false: {\n          return result\n        }\n      }\n    }\n  }\n}\n\n/**\n * Parses an integer number with an optional minus sign, e.g. `0`, `-7`, `420`.\n *\n * @returns Parsed integer number\n */\nexport function integer(): Parser<number> {\n  return {\n    parse(input, pos) {\n      const result = regexp(INTEGER_RE, 'integer number').parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, result.pos],\n            pos: result.pos,\n            value: parseInt(result.value, 10)\n          }\n        }\n\n        case false: {\n          return result\n        }\n      }\n    }\n  }\n}\n\n/**\n * Parses a float number with an optional minus sign, e.g. `0.25`, `-7.90`, `4.20`.\n *\n * Note: It doesn't handle floats with exponent parts.\n *\n * @returns Parsed float number\n */\nexport function float(): Parser<number> {\n  return {\n    parse(input, pos) {\n      const result = regexp(FLOAT_RE, 'float number').parse(input, pos)\n\n      switch (result.isOk) {\n        case true: {\n          return {\n            isOk: true,\n            span: [pos, result.pos],\n            pos: result.pos,\n            value: parseFloat(result.value)\n          }\n        }\n\n        case false: {\n          return result\n        }\n      }\n    }\n  }\n}\n","import type { Parser } from '@types'\n\n/**\n * Ensures that one of the characters in the given string matches the current character.\n *\n * @param chars - A string of characters that current character should match\n *\n * @returns Current character\n */\nexport function oneOf(chars: string): Parser<string> {\n  const charset = [...chars]\n\n  return {\n    parse(input, pos) {\n      if (input.length === pos) {\n        return {\n          isOk: false,\n          span: [pos, pos],\n          pos,\n          expected: 'oneOf @ reached the end of input'\n        }\n      }\n\n      const nextPos = pos + 1\n      const char = input.substring(pos, nextPos)\n\n      if (charset.includes(char)) {\n        return {\n          isOk: true,\n          span: [pos, nextPos],\n          pos: nextPos,\n          value: char\n        }\n      }\n\n      return {\n        isOk: false,\n        span: [pos, pos],\n        pos,\n        expected: `one of: ${charset.join(', ')}`\n      }\n    }\n  }\n}\n","import type { SucceedingParser } from '@types'\n\n/**\n * Simply returns the unparsed input as a string. Never fails.\n *\n * @returns Rest of the input as a string\n */\nexport function rest(): SucceedingParser<string> {\n  return {\n    parse(input, pos) {\n      return {\n        isOk: true,\n        span: [pos, input.length],\n        pos: input.length,\n        value: input.substring(pos)\n      }\n    }\n  }\n}\n","import { regexp } from './regexp'\n\nimport type { Parser } from '@types'\n\nconst WHITESPACE_REQUIRED_RE = /\\s+/g\n\n/**\n * Parses whitespace, either a single character or consecutive ones.\n *\n * @returns Matched whitespace character(s)\n */\nexport function whitespace(): Parser<string> {\n  return regexp(WHITESPACE_REQUIRED_RE, 'whitespace')\n}\n"]}