{"id":26059626,"url":"https://github.com/mnikander/langium_calculator","last_synced_at":"2026-04-23T09:35:49.779Z","repository":{"id":274303721,"uuid":"921611751","full_name":"mnikander/langium_calculator","owner":"mnikander","description":"Domain specific language (DSL) for basic arithmetic expressions","archived":false,"fork":false,"pushed_at":"2025-01-26T13:29:27.000Z","size":85,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-08T13:28:34.938Z","etag":null,"topics":["domain-specific-language","langium","transpiler"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/mnikander.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-24T09:24:39.000Z","updated_at":"2025-01-26T13:29:30.000Z","dependencies_parsed_at":"2025-01-26T13:26:04.964Z","dependency_job_id":"04fd9823-f28b-41cf-bd93-4242258ec06e","html_url":"https://github.com/mnikander/langium_calculator","commit_stats":null,"previous_names":["mnikander/langium_calculator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mnikander/langium_calculator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnikander%2Flangium_calculator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnikander%2Flangium_calculator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnikander%2Flangium_calculator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnikander%2Flangium_calculator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mnikander","download_url":"https://codeload.github.com/mnikander/langium_calculator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnikander%2Flangium_calculator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32174858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T02:19:40.750Z","status":"ssl_error","status_checked_at":"2026-04-23T02:17:55.737Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["domain-specific-language","langium","transpiler"],"created_at":"2025-03-08T13:26:47.883Z","updated_at":"2026-04-23T09:35:49.741Z","avatar_url":"https://github.com/mnikander.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Calculator DSL\n\nThis domain-specific language (DSL) allows writing and evaluating basic arithmetic expressions in prefix-notation, i.e. Polish notation.\nThe equation `1+2*3` would be expressed as: `(+ 1 (* 2 3))`.\nNote that the parethesis make the order of execution explicit, so there is no order-of-precedence amongst functions.\n\n## How does the toolchain work?\n\nThis project was built using [Langium](https://langium.org/), a language engineering tool.\nThe grammar for the language is defined in _src/language/calculator.langium_.\nLangium uses this grammar definition to generate a tokenizer, parser, and VS code extension with syntax highlighting and auto-completion for the language.\nAfter everything has been generated, langium is able to parse a document written in the 'calculator language' and generate an abstract syntax tree for it.\n\n**An example document in the calculator language:**\n```lisp\n(+ 1 2)\n```\n\n**The abstract syntax tree (AST), exported to JSON:**\n\n```json\n{\n    \"$type\": \"Model\",\n    \"expressions\": [\n        {\n            \"$type\": \"Application\",\n            \"operator\": {\n                \"$type\": \"Binary\",\n                \"value\": \"+\"\n            },\n            \"arguments\": [\n                {\n                    \"$type\": \"Integer\",\n                    \"value\": 1\n                },\n                {\n                    \"$type\": \"Integer\",\n                    \"value\": 2\n                }\n            ]\n        },\n    ]\n}\n```\n\nTo get executable code, the AST must be translated into a language which we can execute.\nThe hand-written code generator can be found in _src/cli/generator.ts_.\nIt takes any 'calculator AST' and converts (transpiles) it to the corresponding C++ code.\n\n**The generated C++ code:**\n\n```c++\n#include \u003ccmath\u003e\n#include \u003ccstdlib\u003e\n#include \u003ciostream\u003e\n#include \u003cfunctional\u003e\n\nint main()\n{\n    std::cout \u003c\u003c std::to_string(std::plus\u003c\u003e{}(1, 2)) \u003c\u003c std::endl;\n    return EXIT_SUCCESS;\n}\n```\n\nThe C++ code can then be compiled and executed to evaluate the calculator expressions.\nC++ was chosen as the target language because it's fast and provides useful abstractions.\nThis makes it easier to develop and debug the code generator, than if LLVM IR or WebAssembly was chosen as the target language.\nFunction objects from the functional header were used, instead of the inbuild `operator+`, for example. \nThis maintains a more consistent syntax even with functions for which there are no inbuilt operators in C++.\n\nGenerators could be written for other languages as well.\nJavaScript is a very attractive target language because an IDE and the entire toolchain, including execution of the code, could be run inside the browser.\nThe langauge could then be used by simply visiting the right website.\nThe IDE and execution environment would run locally on the client (in the browser) and not on the server, which ensures the IDE is very responsive and hosting costs stay reasonable.\nFor the time being, that approach was not chosen here though.\n\n## Setup\n\n1. Setup Langium on your machine: https://www.npmjs.com/package/langium\n2. Clone this repo\n3. Build using the task in vscode (or execute `npm run langium:generate \u0026\u0026 npm run build` in a terminal)\n4. Run the resulting program in vscode, to start a new vscode window which has the extension for 'Calculator' loaded\n5. In this new vscode window, open a .calc file in the example/ directory to try out syntax highlighting and auto-completion\n\n## Compile and run the entire pipeline\n\nEnsure you have [langium](https://www.npmjs.com/package/langium) and gcc (or another C++ compiler) installed on your Unix machine and run the following commands:\n\n```bash\nnpm run langium:generate \u0026\u0026 \\\nnpm run build \u0026\u0026 \\\nnode bin/cli.js toJSON examples/example.calc out/generated.json \u0026\u0026 \\\nnode bin/cli.js toCPP examples/example.calc out/generated.cpp \u0026\u0026 \\\ng++ -o out/generated out/generated.cpp \u0026\u0026 \\\n./out/generated\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnikander%2Flangium_calculator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmnikander%2Flangium_calculator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnikander%2Flangium_calculator/lists"}