{"id":17124926,"url":"https://github.com/shellyln/fruitsconfits","last_synced_at":"2025-06-18T10:40:46.588Z","repository":{"id":34988330,"uuid":"194683822","full_name":"shellyln/fruitsconfits","owner":"shellyln","description":"A well typed and sugared parser combinator framework for TypeScript/JavaScript.","archived":false,"fork":false,"pushed_at":"2023-03-15T02:46:17.000Z","size":1496,"stargazers_count":5,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-13T06:13:05.457Z","etag":null,"topics":["javascript","parser","parser-combinator","parser-framework","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shellyln.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-07-01T14:01:40.000Z","updated_at":"2021-12-09T14:12:10.000Z","dependencies_parsed_at":"2025-04-13T06:13:11.117Z","dependency_job_id":"a23190f0-c24a-4674-9ffb-2d1a0236c1e2","html_url":"https://github.com/shellyln/fruitsconfits","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/shellyln/fruitsconfits","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Ffruitsconfits","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Ffruitsconfits/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Ffruitsconfits/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Ffruitsconfits/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shellyln","download_url":"https://codeload.github.com/shellyln/fruitsconfits/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Ffruitsconfits/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260536944,"owners_count":23024514,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","parser","parser-combinator","parser-framework","typescript"],"created_at":"2024-10-14T18:43:42.561Z","updated_at":"2025-06-18T10:40:41.578Z","avatar_url":"https://github.com/shellyln.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FruitsConfits\n### A well typed and _sugared_ parser combinator framework for TypeScript/JavaScript.\n\n\u003cimg src=\"https://raw.githubusercontent.com/shellyln/fruitsconfits/master/docs/images/logo.svg?sanitize=true\" title=\"logo\" style=\"width: 200px\"\u003e\n\n\n[![npm](https://img.shields.io/npm/v/fruitsconfits.svg)](https://www.npmjs.com/package/fruitsconfits)\n[![GitHub release](https://img.shields.io/github/release/shellyln/fruitsconfits.svg)](https://github.com/shellyln/fruitsconfits/releases)\n[![.github/workflows/test.yml](https://github.com/shellyln/fruitsconfits/workflows/.github/workflows/test.yml/badge.svg)](https://github.com/shellyln/fruitsconfits/actions)\n[![GitHub forks](https://img.shields.io/github/forks/shellyln/fruitsconfits.svg?style=social\u0026label=Fork)](https://github.com/shellyln/fruitsconfits/fork)\n[![GitHub stars](https://img.shields.io/github/stars/shellyln/fruitsconfits.svg?style=social\u0026label=Star)](https://github.com/shellyln/fruitsconfits)\n\n\n## Install\n\n```sh\nnpm install fruitsconfits\n```\n\n\n\u003e NOTICE:  \n\u003e Use with `webpack \u003e= 5`\n\u003e\n\u003e If you get the error:\n\u003e\n\u003e ```\n\u003e Module not found: Error: Can't resolve '(importing/path/to/filename)'\n\u003e in '(path/to/node_modules/path/to/dirname)'\n\u003e Did you mean '(filename).js'?`\n\u003e ```\n\u003e\n\u003e Add following setting to your `webpack.config.js`.\n\u003e\n\u003e ```js\n\u003e {\n\u003e     test: /\\.m?js/,\n\u003e     resolve: {\n\u003e         fullySpecified: false,\n\u003e     },\n\u003e },\n\u003e ```\n\u003e\n\u003e On `webpack \u003e= 5`, the extension in the request is mandatory for it to be fully specified\n\u003e if the origin is a '*.mjs' file or a '*.js' file where the package.json contains '\"type\": \"module\"'.\n\n\n\n### Breakikng changes\n\nSee CHANGELOG.md.\n\n\n## Features\n\n* Build a lexer or parser for a string or object list by parser combinator.\n* The parser can receive user data context and acts as a reducer.\n* Sugar sweet API syntaxes.\n\n## High level APIs\n\n### getStringParsers(params)\nGet the string parser generators.\n\n```ts\nexport function getStringParsers\u003cC, R\u003e(\n        params: {\n            rawToToken: (rawToken: string) =\u003e R,\n            concatTokens: (tokens: R[]) =\u003e R[],\n        });\n```\n\n#### params\n* `rawToToken` : function to convert string token to AST element.\n* `concatTokens` : function to merge two AST elements into one AST element.\n\n#### returns\nreturns an object that containing the parsers.\n* `seq(needle: string)`\n  * parser to match the sequence `needle`\n* `cls(...needles: string[])`\n  * parser to match the sequence classes `needles`\n* `notCls(...needles: string[])`\n  * parser to match the negation of sequence classes `needles`\n* `clsFn(needle: (src: string) =\u003e number)`\n  * parser to match the sequence class `needle`\n    * the class is defined by the lambda function\n* classes\n  * `alpha`\n    * parser to match the sequence of us-ascii alphabetic characters\n  * `upper`\n    * parser to match the sequence of us-ascii upper alphabetic characters\n  * `lower`\n    * parser to match the sequence of us-ascii lower alphabetic characters\n  * `num`\n    * parser to match the sequence of us-ascii decimal numeric characters\n  * `nonzero`\n    * parser to match the sequence of us-ascii decimal numeric characters except `0`\n  * `bin`\n    * parser to match the sequence of us-ascii binary numeric characters\n  * `oct`\n    * parser to match the sequence of us-ascii octal numeric characters\n  * `hex`\n    * parser to match the sequence of us-ascii hexadecimal numeric characters\n  * `alnum`\n    * parser to match the sequence of us-ascii alphabetic and numeric characters\n  * `space`\n    * parser to match the sequence of whitespace characters except newline (CR/LF) characters\n      * the whitespace characters definition conform to javascript regexp\n  * `spaceWithinSingleLine`\n    * parser to match the sequence of whitespace characters\n      * the whitespace characters definition conform to javascript regexp\n  * `ctrl`\n    * parser to match the sequence of control characters\n      * the control characters definition conform to javascript regexp\n  * `newline`\n    * parser to match the sequence of newline (CR/LF) characters\n  * `word`\n    * parser to match the negation of the sequence of whitespaces and control characters\n      * the whitespace and control characters definition conform to javascript regexp\n  * `any`\n    * parser to match the sequence class that matches to any token\n* numbers\n  * `bin(...prefixes: StringParserFnWithCtx\u003cC, R\u003e[])`\n    * parse a binary number\n  * `oct(...prefixes: StringParserFnWithCtx\u003cC, R\u003e[])`\n    * parse a octal number\n  * `hex(...prefixes: StringParserFnWithCtx\u003cC, R\u003e[])`\n    * parse a hex number\n  * `int`\n    * parse a javascript style integer number\n  * `bigint`\n    * parse a javascript style bigint number\n  * `float`\n    * parse a javascript style floating point number\n* `isParam(criteria: (o: any) =\u003e boolean, conv?: (o: any) =\u003e any)`\n  * parser to match a ES6 template strings parameter value\n* `cat(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser that combine and concatenate the parsing results of `parsers`\n* `once(parser: StringParserFnWithCtx\u003cC, R\u003e)`\n  * parser to match once to the parsing results of `parser`\n* `repeat(parser: StringParserFnWithCtx\u003cC, R\u003e)`\n  * parser to match zero or more times to the parsing results of `parser`\n* `qty(min?: number, max?: number) =\u003e (parser: StringParserFnWithCtx\u003cC, R\u003e)`\n  * parser to match min to max times to the parsing results of `parser`\n    * if min and max are ommitted, it is same as `repeat` parser\n    * if max is ommitted, it matches min or more times\n* `zeroWidth(helper?: () =\u003e R)`\n  * parser to match any zero width and return result that is provided by `helper`\n* `err(message: string)`\n  * parser to match any zero width and raise the error that has `message`\n* `beginning(helper?: () =\u003e R)`\n  * parser to match zero width beginning of input and return result that is provided by `helper`\n* `end(helper?: () =\u003e R)`\n  * parser to match zero width end of input and return result that is provided by `helper`\n* `first(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser to match the first matched parser in the `parsers`\n* `or(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser to match the most long matched parser in the `parsers`\n* `combine(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser that combine parsers `parsers`\n* `erase(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser that combine parsers `parsers` and return empty result `[]`\n* `trans(fn: (tokens: R[]) =\u003e R[]) =\u003e (...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser that combine parsers `parsers` and transform the result by `fn`\n* `ahead(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser to match zero width by reading ahead and matching with `parsers`\n* `behind(n: number, helper?: () =\u003e R)(...parsers: StringParserFnWithCtx\u003cC, R\u003e[])`\n  * parser to match zero width by reading behind and matching with `parsers` and return result that is provided by `helper`\n* `rules(args: ApplyProductionRulesArg\u003cstring, C, R\u003e) =\u003e (lexer: StringParserFnWithCtx\u003cC, R\u003e)`\n  * parser to match the production rules `args`\n    * args.rules : production rules\n    * args.maxApply : maximum number of production rules applied\n    * args.check : end condition of production rules\n* `makeProgram`\n  * parser to enclose most outer\n    * converts the internal `ParseError` thrown to a return value\n\n\n### getObjectParsers(params)\nGet the object list parser generators.\n\n```ts\nexport function getObjectParsers\u003cT extends ArrayLike\u003cT[number]\u003e, C, R\u003e(\n        params: {\n            rawToToken: (rawToken: T[number]) =\u003e R,\n            concatTokens: (tokens: R[]) =\u003e R[],\n            comparator: (a: T[number], b: T[number]) =\u003e boolean,\n        });\n```\n\n#### params\n* `rawToToken` : function to convert the input object list item to AST element.\n* `concatTokens` : function to merge two AST elements into one AST element.\n* `comparator` : function to compare two input object list items.\n\n#### returns\nreturns an object that containing the parsers.\n* `seq(needle: T)`\n  * parser to match the sequence `needle`\n* `cls(...needles: T[number][])`\n  * parser to match the sequence classes `needles`\n* `notCls(...needles: T[number][])`\n  * parser to match the negation of sequence classes `needles`\n* `clsFn(needle: (src: T[number]) =\u003e boolean)`\n  * parser to match the sequence class `needle`\n    * the class is defined by the lambda function\n* classes\n  * `any`\n    * parser to match the sequence class that matches to any token\n* `cat(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser that combine and concatenate the parsing results of `parsers`\n* `once(parser: ParserFnWithCtx\u003cT, C, R\u003e)`\n  * parser to match once to the parsing results of `parser`\n* `repeat(parser: ParserFnWithCtx\u003cT, C, R\u003e)`\n  * parser to match zero or more times to the parsing results of `parser`\n* `qty(min?: number, max?: number) =\u003e (parser: ParserFnWithCtx\u003cT, C, R\u003e)`\n  * parser to match min to max times to the parsing results of `parser`\n    * if min and max are ommitted, it is same as `repeat` parser\n    * if max is ommitted, it matches min or more times\n* `zeroWidth(helper?: () =\u003e R)`\n  * parser to match any zero width and return result that is provided by `helper`\n* `err(message: string)`\n  * parser to match any zero width and raise the error that has `message`\n* `beginning(helper?: () =\u003e R)`\n  * parser to match zero width beginning of input and return result that is provided by `helper`\n* `end(helper?: () =\u003e R)`\n  * parser to match zero width end of input and return result that is provided by `helper`\n* `first(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser to match the first matched parser in the `parsers`\n* `or(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser to match the most long matched parser in the `parsers`\n* `combine(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser that combine parsers `parsers`\n* `erase(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser that combine parsers `parsers` and return empty result `[]`\n* `trans(fn: (tokens: R[]) =\u003e R[]) =\u003e (...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser that combine parsers `parsers` and transform the result by `fn`\n* `ahead(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser to match zero width by reading ahead and matching with `parsers`\n* `behind(n: number, helper?: () =\u003e R)(...parsers: ParserFnWithCtx\u003cT, C, R\u003e[])`\n  * parser to match zero width by reading behind and matching with `parsers` and return result that is provided by `helper`\n* `rules(args: ApplyProductionRulesArg\u003cT, C, R\u003e) =\u003e (lexer: ParserFnWithCtx\u003cT, C, R\u003e)`\n  * parser to match the production rules `args`\n    * args.rules : production rules\n    * args.maxApply : maximum number of production rules applied\n    * args.check : end condition of production rules\n* `makeProgram`\n  * parser to enclose most outer\n    * converts the internal `ParseError` thrown to a return value\n\n\n### parserInput(src: T, context?: C)\n\nBuild a parser input.\n\nExample:\n```ts\n...\n\nconst program = makeProgram(trans(tokens =\u003e tokens)(\n    erase(repeat(commentOrSpace)),\n    first(listValue, objectValue, constExpr(end())),\n    erase(repeat(commentOrSpace)),\n    end(), ));\n\nexport function parse(s: string) {\n    const z = program(parserInput(s));\n    if (! z.succeeded) {\n        throw new Error(formatErrorMessage(z));\n    }\n    return z.tokens[0].value;\n}\n```\n\n\n### templateStringsParserInput(strings, values, context?: C)\n\nBuild a parser input from ES6 template strings.\n\nExample:\n```ts\nconst program = makeProgram(combine(\n    seq('Hello,'),\n    isParam(o =\u003e String(o) === 'world'),\n    seq('!'),\n    end(), ));\n\nexport function parse(strings: TemplateStringsArray, ...values: any[]) {\n    const z = program(templateStringsParserInput(strings, values));\n    if (! z.succeeded) {\n        throw new Error(formatErrorMessage(z));\n    }\n    return z.tokens;\n}\n```\n\n\n## Examples\n\n* [JSON parser](https://github.com/shellyln/fruitsconfits/blob/master/src/examples/json-parser/index.ts)\n* [CSV parser](https://github.com/shellyln/fruitsconfits/blob/master/src/examples/csv-parser/index.ts)\n* [formula parser](https://github.com/shellyln/fruitsconfits/blob/master/src/examples/formula-parser/index.ts)\n\n\n## Real world examples\n* [Tynder](https://github.com/shellyln/tynder)\n  * TypeScript friendly Data validator for JavaScript.\n  * [Code](https://github.com/shellyln/tynder/blob/master/src/compiler.ts)\n* [kanban-board-app](https://github.com/shellyln/kanban-board-app)\n  * Kanban style task management board app\n  * [Code](https://github.com/shellyln/kanban-board-app/blob/master/src/lib/csv.ts)\n* [Open SOQL](https://github.com/shellyln/open-soql)\n  * Open source implementation of the SOQL.\n  * [Code (1)](https://github.com/shellyln/open-soql/blob/master/src/lib/parser.ts),\n    [(2)](https://github.com/shellyln/open-soql/blob/master/src/lib/csv-parser.ts)\n\n\n## License\n[ISC](https://github.com/shellyln/fruitsconfits/blob/master/LICENSE.md)  \nCopyright (c) 2019 Shellyl_N and Authors.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshellyln%2Ffruitsconfits","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshellyln%2Ffruitsconfits","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshellyln%2Ffruitsconfits/lists"}