{"id":17086404,"url":"https://github.com/dasch/parser","last_synced_at":"2025-04-12T21:40:35.232Z","repository":{"id":52693649,"uuid":"156864396","full_name":"dasch/parser","owner":"dasch","description":"Parser combinators for Elm.","archived":false,"fork":false,"pushed_at":"2021-04-20T20:37:56.000Z","size":124,"stargazers_count":4,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T15:48:13.720Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elm","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dasch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-09T13:16:15.000Z","updated_at":"2019-01-16T15:46:15.000Z","dependencies_parsed_at":"2022-08-22T06:40:13.704Z","dependency_job_id":null,"html_url":"https://github.com/dasch/parser","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dasch%2Fparser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dasch%2Fparser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dasch%2Fparser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dasch%2Fparser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dasch","download_url":"https://codeload.github.com/dasch/parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248637832,"owners_count":21137538,"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":[],"created_at":"2024-10-14T13:28:32.991Z","updated_at":"2025-04-12T21:40:35.198Z","avatar_url":"https://github.com/dasch.png","language":"Elm","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dasch/parser\n\nEasy to use text parsing library for Elm.\n\nThis library does not attempt to provide the fastest parsing API, nor does it allow for the most flexibility when it comes to error messages and contextual feedback. Rather, this library seeks to provide an intuitive, easy to use API for writing parsers that don't need to be crazy fast or provide detailed error messages.\n\n**Status:** This library is pretty new and probably has a bunch of bugs. Please try it out and report things to the Github issue tracker! However, don't expect this to be rock solid quite yet.\n\n\n## Examples\n\nLet's say you want to parse URLs such as `https://hello.com:123/greetings?recipient=world#message` into a nice data type, e.g.\n\n```elm\ntype alias Url =\n    { protocol : String\n    , host : String\n    , port_ : Maybe Int\n    , path : String\n    , query : Maybe String\n    , fragment : Maybe String\n    }\n```\n\nIn this case, we'd want a value that looks like this:\n\n```elm\n{ protocol = \"https\"\n, host = \"hello.com\"\n, port_ = Just 123,\n, path = \"/greetings\"\n, query = Just \"recipient=world\"\n, fragment = Just \"message\"\n}\n```\n\nYou also want an error if the parsing fails.\n\nLet's start by assuming we've already defined the individual pieces:\n\n```elm\nimport Parser exposing (..)\n\n-- Parser.Common has useful high level parsers.\nimport Parser.Common exposing (..)\n\nurl : Parser Url\nurl =\n    into Url\n        |\u003e grab protocol\n        |\u003e ignore (string \"://\")\n        |\u003e grab host\n        |\u003e grab (maybe port_)\n        |\u003e grab path\n        |\u003e grab (maybe query)\n        |\u003e grab (maybe fragment)\n```\n\nThere's already a lot of functionality here:\n\n* `url` has type `Parser Url`, meaning that when it's run, it'll parse a `Url` value when successful.\n* We're buiding a `Url`, and the `into` function starts a pipeline that allows for that. Any function can be used here as long as its arguments match the following `grab` lines.\n* The `|\u003e` (pipe) operator is used to feed values into the `Url` constructor.\n* Each pipeline element can either `grab` or `ignore` the value returned by a parser.\n* The `string` function allows creating a parser that matches an exact string.\n* The `maybe` function allows _maybe_ matching a parser, meaning that the matching is optional and will succeed with `Nothing` if there's no match.\n\nNow let's define each individual component. All of them are `Parser String`, so they'll succeed with a `String` value.\n\n```elm\nprotocol : Parser String\nprotocol =\n    stringWith (oneOrMore alpha)\n```\n\nHere we match one or more alphabetic characters, then map the characters to a `String`. We need to do this because `alpha` is a `Parser Char`, and `oneOrMore` turns a `Parser a` into a `Parser (List a)`. Therefore we'll end up with `Parser (List Char)`, but `stringWith` allows us to convert that into a `Parser String`.\n\n```elm\nhost : Parser String\nhost =\n    separatedBy (char '.') (stringWith (oneOrMore alphaNum))\n        |\u003e map (String.join \".\")\n```\n\nHere we first use `separatedBy` to get all the components of the host. Each component matches a string with one or more alphanumeric characters, and each component is separated by `.`. If this matches we'll end up with a `Parser (List String)`. By using `map` we'll turn that into a `Parser String` that succeeds with each component joined with a `.` again.\n\n```elm\nport_ : Parser Int\nport_ =\n    char ':'\n        |\u003e followedBy int\n```\n\nHere we match a `:` followed by an integer, e.g. `42`. `followedBy` discards the value of the previous parser in the pipeline in favor of its argument's value, so we'll just get a `Parser Int`.\n\n```elm\npath : Parser String\npath =\n    stringWith (oneOrMore (except (oneOf [ char '?', char '#' ])))\n        |\u003e orElse (succeed \"/\")\n```\n\nWe match a string with one or more characters that are _not_ one of `?` or `#`. If that fails, i.e. there's no path, we fall back to succeeding with `/` as the path using `orElse`.\n\n```elm\nquery : Parser String\nquery =\n    char '?'\n        |\u003e followedBy (stringWith (zeroOrMore (except (char '#'))))\n```\n\nWe match the character `?` followed by a string with zero or more characters that are _not_ `#`.\n\n```elm\nfragment : Parser String\nfragment =\n    char '#'\n        |\u003e followedBy (stringWith (until end anyChar))\n```\n\nWe match the character `#` followed by a string with zero or more of any character until the end of the parsed string.\n\nNow we have a parser that matches most valid URLs, but how do we run it? Here's how:\n\n```elm\nparsedUrl : Result Error Url\nparsedUrl =\n    Parser.parse \"https://hello.com:123/greetings?recipient=world#message\" url\n```\n\n`parse` takes an input string and a parser of type `Parse a` and returns a `Result Error a`, with `Error` specifying the error message and position into the input if the parser fails.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdasch%2Fparser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdasch%2Fparser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdasch%2Fparser/lists"}