{"id":13394166,"url":"https://github.com/ohmjs/ohm","last_synced_at":"2026-02-12T13:23:27.116Z","repository":{"id":32443457,"uuid":"36021747","full_name":"ohmjs/ohm","owner":"ohmjs","description":"A library and language for building parsers, interpreters, compilers, etc.","archived":false,"fork":false,"pushed_at":"2025-05-06T14:19:56.000Z","size":25439,"stargazers_count":5289,"open_issues_count":49,"forks_count":218,"subscribers_count":87,"default_branch":"main","last_synced_at":"2025-05-06T16:16:59.224Z","etag":null,"topics":["compiler","grammars","javascript","parser","parsing","peg","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/ohmjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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":"2015-05-21T15:42:14.000Z","updated_at":"2025-05-06T12:00:02.000Z","dependencies_parsed_at":"2024-04-19T00:39:21.828Z","dependency_job_id":"9386d510-66c7-4eae-afce-e1a518b1c05b","html_url":"https://github.com/ohmjs/ohm","commit_stats":{"total_commits":1621,"total_committers":45,"mean_commits":"36.022222222222226","dds":"0.40777297964219616","last_synced_commit":"5137258c634ed383db8982ca805e5f8d39739d7b"},"previous_names":["harc/ohm"],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohmjs%2Fohm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohmjs%2Fohm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohmjs%2Fohm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohmjs%2Fohm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ohmjs","download_url":"https://codeload.github.com/ohmjs/ohm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252940918,"owners_count":21828769,"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":["compiler","grammars","javascript","parser","parsing","peg","typescript"],"created_at":"2024-07-30T17:01:11.135Z","updated_at":"2026-02-12T13:23:27.110Z","avatar_url":"https://github.com/ohmjs.png","language":"JavaScript","readme":"# [Ohm](https://ohmjs.org/) \u0026middot; [![NPM](https://img.shields.io/npm/v/ohm-js.svg)](https://www.npmjs.com/package/ohm-js) [![Node.js CI](https://github.com/ohmjs/ohm/actions/workflows/node.js.yml/badge.svg)](https://github.com/ohmjs/ohm/actions/workflows/node.js.yml) [![Chat on Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true)](https://discord.gg/KwxY5gegRQ)\n\nOhm is a parsing toolkit consisting of a library and a domain-specific language. You can use it to parse custom file formats or quickly build parsers, interpreters, and compilers for programming languages.\n\nThe _Ohm language_ is based on [parsing expression grammars](http://en.wikipedia.org/wiki/Parsing_expression_grammar)\n(PEGs), which are a formal way of describing syntax, similar to regular expressions and context-free\ngrammars. The _Ohm library_ provides a JavaScript interface for creating parsers, interpreters, and\nmore from the grammars you write.\n\n- **Full support for left-recursive rules** means that you can define left-associative operators in a natural way.\n- **Object-oriented grammar extension** makes it easy to extend an existing language with new syntax.\n- **Modular semantic actions.** Unlike many similar tools, Ohm completely\n  separates grammars from semantic actions. This separation improves modularity and extensibility, and makes both grammars and semantic actions easier to read and understand.\n- **Online editor and visualizer.** The [Ohm Editor](https://ohmjs.org/editor/) provides instant feedback and an [interactive visualization](https://dubroy.com/blog/visualizing-packrat-parsing/) that makes the entire execution of the parser visible and tangible. It'll [make you feel like you have superpowers](https://twitter.com/kylestetz/status/1349770893120172036). 💪\n\nSome awesome things people have built using Ohm:\n\n- [Seymour](https://harc.github.io/seymour-live2017/), a live programming environment for the classroom.\n- [Shadama](https://tinlizzie.org/~ohshima/shadama2/live2017/), a particle simulation language designed for high-school science.\n- [turtle.audio](http://turtle.audio/), an audio environment where simple text commands generate lines that can play music.\n- A [browser-based tool](https://www.arthurcarabott.com/konnakkol/) that turns written _Konnakkol_ (a South Indian vocal percussion art) into audio.\n- [Wildcard](https://www.geoffreylitt.com/wildcard/), a browser extension that empowers anyone to modify websites to meet their own specific needs, uses Ohm for its spreadsheet formulas.\n\n## Getting Started\n\nThe easiest way to get started with Ohm is to use the [interactive editor](https://ohmjs.org/editor/). Alternatively, you can play with one of the following examples on JSFiddle:\n\n- [Basic parsing example](https://jsfiddle.net/pdubroy/p3b1v2xb/)\n- [Arithmetic example with semantics](https://jsfiddle.net/pdubroy/15k63qae/)\n\n### Resources\n\n- Tutorial: [Ohm: Parsing Made Easy](https://nextjournal.com/dubroy/ohm-parsing-made-easy)\n- The [math example](https://github.com/ohmjs/ohm/tree/main/examples/math/index.html) is extensively commented and is a good way to dive deeper.\n- [Examples](https://github.com/ohmjs/ohm/tree/main/examples/)\n- [Documentation](doc/README.md)\n- For community support and discussion, join us on [Discord](https://discord.gg/KwxY5gegRQ), [GitHub Discussions](https://github.com/ohmjs/ohm/discussions), or the [ohm-discuss mailing list](https://groups.google.com/u/0/g/ohm-discuss).\n- For updates, follow [@\\_ohmjs on Twitter](https://twitter.com/_ohmjs).\n\n### Installation\n\n#### On a web page\n\nTo use Ohm in the browser, just add a single `\u003cscript\u003e` tag to your page:\n\n```html\n\u003c!-- Development version of Ohm from unpkg.com --\u003e\n\u003cscript src=\"https://unpkg.com/ohm-js@17/dist/ohm.js\"\u003e\u003c/script\u003e\n```\n\nor\n\n```html\n\u003c!-- Minified version, for faster page loads --\u003e\n\u003cscript src=\"https://unpkg.com/ohm-js@17/dist/ohm.min.js\"\u003e\u003c/script\u003e\n```\n\nThis creates a global variable named `ohm`.\n\n#### Node.js\n\nFirst, install the `ohm-js` package with your package manager:\n\n- [npm](http://npmjs.org): `npm install ohm-js`\n- [Yarn](https://yarnpkg.com/): `yarn add ohm-js`\n- [pnpm](https://pnpm.io/): `pnpm add ohm-js`\n\nThen, you can use `require` to use Ohm in a script:\n\n\u003c!-- @markscript\n  markscript.transformNextBlock(s =\u003e s.replace('const ', 'var '));\n--\u003e\n\n```js\nconst ohm = require('ohm-js');\n```\n\nOhm can also be imported as an ES module:\n\n```js\nimport * as ohm from 'ohm-js';\n```\n\n#### Deno\n\nTo use Ohm from [Deno](https://deno.land/):\n\n```js\nimport * as ohm from 'https://unpkg.com/ohm-js@17';\n```\n\n### Basics\n\n#### Defining Grammars\n\n![Instantiating a grammar](https://ohmjs.org/img/docs/instantiating-grammars.png)\n\nTo use Ohm, you need a grammar that is written in the Ohm language. The grammar provides a formal\ndefinition of the language or data format that you want to parse. There are a few different ways\nyou can define an Ohm grammar:\n\n- The simplest option is to define the grammar directly in a JavaScript string and instantiate it\n  using `ohm.grammar()`. In most cases, you should use a [template literal with String.raw](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw):\n\n  ```js\n  const myGrammar = ohm.grammar(String.raw`\n    MyGrammar {\n      greeting = \"Hello\" | \"Hola\"\n    }\n  `);\n  ```\n\n- **In Node.js**, you can define the grammar in a separate file, and read the file's contents and instantiate it using `ohm.grammar(contents)`:\n\n  In `myGrammar.ohm`:\n\n        MyGrammar {\n          greeting = \"Hello\" | \"Hola\"\n        }\n\n  In JavaScript:\n\n  ```js\n  const fs = require('fs');\n  const ohm = require('ohm-js');\n  const contents = fs.readFileSync('myGrammar.ohm', 'utf-8');\n  const myGrammar = ohm.grammar(contents);\n  ```\n\nFor more information, see [Instantiating Grammars](doc/api-reference.md#instantiating-grammars) in the API reference.\n\n#### Using Grammars\n\n![Matching input](https://ohmjs.org/img/docs/matching.png)\n\n\u003c!-- @markscript\n  // The duplication here is required because Markscript only executes top-level code blocks.\n  // TODO: Consider fixing this in Markscript.\n  const myGrammar = ohm.grammar('MyGrammar { greeting = \"Hello\" | \"Hola\" }');\n--\u003e\n\nOnce you've instantiated a grammar object, use the grammar's `match()` method to recognize input:\n\n```js\nconst userInput = 'Hello';\nconst m = myGrammar.match(userInput);\nif (m.succeeded()) {\n  console.log('Greetings, human.');\n} else {\n  console.log(\"That's not a greeting!\");\n}\n```\n\nThe result is a MatchResult object. You can use the `succeeded()` and `failed()` methods to see whether the input was recognized or not.\n\nFor more information, see the [main documentation](doc/README.md).\n\n### Debugging\n\nOhm has two tools to help you debug grammars: a text trace, and a graphical visualizer.\n\n[![Ohm Visualizer](https://ohmjs.org/img/docs/visualizer-small.png)](https://ohmjs.org/editor)\n\nYou can [try the visualizer online](https://ohmjs.org/editor).\n\nTo see the text trace for a grammar `g`, just use the [`g.trace()`](doc/api-reference.md#trace)\nmethod instead of `g.match`. It takes the same arguments, but instead of returning a MatchResult\nobject, it returns a Trace object — calling its `toString` method returns a string describing\nall of the decisions the parser made when trying to match the input. For example, here is the\nresult of `g.trace('ab').toString()` for the grammar `G { start = letter+ }`:\n\n\u003c!-- @markscript\n  markscript.transformNextBlock(function(code) {\n    const trace = ohm.grammar('G { start = letter+ }').trace('ab');\n    assert.equal(trace.toString().trim(), code.trim());\n  });\n--\u003e\n\n```\nab         ✓ start ⇒  \"ab\"\nab           ✓ letter+ ⇒  \"ab\"\nab             ✓ letter ⇒  \"a\"\nab                 ✓ lower ⇒  \"a\"\nab                   ✓ Unicode [Ll] character ⇒  \"a\"\nb              ✓ letter ⇒  \"b\"\nb                  ✓ lower ⇒  \"b\"\nb                    ✓ Unicode [Ll] character ⇒  \"b\"\n               ✗ letter\n                   ✗ lower\n                     ✗ Unicode [Ll] character\n                   ✗ upper\n                     ✗ Unicode [Lu] character\n                   ✗ unicodeLtmo\n                     ✗ Unicode [Ltmo] character\n           ✓ end ⇒  \"\"\n```\n\n## Publishing Grammars\n\nIf you've written an Ohm grammar that you'd like to share with others, see\nour [suggestions for publishing grammars](./doc/publishing-grammars.md).\n\n## Contributing to Ohm\n\nInterested in contributing to Ohm? Please read [CONTRIBUTING.md](./CONTRIBUTING.md)\nand the [Ohm Contributor Guide](doc/contributor-guide.md).\n","funding_links":[],"categories":["JavaScript","🌐 Web Development - Frontend","compiler","\u003ca name=\"JavaScript\"\u003e\u003c/a\u003eJavaScript","Compilers \u0026 Language Interpreters"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fohmjs%2Fohm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fohmjs%2Fohm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fohmjs%2Fohm/lists"}