{"id":28360711,"url":"https://github.com/jleahred/fsm_gen","last_synced_at":"2025-09-14T20:55:33.536Z","repository":{"id":62439292,"uuid":"177114712","full_name":"jleahred/fsm_gen","owner":"jleahred","description":"External DSL for code generation of Finite State Machines","archived":false,"fork":false,"pushed_at":"2023-07-24T20:00:20.000Z","size":374,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-20T23:35:22.326Z","etag":null,"topics":["cpp","dsl","fsm","generator","rust"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jleahred.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,"zenodo":null}},"created_at":"2019-03-22T09:50:56.000Z","updated_at":"2023-12-24T18:45:44.000Z","dependencies_parsed_at":"2025-06-20T23:41:51.238Z","dependency_job_id":null,"html_url":"https://github.com/jleahred/fsm_gen","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jleahred/fsm_gen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jleahred%2Ffsm_gen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jleahred%2Ffsm_gen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jleahred%2Ffsm_gen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jleahred%2Ffsm_gen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jleahred","download_url":"https://codeload.github.com/jleahred/fsm_gen/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jleahred%2Ffsm_gen/sbom","scorecard":{"id":523129,"data":{"date":"2025-08-11","repo":{"name":"github.com/jleahred/fsm_gen","commit":"29c29eab481e74faf1dc284b19a9da44b599451d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"16 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: RUSTSEC-2021-0139","Warn: Project is vulnerable to: GHSA-2rxc-gjrp-vjhx","Warn: Project is vulnerable to: RUSTSEC-2024-0404","Warn: Project is vulnerable to: RUSTSEC-2021-0145 / GHSA-g98v-hv3f-hcfr","Warn: Project is vulnerable to: RUSTSEC-2024-0375","Warn: Project is vulnerable to: RUSTSEC-2020-0159","Warn: Project is vulnerable to: RUSTSEC-2021-0093 / GHSA-pqqp-xmhj-wgcw","Warn: Project is vulnerable to: RUSTSEC-2022-0041 / GHSA-qc84-gqf4-9926","Warn: Project is vulnerable to: RUSTSEC-2020-0146 / GHSA-3358-4f7f-p4j4","Warn: Project is vulnerable to: RUSTSEC-2019-0011 / GHSA-rh89-x75f-rh3c","Warn: Project is vulnerable to: RUSTSEC-2023-0045 / GHSA-wfg4-322g-9vqv","Warn: Project is vulnerable to: RUSTSEC-2024-0370","Warn: Project is vulnerable to: RUSTSEC-2022-0013 / GHSA-m5pq-gvj9-9vr8","Warn: Project is vulnerable to: GHSA-c827-hfw6-qwvm","Warn: Project is vulnerable to: RUSTSEC-2022-0006 / GHSA-9hpw-r23r-xgm5","Warn: Project is vulnerable to: RUSTSEC-2020-0071 / GHSA-wcg3-cvx6-7396"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T03:35:13.100Z","repository_id":62439292,"created_at":"2025-08-20T03:35:13.100Z","updated_at":"2025-08-20T03:35:13.100Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275167355,"owners_count":25416989,"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","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cpp","dsl","fsm","generator","rust"],"created_at":"2025-05-28T11:36:14.634Z","updated_at":"2025-09-14T20:55:33.528Z","avatar_url":"https://github.com/jleahred.png","language":"C++","readme":"# FSM generator\n\n## Installation\n\n```bash\ncargo install -f fsm_gen\n```\n\nYou can download from repository and build and install as usual\n\n```bash\ncargo build --release\ncargo install --path . -f\n```\n\n\n## TODO\n\n\n- revisit dot\n- generate mermaid\n- check README.md\n\n- Error transition is special\n- Inprove exceptions control\n- web ui for templates\n- read template from file\n\n- Complete the cpp example and update on README.md\n- Check fsm format\n  - detect duplicated states\n  - detect duplicated inputs and guards\n- output with signals\n\n- Add new templates\n\n## Versions\n\n### 0.8\n- Added adapters (aka transformers)\n- New cpp generator with no c++ template\u003c\u003e code\n- cpp template with CamelNames for structs\n- \"_\" special final state\n\n### 0.7\n\n- Modifs on `cpp` generated code\n    - Removed `.reference` files\n    - Added `_forwards` files\n    - `gen_` at the begining to indicate you souldn't touch\n    - `actions` and `guards` using `cpp templates`\n- Better `.dot` generated diagrams\n- cpp\n    - Removed shadow warning\n    - Removed no virtual destructor\n\n### 0.6\n\n- `cpp` generated code with option to move to `error` state\n- Instead of `languages`, now we speak about `templates`\n\n### 0.5\n\n- moved to tera templates\n- added dot files generation\n \n### 0.4\n\n- error redefinied action on cpp (watch example iceberg)\n- fix error when running on current directory\n- Add full proposed file for hand written .h and .cpp on generated one\n\n### 0.3\n\n- multiline guards with no status name\n- multi guard and multi actions\n- '\\_' on input means any other input\n- negative guards\n- if no transition, it will generate an error\n- updated rust-peg lib and working with macros\n- if execption is throwed, we will go to error transition\n- better error information\n  - on parsing show line\n  - check orphans status\n- makefile install, test cpp\n\n### 0.2\n\n- Actions\n- private hpp (hand file)\n- Template functions to specialize on transaction change\n- Anonymous `namespace` for functions\n- Add comments support on fsm grammar\n\n\n## Objective\n\nAll computer systems interact with the external world by receiving information, processing it, and generating a result.\n\nIn addition to communicating with the outside world through `input/output`, it is common for a system to manage a `state`.\n\nThese two elements are fundamental in computer systems.\n\nThat's why I developed two external DSLs (for data and states) several years ago to simplify working with these concepts (which I still use in production and find very helpful).\n\nIn this repository, I have rewritten one of them: a code generator for state machines.\n\nCurrently, it generates C++ code (the most practical to me at the moment ;-).\n\nTo explain the system, I will use the example in [cpp_test/fsm](cpp_test/fsm).\n\nThis example is about building a system that handles login requests.\n\nThe _state_ diagram would look like this:\n\n![Basic diagram](basic_diagram.png)\n\nFirst, the client will require a key to send a request login with a coded password.\n\nThis key will be used to encrypt the username and password (the password will go through a hash function) in the login request.\n\nThis encryption is irreversible (hash function). The server will perform the same operation (starting from the password hash) to verify its validity.\n\nIf it is correct, a login confirmation will be sent.\n\nThe DSL representation of this definition would be:\n\n```fsm\n// Example of an FSM for managing login\n// on the server side\n\n[init]\n    rq_key              -\u003e  w_login     /   send_key           // this is a comment\n    timer               -\u003e  init\n\n[w_login]\n    rq_login\n        \u0026  ok           -\u003e  login       /   send_login\n                        -\u003e  error\n    timer\n        \u0026 timeout       -\u003e  error\n                        -\u003e  w_login\n[login]\n    rq_logout           -\u003e  logout      /   send_logout\n    heartbeat           -\u003e  login       /   update_hbr\n    timer\n        \u0026 timeout       -\u003e  logout\n                        -\u003e  login\n\n[logout]\n    timer               -\u003e  _\n    _                   -\u003e  testing     /   send_logout\n\n[error]\n    _                   -\u003e  error\n\n```\n\nThis program also generates the displayed diagram before using the `DSL`.\n\n\n## Elements\n\nLet's now break down the elements that define a state machine.\n\nA state machine specifies the states and transitions based on the received inputs.\n\n### State\n\nThe machine is always in a state, and for each received input and the contextual information of the current state, we transition to another state, potentially performing some actions.\n\nTherefore, in each state, there will be specific contextual information associated with that state.\n\n\n### Transition\n\n```fsm\n[w_login]\n    rq_login            -\u003e  login       /   send_login\n```\n\nStarting from the state w_login, if we receive the login request, we transition to the state login and send the login confirmation (send_login).\n\nIn this simple transition, we can see the basic elements:\n\n\n```fsm\ninitial estate\n    v\n[w_login]\n\n      INPUT                FINAL STATE         ACTION\n        v                     v                  v\n    rq_login            -\u003e  login       /   send_login\n```\n\n\n\n### Initial State\n\n\n```fsm\n[init]\n```\n\n* Enclosed in brackets\n* At the beginning of the line\n\n### Input\n\nReceived element\n\n```fsm\n[w_login]\n\n      INPUT\n        v\n    rq_login            -\u003e  login       /   send_login\n```\n\n\n### Final State\n\n```fsm\n[w_login]\n\n                         FINAL STATE         \n                              v                   \n    rq_login            -\u003e  login       /   send_login\n```\n\nWhere the machine will be positioned for processing the next _input_\n\n\n### Action\n\n```fsm\n[w_login]\n\n                                             ACTION\n                                               v\n    rq_login            -\u003e  login       /   send_login\n```\n\nIn addition to transitioning to the new state, we can specify what action/effect to do on each transition\n\nMultiple actions can be define for each transition by separating them with spaces\n\n\n```fsm\n[w_login]\n    rq_login            -\u003e  login       /   send_login   write_log\n```\n\n\n### Guards\n\nGuards are used to define different paths based on the state information and input\n\n```\n                    GUARD\n                     v\n    rq_login    \u0026   ok   -\u003e  login       /   send_login\n``` \n\nYou can have more than one guard.\n\n```\n                    GUARD      GUARD\n                     v           v\n    rq_login    \u0026   ok   \u0026  system_ready  -\u003e  login       /   send_login\n```\n\nFor an input, you can for using several guards to generate different transitions\n\nWhen last transition doesn't have guard, behave as _else_\n\n```\n    rq_login\n        \u0026   valid   -\u003e  login       /   send_login\n                    -\u003e  logout      /   log_err\n```\n\nYou can use negation with guards\n\nThe previous example could be written with a negative guard.\n\n```\n    rq_login\n           NEGATED GUARD\n            v\n        \u0026   !valid  -\u003e  logout      /   log_err\n                    -\u003e  login       /   send_login\n```\n\n### Special input\n\nIn the following transition, we have a special input \"_\":\n\n```fsm\n[logout]\n    _                   -\u003e  testing     /   send_logout\n    ^\n  SPECIAL INPUT\n```\n\nThe symbol \"_\" will be used to indicate that a transition should be generated with the rules defined in this one for each unspecified input.\n\n### Special final state\n\n```fsm\n[logout]\n    timer               -\u003e  _\n                            ^\n                          SPECIAL FINAL STATE\n\n    _                   -\u003e  testing     /   send_logout\n```\n\nA final state with the symbol \"_\" indicates that there is no change in state.\n\nNot only do we stay in the same state, but the state's context data remains unchanged.\n\n### error status and implicit transitions\n\n\n`error` is a special status\n\nYou can move to `error` status explicitly as any other normal status\n\nBut any transition no defined, will finish on error status.\n\nYou can also put some verifications on transiction funcion, and incase\nof fail, you can move to error (even when is not explicitly writted on `fsm`)\n\nThis is so, because checking the params, is so commont that adding guards for it, would generate a lot of noise\n\n\nIn our example...\n\n```fsm\n[init]\n    rq_key          -\u003e  w_login     /   send_key\n    timer           -\u003e  init\n```\n\nThere are no transations for `rq_login` and `rq_logout`. Both are implicit and is\nequivalent to...\n\n```fsm\n[init]\n    rq_key          -\u003e  w_login     /   send_key\n    timer           -\u003e  init\n    _               -\u003e  error\n```\n\n\n### Adapters\n\naka _transformers_\n\nAdapters can be placed at the input, guards, and transition levels.\n\nIn the case of transitions, they will be placed in the final state.\n\n```fsm\n                                                           ADAPTER\n[init]                                                        v\n    rq_key                      -\u003e  w_login     /   send_key|rq\n    timer                       -\u003e  init\n    _                           -\u003e  logout      /   log_err\n\n\n```\n\nThe adapters will help us extract common functionalities, reducing the number of functions to be filled manually, or adding context information to make the generated code more readable.\n\n```fsm\n                ADAPTER                   ADAPTER             ADAPTER\n[init]             v                         v                   v\n    rq_key    \u0026ok|rq            -\u003e  w_login|rqok    /   send_key|rq\n    timer                       -\u003e  init\n    _                           -\u003e  logout          /   log_err\n\n\n```\n\n\n\n### Comments\n\nComments start with // and continue until the end of the line.\n\n\n\n## Usage\n\nTo get help...\n\n```bash\nfsm_gen --help\n```\n\n```fsm\n\u003e fsm_gen -h\n\n\nfsm_gen 0.8.0\n\n    Generate code from a simple fsm file\n    To check the supported templates  --show_templs\n    \n\nUSAGE:\n    fsm_gen [FLAGS] [OPTIONS] [fsm-files]...\n\nFLAGS:\n    -d, --dot-graphviz    Generate graphviz dot file\n    -f, --force           Generate all files regardless of change date. DANGEROUS!!!\n    -h, --help            Prints help information\n        --help-cpp        Give me some information about generating cpp files with no templates to fill\n    -s, --show-templs     Show supported template generators\n    -V, --version         Prints version information\n\nOPTIONS:\n    -T, --threads \u003cn-threads\u003e    Number of threads to use. 0 means one per core  ;-) [default: 0]\n    -t, --templ \u003ctempl\u003e          Template to generate code (show available --show-templs) [default: cpp]\n\nARGS:\n    \u003cfsm-files\u003e...    List of fsm files to be processed\n\n```\n\nThe default template is `cpp` (for c++) (and at the moment the only one)\n\n\n```bash\nfsm_gen --help\n```\n\n```fsm\n\u003e fsm_gen --show-templs\n\nSupported templates:   cpp \n\n```\n\n\n\n```bash\nfsm_gen --help\n```\n\n\nHelp about cpp template...\n\n```fsm\n\u003e fsm_gen --help-cpp\n\nBeing \"name.fsm\" the name of the file with the definition of the machine, next files an directories will be generated\n\nAll will be generated on directory...\n\n    fsm_\u003cname\u003e/\n\n\n    Main entry point. Do not modify, it will be rewritting on each execution\n        \u003cname\u003e.h\n        \u003cname\u003e.cpp\n\n    Types\n        \u003cname\u003e_types.h                      (to be filled manually)\n        \u003cname\u003e_types_reference.h            (just as reference)\n        \u003cname\u003e_types_adapters_fordward.h    (forward declaration and reference)\n        \u003cname\u003e_types_adapters.h             (to be filled manually)\n\n    Support functions.\n    You shouldn't mofify headers and you have to fill  .cpp\n\n        impl/log.hpp\n\n        impl/guards.h\n        impl/guards.cpp\n\n        impl/actions.h\n        impl/actions.cpp\n        \n        impl/transitions.h\n        impl/transitions.cpp\n\n\n```\n\n\n\nTo generate code...  run\n\n```bash\nfsm_gen login.fsm\n```\n\nAnd it will generate the `c++`\n\nYou can pass a list of `fsm` files\n\n```bash\nfsm_gen login.fsm  test/seller.fsm test/test2/lift.fsm\n```\n\nThe code will be generated on same directory of original `.fsm` file\n\nIf your shell supports it, you could run...\n\n```bash\nfsm_gen **/*.fsm\n```\n\n## C++ code generation\n\nIt will also generate the files _types.h_, _types_adapters.h_, and _types_forward.h_.\n\nThe _types_reference.h_ file serves as a reference for everything generated in the types files.\n\nThe _types.h_ file is initially created and will not be overwritten in subsequent executions.\n\nThis file will be used to customize the \"types\".\n\nDirectories/modules will be created for \n\n    impl\n        actions\n        guards\n        transitions\n\n\nThe header files will be rewritten and will help avoid \"dead code\" and provide the new functions to be filled in.\n\n`transitions`, `guards` and `adapters` should be pure, no effects\n\n* `transitions` will return the new transition with provider parameters (from status, intput)\n* `guards`: will return true or false with current status and input\n* `adapters` will return a new type using the parameters where the adapter is applied\n* `actions`with initial transition status, the input and the final status, we have the oportunity to do something (in general, produce an _effect_)\n\nWhen an `adapter` is applied to a `transition`, `guard`, or `action`, the parameter will be the `adatpter` type\n\n\nThe `adapters` will be C++ structs with constructors based on the context.\n\nIn these types, we have the opportunity to add direct or processed information.\n\nThe adapters will help us extract common factors, reducing the number of functions to be filled in, or add context information to make the generated code more readable.\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjleahred%2Ffsm_gen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjleahred%2Ffsm_gen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjleahred%2Ffsm_gen/lists"}