{"id":15633635,"url":"https://github.com/zkat/mona","last_synced_at":"2026-03-17T20:31:51.593Z","repository":{"id":10726175,"uuid":"12978520","full_name":"zkat/mona","owner":"zkat","description":"Composable parsing for JavaScript","archived":false,"fork":false,"pushed_at":"2015-11-12T06:53:23.000Z","size":1430,"stargazers_count":156,"open_issues_count":5,"forks_count":11,"subscribers_count":12,"default_branch":"develop","last_synced_at":"2025-08-09T11:21:00.695Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zkat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-09-20T16:37:26.000Z","updated_at":"2025-06-26T01:48:01.000Z","dependencies_parsed_at":"2022-08-31T02:40:31.156Z","dependency_job_id":null,"html_url":"https://github.com/zkat/mona","commit_stats":null,"previous_names":["sykopomp/mona"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/zkat/mona","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fmona","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fmona/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fmona/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fmona/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zkat","download_url":"https://codeload.github.com/zkat/mona/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fmona/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275680775,"owners_count":25508652,"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","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-10-03T10:49:45.804Z","updated_at":"2025-09-21T00:31:09.708Z","avatar_url":"https://github.com/zkat.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# mona\n\n[![Travis](https://img.shields.io/travis/zkat/mona.svg)]()\n[![npm version](https://img.shields.io/npm/v/mona.svg)]()\n[![license](https://img.shields.io/npm/l/mona.svg)]()\n\n`mona` is a Javascript library for easily writing reusable, composable parsers.\nIt makes parsing complex grammars easy and fun!\n\nWith `mona`, you simply write some Javascript functions that parse small pieces\nof text and return any Javascript value, and then you glue them together into\nbig, intricate parsers using `combinators` to... combine them! No custom syntax\nor separate files or separate command line tools to run: you can integrate this\ninto your regular JS app.\n\nIt even makes it really really easy to give excellent error messages, including\nline and column numbers, and messages with what was expected, with little to no\neffort.\n\nNew parsers are hella easy to write -- give it a shot! And if you're familiar\nwith [Parsec](https://hackage.haskell.org/package/parsec), then you've come to\nthe right place. :)\n\n## Table of Contents\n\n* [Install](#install)\n* [Examples](#examples)\n* [API](#api)\n    * [@mona/parse](#monaparse)\n        * [`parse`](#mona-parse)\n    * [@mona/parse-async](#monaparse-async)\n        * [`parseAsync`](#mona-parseAsync)\n    * [@mona/core](#monacore)\n        * [`value`](#mona-value)\n        * [`bind`](#mona-bind)\n        * [`fail`](#mona-fail)\n        * [`label`](#mona-label)\n        * [`token`](#mona-token)\n        * [`eof`](#mona-eof)\n        * [`delay`](#mona-delay)\n        * [`log`](#mona-log)\n        * [`map`](#mona-map)\n        * [`tag`](#mona-tag)\n        * [`lookAhead`](#mona-lookAhead)\n        * [`is`](#mona-is)\n        * [`isNot`](#mona-isNot)\n    * [@mona/combinators](#monacombinators)\n        * [`and`](#mona-and)\n        * [`or`](#mona-or)\n        * [`maybe`](#mona-maybe)\n        * [`not`](#mona-not)\n        * [`unless`](#mona-unless)\n        * [`sequence`](#mona-sequence)\n        * [`join`](#mona-join)\n        * [`followedBy`](#mona-followedBy)\n        * [`split`](#mona-split)\n        * [`splitEnd`](#mona-splitEnd)\n        * [`collect`](#mona-collect)\n        * [`exactly`](#mona-exactly)\n        * [`between`](#mona-between)\n        * [`skip`](#mona-skip)\n        * [`range`](#mona-range)\n    * [@mona/strings](#monastrings)\n        * [`stringOf`](#mona-stringOf)\n        * [`oneOf`](#mona-oneOf)\n        * [`noneOf`](#mona-noneOf)\n        * [`string`](#mona-string)\n        * [`alphaUpper`](#mona-alphaUpper)\n        * [`alphaLower`](#mona-alphaLower)\n        * [`alpha`](#mona-alpha)\n        * [`digit`](#mona-digit)\n        * [`alphanum`](#mona-alphanum)\n        * [`space`](#mona-space)\n        * [`spaces`](#mona-spaces)\n        * [`text`](#mona-text)\n        * [`trim`](#mona-trim)\n        * [`trimLeft`](#mona-trimLeft)\n        * [`trimRight`](#mona-trimRight)\n        * [`eol`](#mona-eol)\n    * [@mona/numbers](#monanumbers)\n        * [`natural`](#mona-natural)\n        * [`integer`](#mona-integer)\n        * [`real`](#mona-real)\n        * [`float`](#mona-real)\n        * [`cardinal`](#mona-cardinal)\n        * [`ordinal`](#mona-ordinal)\n        * [`shortOrdinal`](#mona-shortOrdinal)\n* [Gentle Introduction to Monadic Parser Combinators](#gentle-intro-to-monadic-parser-combinators)\n\n## Install\n\n`$ npm install mona`\n\nYou can directly require `mona` through your module loader of choice, or you can\nuse the prebuilt UMD versions found in the `browser/` directory:\n\n* Node.js/CommonJS - `var mona = require('mona')`\n* ES6 Modules/Babel - `import mona from 'mona'`\n* AMD - `define(['node_modules/mona/browser/mona'], function (mona) { ... })`\n* Global - `\u003cscript src=/js/node_modules/mona/browser/mona.min.js\u003e\u003c/script\u003e`\n\n## Examples\n\n### Parse a series of ints separated by commas\n\n```javascript\nfunction commaInts () {\n  return mona.split(mona.integer(), mona.string(','))\n}\nmona.parse(commaInts(), '1,2,3,49829,49,139')\n// =\u003e [1, 2, 3, 49829, 49, 139]\n```\n\n### A simple, readable CSV parser in ~25 lines\n\n```javascript\nfunction parseCSV (text) {\n  return mona.parse(csv(), text)\n}\nfunction csv () {\n  return mona.splitEnd(line(), mona.eol())\n}\nfunction line () {\n  return mona.split(cell(), mona.string(','))\n}\nfunction cell () {\n  return mona.or(quotedCell(),\n                 mona.text(mona.noneOf(',\\n\\r')))\n}\nfunction quotedCell () {\n  return mona.between(mona.string('\"'),\n                      mona.string('\"'),\n                      mona.text(quotedChar()))\n}\nfunction quotedChar () {\n  return mona.or(mona.noneOf('\"'),\n                 mona.and(mona.string('\"\"'),\n                          mona.value('\"')))\n}\nparseCSV('foo,\"bar\"\\n\"b\"\"az\",quux\\n')\n// =\u003e [['foo', 'bar'], ['b\"az', 'quux']]\n```\n\n# API\n\n`mona` is a package composed of multiple other packages, re-exported through a\nsingle module. You have the option of installing `mona` from npm directly, or\ninstalling any of the subpackages and using those independently.\n\nThis API section is organized such that each parser or function is listed under\nthe subpackage it belongs to, along with the name of the npm package you can\nfind it in.\n\n### `@mona/parse`\n\nThis module or one of its siblings is needed in order to actually execute\ndefined parsers. Currently, it exports only a single function: a synchronous\nparser runner.\n\n#### \u003ca name=\"mona-parse\"\u003e\u003c/a\u003e`\u003e parse(parser, string[, opts]) -\u003e T`\n\nSynchronously executes a parser on a given string, and returns the resulting\nvalue.\n\n* `{Parser\u003cT\u003e} parser` - The parser to execute.\n* `{String} string` - String to parse.\n* `{Opts} [opts]` - Options object.\n* `{Boolean} [opts.throwOnError=true]` - If truthy, throws a ParserError if the  parser fails and returns ParserState instead of its value.\n* `{String} [opts.fileName]` - filename to use for error messages.\n\n```javascript\nparse(token(), 'a') // =\u003e 'a'\nparse(integer(), '123') // =\u003e 123\n```\n\n### `@mona/parse-async`\n\nThis module exports only a single function: an asynchronous parser runner. You\nneed this module or something similar in order to actually execute your parsers.\n\n#### \u003ca name=\"mona-parseAsync\"\u003e\u003c/a\u003e`\u003e parseAsync(parser, callback[, opts]) -\u003e Handle`\n\nExecutes a parser asynchronously, returning an object that can be used to\nmanage the parser state.\n\nYou can feed new data into the parsing process by calling the returned handle's\n`#data()` method. Unless the parser given tries to match `eof()`, parsing will\ncontinue until the handle's `#done()` method is called.\n\n* `{Function} parser` - The parser to execute.\n* `{AsyncParserCallback} callback` - node-style 2-arg callback executed once\n  per successful application of `parser`.\n* `{Object} [opts]` - Options object.\n* `{String} [opts.fileName]` - filename to use for error messages.\n\n```javascript\nvar handle = parseAsync(token(), function(tok) {\n console.log('Got a token: ', tok)\n})\nhandle.data('foo')\n\n// logs:\n// \u003e Got a token: f\n// \u003e Got a token: o\n// \u003e Got a token: o\n```\n\n### `@mona/core`\n\nThe core parser package contains essential and dev-utility parsers that are\nintended to be the core of the rest of the parser libraries. Some of these are\nvery low level, such as `bind()`. Others are not necessarily meant to be used in\nproduction, but can help with debugging, such as `log()`.\n\n#### \u003ca name=\"mona-value\"\u003e\u003c/a\u003e`\u003e value(val) -\u003e Parser\u003cT\u003e`\n\nAlways succeeds with `val` as its value, without consuming any input.\n\n * `{T} val` - value to use as this parser's value.\n\n ```javascript\n parse(value('foo'), '') // =\u003e 'foo'\n ```\n\n#### \u003ca name=\"mona-bind\"\u003e\u003c/a\u003e`\u003e bind(parser, fun) -\u003e Parser\u003cU\u003e`\n\nCalls `fun` on the value from `parser`. Fails without executing `fun` if\n`parser` fails.\n\n* `{Parser\u003cT\u003e} parser` - The parser to execute.\n\n* `{Function(Parser\u003cT\u003e) -\u003e Parser\u003cU\u003e} fun` - Function called with the resulting\n  value of `parser`.\n\n```javascript\nparse(bind(token(), function (x) {\n  return value(x + '!')\n}), 'a') // =\u003e 'a!'\n```\n\n#### \u003ca name=\"mona-fail\"\u003e\u003c/a\u003e`\u003e fail([msg[, type]]) -\u003e Parser\u003cFail\u003e`\n\nAlways fails without consuming input. Automatically includes the line and column\npositions in the final `ParserError`.\n\n* `{String} [msg='parser error']` - Message to report with the failure.\n* `{String} [type='failure']` - A type to apply to the ParserError.\n\n#### \u003ca name=\"mona-label\"\u003e\u003c/a\u003e`\u003e label(parser, msg) -\u003e Parser\u003cT\u003e`\n\nLabel a `parser` failure by replacing its error messages with `msg`.\n\n* `{Parser\u003cT\u003e} parser` - Parser whose errors to replace.\n* `{String} msg` - Error message to replace errors with.\n\n```javascript\nparse(token(), '') // =\u003e unexpected eof\nparse(label(token(), 'thing'), '') // =\u003e expected thing\n```\n\n#### \u003ca name=\"mona-token\"\u003e\u003c/a\u003e`\u003e token([count]) -\u003e Parser\u003cString\u003e`\n\nConsumes a single item from the input, or fails with an unexpected eof error if\nthere is no input left.\n\n* `{Integer} [count=1]` - number of tokens to consume. Must be \u003e 0.\n\n```javascript\nparse(token(), 'a') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-eof\"\u003e\u003c/a\u003e`\u003e eof() -\u003e Parser\u003ctrue\u003e`\n\nSucceeds with a value of `true` if there is no more input to consume.\n\n```javascript\nparse(eof(), '') // =\u003e true\n```\n\n#### \u003ca name=\"mona-delay\"\u003e\u003c/a\u003e`\u003e delay(constructor, ...args) -\u003e Parser\u003cT\u003e`\n\nDelays calling of a parser constructor function until parse-time. Useful for\nrecursive parsers that would otherwise blow the stack at construction time.\n\n* `{Function(...T) -\u003e Parser\u003cT\u003e} constructor` - A function that returns a\n  Parser.\n* `{...T} args` - Arguments to apply to the constructor.\n\n```javascript\n// The following would usually result in an infinite loop:\nfunction foo() {\n return or(x(), foo())\n}\n// But you can use delay() to remedy this...\nfunction foo() {\n return or(x(), delay(foo))\n}\n```\n\n#### \u003ca name=\"mona-log\"\u003e\u003c/a\u003e`\u003elog(parser, label[, level]) -\u003e Parser\u003cT\u003e`\n\nLogs the `ParserState` resulting from `parser` with a `label`.\n\n* `{Parser\u003cT\u003e} parser` - Parser to wrap.\n* `{String} tag` - Tag to use when logging messages.\n* `{String} [level='log']` - 'log', 'info', 'debug', 'warn', 'error'.\n\n#### \u003ca name=\"mona-map\"\u003e\u003c/a\u003e`\u003emap(fun, parser) -\u003e Parser\u003cT\u003e`\n\nTransforms the resulting value of a successful application of its given parser.\nThis function is a lot like `bind`, except it always succeeds if its parser\nsucceeds, and is expected to return a transformed value, instead of another\nparser.\n\n* `{Function(U) -\u003e T} transformer` - Function called on `parser`'s value. Its return value will be used as the `map` parser's value.\n* `{Parser\u003cU\u003e} parser` - Parser that will yield the input value.\n\n```javascript\nparse(map(parseFloat, text()), '1234.5') // =\u003e 1234.5\n```\n\n#### \u003ca name=\"mona-tag\"\u003e\u003c/a\u003e`\u003etag(parser, tag) -\u003e Parser\u003cObject\u003cT\u003e\u003e`\n\nResults in an object with a single key whose value is the result of the given\nparser. This can be useful for when you want to build ASTs or otherwise do some\ntagged tree structure.\n\n* `{Parser\u003cT\u003e} parser` - Parser whose value will be tagged.\n* `{String} tag` - String to use as the object's key.\n\n```javascript\nparse(tag(token(), 'myToken'), 'a') // =\u003e {myToken: 'a'}\n```\n\n#### \u003ca name=\"mona-lookAhead\"\u003e\u003c/a\u003e`\u003elookAhead(parser) -\u003e Parser\u003cT\u003e`\n\nRuns a given parser without consuming input, while still returning a success or\nfailure.\n\n* `{Parser\u003cT\u003e} parser` - Parser to execute.\n\n```javascript\nparse(and(lookAhead(token()), token()), 'a') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-is\"\u003e\u003c/a\u003e`\u003eis(predicate[, parser]) -\u003e Parser\u003cT\u003e`\n\nSucceeds if `predicate` returns a truthy value when called on `parser`'s result.\n\n* `{Function(T) -\u003e Boolean} predicate` - Tests a parser's result.\n* `{Parser\u003cT\u003e} [parser=token()]` - Parser to run.\n\n```javascript\nparse(is(function (x) { return x === 'a' }), 'a') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-isNot\"\u003e\u003c/a\u003e`\u003e isNot(predicate[, parser]) -\u003e Parser\u003cT\u003e`\n\nSucceeds if `predicate` returns a falsy value when called on `parser`'s result.\n\n* `{Function(T) -\u003e Boolean} predicate` - Tests a parser's result.\n* `{Parser\u003cT\u003e} [parser=token()]` - Parser to run.\n\n```javascript\nparse(isNot(function (x) { return x === 'a' }), 'b') // =\u003e 'b'\n```\n\n### `@mona/combinators`\n\nParser combinators are at the very core of what makes something like mona shine:\nThey are, themselves, parsers, but they are intended to accept _other parsers_\nas arguments, that they will then use to do whatever job they're doing.\n\nCombinators do just that: They combine parsers. They act as the glue that lets\nyou take all those individual parsers that you wrote, and combine them into\nincreasingly more intricate parsers.\n\nThis package contains things like `collect()`, `split()`, and the `or()`/`and()`\npair.\n\n#### \u003ca name=\"mona-and\"\u003e\u003c/a\u003e`\u003e and(...parsers, lastParser) -\u003e Parser\u003cT\u003e`\n\nSucceeds if all the parsers given to it succeed, using the value of the last\nexecuted parser as its return value.\n\n* `{...Parser\u003c*\u003e} parsers` - Parsers to execute.\n* `{Parser\u003cT\u003e} lastParser` - Parser whose result is returned.\n\n```javascript\nparse(and(token(), token()), 'ab') // =\u003e 'b'\n```\n\n#### \u003ca name=\"mona-or\"\u003e\u003c/a\u003e`\u003e or(...parsers[, label]) -\u003e Parser\u003cT\u003e`\n\nSucceeds if one of the parsers given to it succeeds, using the value of the\nfirst successful parser as its result.\n\n* `{...Parser\u003cT,*\u003e} parsers` - Parsers to execute.\n* `{String} [label]` - Label to replace the full message with.\n\n```javascript\nparse(or(string('foo'), string('bar')), 'bar') // =\u003e 'bar'\n```\n\n#### \u003ca name=\"mona-maybe\"\u003e\u003c/a\u003e`\u003e maybe(parser) -\u003e Parser\u003cT\u003e | Parser\u003cundefined\u003e`\n\nReturns the result of `parser` if it succeeds, otherwise succeeds with a value\nof `undefined` without consuming any input.\n\n* `{Parser\u003cT\u003e} parser` - Parser to try.\n\n```javascript\nparse(maybe(token()), 'a') // =\u003e 'a'\nparse(maybe(token()), '') // =\u003e undefined\n```\n\n#### \u003ca name=\"mona-not\"\u003e\u003c/a\u003e`\u003e not(parser) -\u003e Parser\u003cundefined\u003e`\n\nSucceeds if `parser` fails. Does not consume.\n\n* `{Parser\u003c*\u003e} parser` - parser to test.\n\n```javascript\nparse(and(not(string('a')), token()), 'b') // =\u003e 'b'\n```\n\n#### \u003ca name=\"mona-unless\"\u003e\u003c/a\u003e`\u003e unless(notParser, ...moreParsers, lastParser) -\u003e Parser\u003cT\u003e`\n\nWorks like `and`, but fails if the first parser given to it succeeds. Like\n`and`, it returns the value of the last successful parser.\n\n* `{Parser\u003c*\u003e} notParser` - If this parser succeeds, `unless` will fail.\n* `{...Parser} moreParsers` - Rest of the parses to test.\n* `{Parser\u003cT\u003e} lastParser` - Parser whose value to return.\n\n```javascript\nparse(unless(string('a'), token()), 'b') // =\u003e 'b'\n```\n\n#### \u003ca name=\"mona-sequence\"\u003e\u003c/a\u003e`\u003e sequence(fun) -\u003e Parser\u003cT\u003e`\n\nPut simply, this parser provides a way to write complex parsers while letting\nyour code look like regular procedural code. You just wrap your parsers with\n`s()`, and the rest of your code can be sequential. If the description seems\nconfusing, see the example.\n\nThis parser executes `fun` while handling the `parserState` internally, allowing\nthe body of `fun` to be written sequentially. The purpose of this parser is to\nsimulate `do` notation and prevent the need for heavily-nested `bind` calls.\n\nThe `fun` callback will receive a function `s` which should be called with\neach parser that will be executed, which will update the internal\nparserState. The return value of the callback must be a parser.\n\nIf any of the parsers fail, sequence will exit immediately, and the entire\nsequence will fail with that parser's reason.\n\n* `{Function -\u003e Parser\u003cT\u003e} fun` - A sequence callback function to execute.\n\n```javascript\nmona.sequence(function (s) {\n  var x = s(mona.token())\n  var y = s(mona.string('b'))\n  return mona.value(x + y)\n})\n```\n\n#### \u003ca name=\"mona-join\"\u003e\u003c/a\u003e`\u003e join(...parsers) -\u003e Parser\u003cArray\u003cT\u003e\u003e`\n\nSucceeds if all the parsers given to it succeed, and results in an array of all\nthe resulting values, in order.\n\n* `{...Parser\u003cT\u003e} parsers` - One or more parsers to execute.\n\n```javascript\nparse(join(alpha(), integer()), 'a1') // =\u003e ['a', 1]\n```\n\n#### \u003ca name=\"mona-followedBy\"\u003e\u003c/a\u003e`\u003e followedBy(parser, ...moreParsers) -\u003e Parser\u003cT\u003e`\n\nReturns the result of its first parser if it succeeds, but fails if any of the\nfollowing parsers fail.\n\n* `{Parser\u003cT\u003e} parser` - The value of this parser is returned if it succeeds.\n\n* `{...Parser\u003c*\u003e} moreParsers` - These parsers must succeed in order for\n  `followedBy` to succeed.\n\n```javascript\nparse(followedBy(string('a'), string('b'), string('c')), 'abc') // =\u003e 'a'\nparse(followedBy(string('a'), string('a')), 'abc') // =\u003e expected {a}\n```\n\n#### \u003ca name=\"mona-split\"\u003e\u003c/a\u003e`\u003e split(parser, separator[, opts]) -\u003e Parser\u003cArray\u003cT\u003e\u003e`\n\nResults in an array of successful results of `parser`, divided by the\n`separator` parser.\n\n* `{Parser\u003cT\u003e} parser` - Parser for matching and collecting results.\n* `{Parser\u003cU\u003e} separator` - Parser for the separator\n* `{Opts} [opts]` - Optional options for controlling min/max.\n* `{Integer} [opts.min=0]` - Minimum length of the resulting array.\n* `{Integer} [opts.max=Infinity]` - Maximum length of the resulting array.\n\n```javascript\nparse(split(token(), space()), 'a b c d') // =\u003e ['a','b','c','d']\n```\n\n#### \u003ca name=\"mona-splitEnd\"\u003e\u003c/a\u003e`\u003e splitEnd(parser, separator[, opts]) -\u003e Parser\u003cArray\u003cT\u003e\u003e`\n\nResults in an array of results that have been successfully parsed by `parser`,\nseparated *and ended* by `separator`.\n\n* `{Parser\u003cT\u003e} parser` - Parser for matching and collecting results.\n* `{Parser\u003cU\u003e} separator` - Parser for the separator\n* `{Integer} [opts.enforceEnd=true]` - If true, `separator` must be at the end\n  of the parse.\n* `{Integer} [opts.min=0]` - Minimum length of the resulting array.\n* `{Integer} [opts.max=Infinity]` - Maximum length of the resulting array.\n\n```javascript\nparse(splitEnd(token(), space()), 'a b c ') // =\u003e ['a', 'b', 'c']\n```\n\n#### \u003ca name=\"mona-collect\"\u003e\u003c/a\u003e`\u003e collect(parser[, opts]) -\u003e Parser\u003cArray\u003cT\u003e\u003e`\n\nResults in an array of `min` to `max` number of matches of `parser`\n\n* `{Parser\u003cT\u003e} parser` - Parser to match.\n* `{Integer} [opts.min=0]` - Minimum number of matches.\n* `{Integer} [opts.max=Infinity]` - Maximum number of matches.\n\n```javascript\nparse(collect(token()), 'abcd') // =\u003e ['a', 'b', 'c', 'd']\n```\n\n#### \u003ca name=\"mona-exactly\"\u003e\u003c/a\u003e`\u003e exactly(parser, n) -\u003e Parser\u003cArray\u003cT\u003e\u003e`\n\nResults in an array of exactly `n` results for `parser`.\n\n* `{Parser\u003cT\u003e} parser` - The parser to collect results for.\n* `{Integer} n` - exact number of results to collect.\n\n```javascript\nparse(exactly(token(), 4), 'abcd') // =\u003e ['a', 'b', 'c', 'd']\n```\n\n#### \u003ca name=\"mona-between\"\u003e\u003c/a\u003e`\u003e between(open, close, parser) -\u003e Parser\u003cV\u003e`\n\nResults in a value between an opening and closing parser.\n\n* `{Parser\u003cT\u003e} open` - Opening parser.\n* `{Parser\u003cU\u003e} close` - Closing parser.\n* `{Parser\u003cV\u003e} parser` - Parser to return the value of.\n\n```javascript\nparse(between(string('('), string(')'), token()), '(a)') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-skip\"\u003e\u003c/a\u003e`\u003e skip(parser) -\u003e Parser\u003cundefined\u003e`\n\nSkips input until `parser` stops matching.\n\n* `{Parser\u003cT\u003e} parser` - Determines whether to continue skipping.\n\n```javascript\nparse(and(skip(string('a')), token()), 'aaaab') // =\u003e 'b'\n```\n\n#### \u003ca name=\"mona-range\"\u003e\u003c/a\u003e`\u003e range(start, end[, parser[, predicate]]) -\u003e Parser\u003cT\u003e`\n\nAccepts a parser if its result is within range of `start` and `end`.\n\n* `{*} start` - lower bound of the range to accept.\n* `{*} end` - higher bound of the range to accept.\n* `{Parser\u003cT\u003e} [parser=token()]` - parser whose results to test\n* `{Function(T) -\u003e Boolean} [predicate=function(x,y){return x\u003c=y }]` - Tests\n  range\n\n```javascript\nparse(range('a', 'z'), 'd') // =\u003e 'd'\n```\n\n### `@mona/strings`\n\nThis package is intended as a collection of string-related parsers. That is,\nparsers that specifically return string-related data or somehow match and\nmanipulate strings themselves.\n\nHere, you'll find the likes of `string()` (the exact-string matching parser),\n`spaces()`, and `trim()`.\n\n#### \u003ca name=\"mona-stringOf\"\u003e\u003c/a\u003e`\u003e stringOf(parser) -\u003e Parser\u003cString\u003e`\n\nResults in a string containing the concatenated results of applying `parser`.\n`parser` must be a combinator that returns an array of string parse results.\n\n* `{Parser\u003cArray\u003cString\u003e\u003e} parser` - Parser whose result to concatenate.\n\n```javascript\nparse(stringOf(collect(token())), 'aaa') // =\u003e 'aaa'\n```\n\n#### \u003ca name=\"mona-oneOf\"\u003e\u003c/a\u003e`\u003e oneOf(matches[, caseSensitive]) -\u003e Parser\u003cString\u003e`\n\nSucceeds if the next token or string matches one of the given inputs.\n\n* `{String|Array\u003cString\u003e} matches` - Characters or strings to match. If this\n  argument is a string, it will be treated as if matches.split('') were passed\n  in.\n* `{Boolean} [caseSensitive=true]` - Whether to match char case exactly.\n\n```javascript\nparse(oneOf('abcd'), 'c') // =\u003e 'c'\nparse(oneOf(['foo', 'bar', 'baz']), 'bar') // =\u003e 'bar'\n```\n\n#### \u003ca name=\"mona-noneOf\"\u003e\u003c/a\u003e`\u003e noneOf(matches[, caseSensitive[, other]]) -\u003e Parser\u003cT\u003e`\n\nFails if the next token or string matches one of the given inputs. If the third\n`parser` argument is given, that parser will be used to collect the actual value\nof `noneOf`.\n\n* `{String|Array} matches` - Characters or strings to match. If this argument is\n  a string, it will be treated as if matches.split('') were passed in.\n* `{Boolean} [caseSensitive=true]` - Whether to match char case exactly.\n* `{Parser\u003cT\u003e} [other=token()]` - What to actually parse if none of the given\n  matches succeed.\n\n```javascript\nparse(noneOf('abc'), 'd') // =\u003e 'd'\nparse(noneOf(['foo', 'bar', 'baz']), 'frob') // =\u003e 'f'\nparse(noneOf(['foo', 'bar', 'baz'], true, text()), 'frob') // =\u003e 'frob'\n```\n\n#### \u003ca name=\"mona-string\"\u003e\u003c/a\u003e`\u003e string(str[, caseSensitive]) -\u003e Parser\u003cString\u003e`\n\nSucceeds if `str` matches the next `str.length` inputs,\nconsuming the string and returning it as a value.\n\n* `{String} str` - String to match against.\n* `{Boolean} [caseSensitive=true]` - Whether to match char case exactly.\n\n```javascript\nparse(string('foo'), 'foo') // =\u003e 'foo'\n```\n\n#### \u003ca name=\"mona-alphaUpper\"\u003e\u003c/a\u003e`\u003e alphaUpper() -\u003e Parser\u003cString\u003e`\n\nMatches a single non-unicode uppercase alphabetical character.\n\n```javascript\nparse(alphaUpper(), 'D') // =\u003e 'D'\n```\n\n#### \u003ca name=\"mona-alphaLower\"\u003e\u003c/a\u003e`\u003e alphaLower() -\u003e Parser\u003cString\u003e`\n\nMatches a single non-unicode lowercase alphabetical character.\n\n```javascript\nparse(alphaLower(), 'd') // =\u003e 'd'\n```\n\n#### \u003ca name=\"mona-alpha\"\u003e\u003c/a\u003e`\u003e alpha() -\u003e Parser\u003cString\u003e`\n\nMatches a single non-unicode alphabetical character.\n\n```javascript\nparse(alpha(), 'd') // =\u003e 'd'\nparse(alpha(), 'D') // =\u003e 'D'\n```\n\n#### \u003ca name=\"mona-digit\"\u003e\u003c/a\u003e`\u003e digit(base) -\u003e Parser\u003cString\u003e`\n\nParses a single digit character token from the input.\n\n* `{Integer} [base=10]` - Optional base for the digit.\n\n```javascript\nparse(digit(), '5') // =\u003e '5'\n```\n\n#### \u003ca name=\"mona-alphanum\"\u003e\u003c/a\u003e`\u003e alphanum(base) -\u003e Parser\u003cString\u003e`\n\nMatches an alphanumeric character.\n\n* `{Integer} [base=10]` - Optional base for numeric parsing.\n\n```javascript\nparse(alphanum(), '1') // =\u003e '1'\nparse(alphanum(), 'a') // =\u003e 'a'\nparse(alphanum(), 'A') // =\u003e 'A'\n```\n\n#### \u003ca name=\"mona-space\"\u003e\u003c/a\u003e`\u003e space() -\u003e Parser\u003cString\u003e`\n\nMatches one whitespace character.\n\n```javascript\nparse(space(), '\\r') // =\u003e '\\r'\n```\n\n#### \u003ca name=\"mona-spaces\"\u003e\u003c/a\u003e`\u003e spaces() -\u003e Parser\u003cString\u003e`\n\nMatches one or more whitespace characters. Returns a single space character as\nits result, regardless of which whitespace characters and how many were matched.\n\n```javascript\nparse(spaces(), '   \\r\\n\\t \\r \\n') // =\u003e ' '\n```\n\n#### \u003ca name=\"mona-text\"\u003e\u003c/a\u003e`\u003e text([parser[, opts]]) -\u003e Parser\u003cString\u003e`\n\nCollects between `min` and `max` number of matches for `parser`. The result is\nreturned as a single string. This parser is essentially `collect()` for strings.\n\n* `{Parser\u003cString\u003e} [parser=token()]` - Parser to use to collect the results.\n* `{Object} [opts]` - Options to control match count.\n* `{Integer} [opts.min=0]` - Minimum number of matches.\n* `{Integer} [opts.max=Infinity]` - Maximum number of matches.\n\n```javascript\n* parse(text(), 'abcde') // =\u003e 'abcde'\n* parse(text(noneOf('a')), 'bcde') // =\u003e 'bcde'\n```\n\n#### \u003ca name=\"mona-trim\"\u003e\u003c/a\u003e`\u003e trim(parser) -\u003e Parser\u003cT\u003e`\n\nTrims any whitespace surrounding `parser`, and returns `parser`'s result.\n\n* `{Parser\u003cT\u003e} parser` - Parser to match after cleaning up whitespace.\n\n```javascript\nparse(trim(token()), '    \\r\\n  a   \\t') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-trimLeft\"\u003e\u003c/a\u003e`\u003e trimLeft(parser) -\u003e Parser\u003cT\u003e`\n\nTrims any _leading_ whitespace before `parser`, and returns `parser`'s result.\n\n* `{Parser\u003cT\u003e} parser` - Parser to match after cleaning up whitespace.\n\n```javascript\nparse(trimLeft(token()), '    \\r\\n  a') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-trimRight\"\u003e\u003c/a\u003e`\u003e trimRight(parser) -\u003e Parser\u003cT\u003e`\n\nTrims any _trailing_ whitespace before `parser`, and returns `parser`'s result.\n\n* `{Parser} parser` - Parser to match after cleaning up whitespace.\n\n```javascript\nparse(trimRight(token()), 'a   \\r\\n') // =\u003e 'a'\n```\n\n#### \u003ca name=\"mona-eol\"\u003e\u003c/a\u003e`\u003e eol() -\u003e Parser\u003cString\u003e`\n\nParses the end of a line.\n\n```javascript\nparse(eol(), '\\n') // =\u003e '\\n'\n```\n\n### `@mona/numbers`\n\nIf you ever need a parser that will take strings and turn them into the numbers\nyou want the to be, this is the place to look. Parsers in this package include\n`integer()`, `float()`, and `ordinal()` (which parses English ordinals (`first`,\n`second`, `third`) into numbers).\n\n#### \u003ca name=\"mona-natural\"\u003e\u003c/a\u003e`\u003e natural(base) -\u003e Parser\u003cInteger\u003e`\n\nMatches a natural number. That is, a number without a positive/negative sign or\ndecimal places, and returns a positive integer.\n\n* `{Integer} [base=10]` - Base to use when parsing the number.\n\n```javascript\n* parse(natural(), '1234') // =\u003e 1234\n```\n\n#### \u003ca name=\"mona-integer\"\u003e\u003c/a\u003e`\u003e integer(base) -\u003e Parser\u003cInteger\u003e`\n\nMatches an integer, with an optional + or - sign.\n\n* `{Integer} [base=10]` - Base to use when parsing the integer.\n\n```javascript\nparse(integer(), '-1234') // =\u003e -1234\n```\n\n#### \u003ca name=\"mona-real\"\u003e\u003c/a\u003e`\u003e real() -\u003e Parser\u003cFloat\u003e`\n\nParses a floating point number.\n\n```javascript\nparse(real(), '-1234e-10') // =\u003e -1.234e-7\n```\n\n#### \u003ca name=\"mona-cardinal\"\u003e\u003c/a\u003e`\u003e cardinal() -\u003e Parser\u003cInteger\u003e`\n\nParses english cardinal numbers into their numerical counterparts\n\n```javascript\nparse(cardinal(), 'two thousand') // =\u003e 2000\n```\n\n#### \u003ca name=\"mona-ordinal\"\u003e\u003c/a\u003e`\u003e ordinal() -\u003e Parser\u003cInteger\u003e`\n\nParses English ordinal numbers into their numerical counterparts.\n\n```javascript\nparse(ordinal(), 'one-hundred thousand and fifth') // 100005\n```\n\n#### \u003ca name=\"mona-shortOrdinal\"\u003e\u003c/a\u003e`\u003e shortOrdinal() -\u003e Parser\u003cInteger\u003e`\n\nParses shorthand english ordinal numbers into their numerical counterparts.\nOptionally allows you to remove correct suffix checks and allow any apparent\nordinal to get through.\n\n* `{Boolean} [strict=true]` - Whether to accept only appropriate suffixes for\n  each number. (if false, `2th` parses to `2`)\n\n```javascript\nparse(shortOrdinal(), '5th') // 5\n```\n\n# Gentle Intro to Monadic Parser Combinators\n\n`mona` works by composing functions called `parsers`. These functions are\ncreated by so-called `parser constructors`. Most of the `mona` API exposes these\nconstructors.\n\n#### Primitive parsers\n\nThere are three primitive parsers in mona: `value()`, `fail()`, and\n`token()`.\n\n* `value()` - results in its single argument, without consuming input.\n* `fail()` - fails unconditionally, without consuming input.\n* `token()` - consumes a single token, or character, from the input. Fails if there's nothing left to consume.\n\nSimply creating a parser is not enough to execute a parser, though.  We need to\nuse the `parse` function, to actually execute the parser on an input string:\n\n```javascript\nmona.parse(mona.value('foo'), '') // =\u003e 'foo'\nmona.parse(mona.fail(), '') // =\u003e throws an exception\nmona.parse(mona.token(), 'a') // =\u003e 'a'\nmona.parse(mona.token(), '') // =\u003e error, unexpected eof\n```\n\n#### The primitive combinator\n\nThese three parsers do not seem to get us much of anywhere, so we introduce our\nfirst *combinator*: `bind()`. `bind()` accepts a parser as its first argument,\nand a function as its second argument. The function will be called with the\nparser's result value *only if the parser succeeds*. The function *must then\nreturn another parser*, which will be used to determine `bind()`'s value:\n\n```javascript\nmona.parse(mona.bind(mona.token(), function (character) {\n  if (character === 'a') {\n    return mona.value('found an \"a\"!')\n  } else {\n    return mona.fail()\n  }\n}), 'a') // =\u003e 'found an \"a\"!'\n```\n\n#### Basic utility combinators\n\n`bind()`, of course, is just the beginning. Now that we know we can combine\nparsers, we can play with some of `mona`'s fancier parsers and combinators. For\nexample, the `or` combinator resolves to the first parser that succeeds, in the\norder they were provided, or fails if none of those parsers succeeded:\n\n```javascript\nmona.parse(mona.or(mona.fail('nope'),\n                   mona.fail('nope again'),\n                   mona.value('this one!')),\n           '')\n// =\u003e 'this one!'\n```\n\n```javascript\nmona.parse(mona.or(mona.fail('nope'),\n                   mona.value('this one!'),\n                   mona.value('but not this one')),\n           '')\n// =\u003e 'this one!'\n```\n\n`and()` is another basic combinator. It succeeds only if all its parsers\nsucceed, and resolves to the value of the last parser. Otherwise, it fails with\nthe first failed parser's error.\n\n```javascript\nmona.parse(mona.and(mona.value('foo'),\n                    mona.value('bar')),\n           '')\n// =\u003e 'bar'\n```\n\nFinally, there's the `not()` combinator. It's important to note that, regardless\nof its argument's result, `not()` will not consume input... it must be combined\nwith something that does.\n\n```javascript\nmona.parse(mona.and(mona.not(mona.token()), mona.value('end of input')), '')\n// =\u003e 'end of input'\n```\n\n#### Matching strings\n\nThe `string()` parser might come in handy: It results in a string matching a given\nstring:\n\n```javascript\nmona.parse(mona.string('foo'), 'foo')\n// =\u003e 'foo'\n```\n\nAnd can of course be combined with some combinator to provide an alternative\nvalue:\n\n```javascript\nmonap.parse(mona.and(mona.string('foo'), mona.value('got a foo!')), 'foo')\n// =\u003e 'got a foo!'\n```\n\nThe `is()` parser can also be used to succeed or fail depending on whether the\nnext token matches a particular predicate:\n\n```javascript\nmona.parse(mona.is(function (x) { return x === 'a' }), 'a')\n// =\u003e 'a'\n```\n\n#### Sequential syntax\n\nWriting parsers by composing functions is perfectly fine and natural, and you\nmight get quite a feel for it, but sometimes it's nice to have something that\nfeels a bit more procedural. For situations like that, you can use `sequence`:\n\n```javascript\nfunction parenthesized () {\n  return mona.sequence(function (s) {\n    // The s() function passed into `sequence()`'s callback\n    // must be used to execute any parsers within the sequence.\n    var open = s(mona.string('('))\n    // open === '(' if the `string()` parser succeeds.\n    var data = s(mona.token())\n    var close = s(mona.string(')'))\n    // The `sequence()` callback must return another parser, just like `bind()`.\n    // Also like `bind()`, it can `return fail()` to fail the parser.\n    return mona.value(data)\n  })\n}\nmona.parse(parenthesized(), '(a)')\n// =\u003e 'a'\n```\n\nWe can generalize this parser into a combinator by accepting an arbitrary parser\nas an input:\n\n```javascript\nfunction parenthesized (parser) {\n  return mona.sequence(function (s) {\n    var open = s(mona.string('('))\n    var data = s(parser) // Use the parser here!\n    var close = s(mona.string(')'))\n    return mona.value(data)\n  })\n}\nmona.parse(parenthesized(mona.string('foo!')), '(foo!)')\n// =\u003e 'foo!'\n```\n\nNote that if the given parser consumes closing parentheses, this will fail:\n\n```javascript\nmona.parse(parenthesized(mona.string('something)'), '(something)')\n// =\u003e error, unexpected EOF\n```\n\n#### The Rest of It\n\nOnce you've got the basics down, you can explore [`mona`'s API](#api) for more\ninteresting parsers. A variety of useful parsers are available for use, such as\n`collect()`, which collects the results of a parser into an array until the\nparser fails, or `float()`, which parses a floating-point number and returns the\nactual number. For more examples on how to use `mona` to create parsers for\nactual formats, take a look in the `examples/` directory included with the\nproject, which includes examples for `json` and `csv`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkat%2Fmona","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzkat%2Fmona","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkat%2Fmona/lists"}