{"id":43257308,"url":"https://github.com/jurgenbelien/parser-example","last_synced_at":"2026-02-01T13:35:43.207Z","repository":{"id":47555742,"uuid":"312789349","full_name":"jurgenbelien/parser-example","owner":"jurgenbelien","description":"A modest example of a parser written in Nearley.js.","archived":false,"fork":false,"pushed_at":"2024-08-20T07:31:10.000Z","size":438,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-20T09:31:50.046Z","etag":null,"topics":["nearley","parser"],"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/jurgenbelien.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-14T09:57:57.000Z","updated_at":"2024-08-20T07:31:09.000Z","dependencies_parsed_at":"2024-08-20T09:31:12.493Z","dependency_job_id":"ec43be15-a049-42b7-b4a2-d05297de1901","html_url":"https://github.com/jurgenbelien/parser-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jurgenbelien/parser-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jurgenbelien%2Fparser-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jurgenbelien%2Fparser-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jurgenbelien%2Fparser-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jurgenbelien%2Fparser-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jurgenbelien","download_url":"https://codeload.github.com/jurgenbelien/parser-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jurgenbelien%2Fparser-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28979191,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T12:13:08.691Z","status":"ssl_error","status_checked_at":"2026-02-01T12:13:08.356Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["nearley","parser"],"created_at":"2026-02-01T13:35:42.580Z","updated_at":"2026-02-01T13:35:43.202Z","avatar_url":"https://github.com/jurgenbelien.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Writing a parser in Nearley.js\n\nA modest example of a parser written in Nearley.js.\n\n## What is a parser?\n\nA parser converts input, often text, into a data structure.\n\nConsider the way a user logs hours worked in Atlassian Jira for instance:\n\u003e Time spent: (eg. 3w 4d 12h)\n\nJira has to convert text entered here into a canonical time quantity.\nThis can be done by writing a parser and then using the resulting data structure to do calculate the total value.\n\n## Lexer\n\nLet's consider the Jira example again: `3w 4d 12h`. The first step is to let a [lexer](./lexer.js) _tokenize_ the input, i.e., describing what kind of groups of characters we might encounter in the input and what their input is.\n\nFor the example text we encounter the following tokens, starting from the left:\n* A digit, representing a value.\n* The letter `w`, representing a unit.\n* A space.\n* Another digit.\n* The letter `d`.\n* Another space.\n* Two digits, forming one number.\n* The letter `h`.\n\nAforementioned tokens representing values are called _literals_ in lexical analysis, and the units can be treated as _keywords_. The _literals in the example are all integers, but we can imagine floats should also be accepted as literals. Lastly, we should tokenize whitespace.\n\n## Grammar\n\nAfter tokenizing we write a grammar to define in what sequence these token can occur. This is where Nearley comes in.\n\nLet's consider our example input again: `3w 4d 12h`. Let's call this our `statement`. The `statement` is a sequence of `quantity` entries, separated by a whitespace _token_. If we would treat the whitespace as optional, we can describe the `statement` as follows:\n\n```\nstatement -\u003e ( quantity ws:? ):+\n```\n\nNote the `:?` and `:+`. These have the same meaning as in Regular Expressions; \"zero or one occurance\" and \"one or more occurances\" respectively.\n\nNow that we have our first rule, we will have to continue writing rules until following every rule eventually ends in a token, like so:\n\n```\nws -\u003e %ws\n```\n\n## Parse results\n\nRunning the text through the parser will result in an array of parse tree, though that array  prefereably has only one entry. Having multiple parse trees means that the parser is ambiguous.\n\nThe parse tree is a multidimensional array where every rule or capture statement returns an array like so:\n\n```\n[\n  //statement\n  [\n    // ( ... ):+ capture group\n    [\n      // quantity\n    ],\n    [\n      // whitespace\n    ]\n  ]\n]\n```\n\n## Using the parser for further computation\n\nIn our use case of converting the string into a canonical unit of time, the complete parse tree is not relevant.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjurgenbelien%2Fparser-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjurgenbelien%2Fparser-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjurgenbelien%2Fparser-example/lists"}