{"id":21131391,"url":"https://github.com/jrop/pratt-calculator","last_synced_at":"2026-03-27T04:07:57.884Z","repository":{"id":144984811,"uuid":"65333971","full_name":"jrop/pratt-calculator","owner":"jrop","description":"A very simple expression evaluator written using a Pratt Parser","archived":false,"fork":false,"pushed_at":"2018-07-05T21:38:16.000Z","size":59,"stargazers_count":25,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-14T14:42:10.991Z","etag":null,"topics":["calculator","expression-evaluator","expression-parser","expression-tree","javascript","nodejs","parser","pratt-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/jrop.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-08-09T23:03:41.000Z","updated_at":"2025-03-11T19:28:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"dda1ef5c-ce23-4b99-8e64-4482b1d1156e","html_url":"https://github.com/jrop/pratt-calculator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jrop/pratt-calculator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrop%2Fpratt-calculator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrop%2Fpratt-calculator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrop%2Fpratt-calculator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrop%2Fpratt-calculator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrop","download_url":"https://codeload.github.com/jrop/pratt-calculator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrop%2Fpratt-calculator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31018555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T03:51:26.850Z","status":"ssl_error","status_checked_at":"2026-03-27T03:51:09.693Z","response_time":164,"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":["calculator","expression-evaluator","expression-parser","expression-tree","javascript","nodejs","parser","pratt-parser"],"created_at":"2024-11-20T05:55:20.916Z","updated_at":"2026-03-27T04:07:57.876Z","avatar_url":"https://github.com/jrop.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Pratt Parser\n============\n\nThis project demonstrates the fundamentals of a Pratt Parser.  It is based on [this paper](https://tdop.github.io/) by Vaughan Pratt, and also learns from [this article](http://javascript.crockford.com/tdop/tdop.html) and [this article](http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/).\n\nAdditionally, this README file attempts to simplify the concepts so that, when I come back to try to implement this again (at some undetermined point in the future), I will be able to remember how this works.\n\nThis README assumes that you already have read the previous two articles as this text merely attempts to simplify some of the concepts, hopefully adding intuition to them.\n\n## Concepts\n\nIn general, the Pratt Parser solves the following problem: given the string \"1 + 2 * 3\", does the \"2\" associate with the \"+\" or the \"\u0026#42;\".  It also solves \"-\" being both a prefix _and_ infix operator, as well as elegantly handling right associativity.\n\nThe Pratt Parser is based on three computational units:\n\n```js\nparser.expr(rbp) // the expression parser\ntoken.nud() // \"Null Denotation\" (operates on no \"left\" context)\ntoken.led(left, bp) // \"Left Denotation\" (operates with \"left\" context)\n```\n\nThe `parser.expr(rbp)` function looks like:\n\n```js\nfunction expr(rbp) {\n\tlet left = lexer.next().nud() // (1)\n\twhile (rbp \u003c lexer.peek().bp) { // (2)\n\t\tconst operator = lexer.next() // (3)\n\t\tleft = operator.led(left, operator.bp) // (4)\n\t}\n\treturn left\n}\n```\n\nOf course, `nud` and `led` may recursively call `expr`.\n\nThe `expr` method can be summarized in english as \"The loop (while) builds out the tree to the left, while recursion (led -\u003e expr) builds the tree out to the right; nud handles prefix operators\":\n\n```js\nfunction expr(rbp) {\n\t// (1) handle prefix operator\n\t// (2) continue until I encounter an operator of lesser precedence than myself\n\t// (3) \"eat\" the operator\n\t// (4) give the operator the left side of the tree, and let it build the right side; this new tree is our new \"left\"\n}\n```\n\n## Contributions\n\nThe Pratt Parser is a new concept to me, and thus this README would probably benefit from clarification, and the code would probably also benefit from cleanup.  Submit a PR if you feel so inclined!\n\n## LICENSE\n\nISC License (ISC)\nCopyright (c) 2016, Jonathan Apodaca \u003cjrapodaca@gmail.com\u003e\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrop%2Fpratt-calculator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrop%2Fpratt-calculator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrop%2Fpratt-calculator/lists"}