# pyfcstm
[](https://pypi.org/project/pyfcstm/)





[](https://codeclimate.com/github/HansBug/pyfcstm/maintainability)
[](https://codecov.io/gh/hansbug/pyfcstm)
[](https://deepwiki.com/HansBug/pyfcstm)
[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Docs+Deploy%22)
[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Code+Test%22)
[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Badge+Creation%22)
[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Package+Release%22)
[](https://github.com/hansbug/pyfcstm/stargazers)
[](https://github.com/hansbug/pyfcstm/network)

[](https://github.com/hansbug/pyfcstm/issues)
[](https://github.com/hansbug/pyfcstm/pulls)
[](https://github.com/hansbug/pyfcstm/graphs/contributors)
[](https://github.com/hansbug/pyfcstm/blob/master/LICENSE)
A Python framework for parsing finite state machine DSL and generating executable code in multiple target languages.
## Installation
You can simply install it with `pip` command line from the official PyPI site.
```shell
pip install pyfcstm
```
For more information about installation, you can refer
to [Installation Documentation](https://hansbug.github.io/pyfcstm/main/tutorials/installation/index.html).
## How To Use It
### Use With CLI
You can use this with CLI command
```shell
pyfcstm --help
```
* Generate Plantuml Code For Visualization
```shell
pyfcstm plantuml -i test_dsl_code.fcstm
```
Here is a simple code example, you can try this out
```
def int a = 0;
def int b = 0x0;
def int round_count = 0; // define variables
state TrafficLight {
>> during before {
a = 0;
}
>> during before abstract FFT;
>> during before abstract TTT;
>> during after {
a = 0xff;
b = 0x1;
}
!InService -> [*] :: Error;
state InService {
enter {
a = 0;
b = 0;
round_count = 0;
}
enter abstract InServiceAbstractEnter /*
Abstract Operation When Entering State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
// for non-leaf state, either 'before' or 'after' aspect keyword should be used for during block
during before abstract InServiceBeforeEnterChild /*
Abstract Operation Before Entering Child States of State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
during after abstract InServiceAfterEnterChild /*
Abstract Operation After Entering Child States of State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
exit abstract InServiceAbstractExit /*
Abstract Operation When Leaving State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
state Red {
during { // no aspect keywords ('before', 'after') should be used for during block of leaf state
a = 0x1 << 2;
}
}
state Yellow;
state Green;
[*] -> Red :: Start effect {
b = 0x1;
};
Red -> Green effect {
b = 0x3;
};
Green -> Yellow effect {
b = 0x2;
};
Yellow -> Red : if [a >= 10] effect {
b = 0x1;
round_count = round_count + 1;
};
Green -> Yellow : /Idle.E2;
Yellow -> Yellow : /E2;
}
state Idle;
[*] -> InService;
InService -> Idle :: Maintain;
Idle -> Idle :: E2;
Idle -> [*];
}
```
* Generate Code With Given Template
```shell
pyfcstm generate -i test_dsl_code.fcstm -t template_dir/ -o generated_code_dir/
```
### Use With Pythonic API
You can use this with pythonic API.
```python
from pyfcstm.dsl import parse_with_grammar_entry
from pyfcstm.model.model import parse_dsl_node_to_state_machine
from pyfcstm.render import StateMachineCodeRenderer
if __name__ == '__main__':
# Load AST Node From DSL Code
ast_node = parse_with_grammar_entry("""
def int a = 0;
def int b = 0x0;
def int round_count = 0; // define variables
state TrafficLight {
state InService {
enter {
a = 0;
b = 0;
round_count = 0;
}
enter abstract InServiceAbstractEnter /*
Abstract Operation When Entering State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
// for non-leaf state, either 'before' or 'after' aspect keyword should be used for during block
during before abstract InServiceBeforeEnterChild /*
Abstract Operation Before Entering Child States of State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
during after abstract InServiceAfterEnterChild /*
Abstract Operation After Entering Child States of State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
exit abstract InServiceAbstractExit /*
Abstract Operation When Leaving State 'InService'
TODO: Should be Implemented In Generated Code Framework
*/
state Red {
during { // no aspect keywords ('before', 'after') should be used for during block of leaf state
a = 0x1 << 2;
}
}
state Yellow;
state Green;
[*] -> Red :: Start effect {
b = 0x1;
};
Red -> Green effect {
b = 0x3;
};
Green -> Yellow effect {
b = 0x2;
};
Yellow -> Red : if [a >= 10] effect {
b = 0x1;
round_count = round_count + 1;
};
}
state Idle;
[*] -> InService;
InService -> Idle :: Maintain;
Idle -> [*];
}
""", entry_name='state_machine_dsl')
# Load DSL Model From DSL AST Node
model = parse_dsl_node_to_state_machine(ast_node)
# Load Template Directory
renderer = StateMachineCodeRenderer(
template_dir='../fsm_generation_template'
)
# Render to Given Directory Via Template Directory
renderer.render(model, 'test_output_x')
```
For more information about this DSL,
see: [PyFCSTM DSL Syntax Tutorial](https://hansbug.github.io/pyfcstm/main/tutorials/dsl/index.html).
Raw data
{
"_id": null,
"home_page": "https://github.com/hansbug/pyfcstm",
"name": "pyfcstm",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "state-machine, code-generation, compiler, template-engine, modelling",
"author": "HansBug",
"author_email": "hansbug@buaa.edu.cn",
"download_url": "https://files.pythonhosted.org/packages/fc/b7/7bd87cf405133685ed3d510a427d02e9969e1a4289bb2000635ed11c27af/pyfcstm-0.1.2.tar.gz",
"platform": null,
"description": "# pyfcstm\n\n[](https://pypi.org/project/pyfcstm/)\n\n\n\n\n\n\n[](https://codeclimate.com/github/HansBug/pyfcstm/maintainability)\n[](https://codecov.io/gh/hansbug/pyfcstm)\n[](https://deepwiki.com/HansBug/pyfcstm)\n\n[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Docs+Deploy%22)\n[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Code+Test%22)\n[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Badge+Creation%22)\n[](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Package+Release%22)\n\n[](https://github.com/hansbug/pyfcstm/stargazers)\n[](https://github.com/hansbug/pyfcstm/network)\n\n[](https://github.com/hansbug/pyfcstm/issues)\n[](https://github.com/hansbug/pyfcstm/pulls)\n[](https://github.com/hansbug/pyfcstm/graphs/contributors)\n[](https://github.com/hansbug/pyfcstm/blob/master/LICENSE)\n\nA Python framework for parsing finite state machine DSL and generating executable code in multiple target languages.\n\n## Installation\n\nYou can simply install it with `pip` command line from the official PyPI site.\n\n```shell\npip install pyfcstm\n```\n\nFor more information about installation, you can refer\nto [Installation Documentation](https://hansbug.github.io/pyfcstm/main/tutorials/installation/index.html).\n\n## How To Use It\n\n### Use With CLI\n\nYou can use this with CLI command\n\n```shell\npyfcstm --help\n```\n\n* Generate Plantuml Code For Visualization\n\n```shell\npyfcstm plantuml -i test_dsl_code.fcstm\n```\n\nHere is a simple code example, you can try this out\n\n```\ndef int a = 0;\ndef int b = 0x0;\ndef int round_count = 0; // define variables\nstate TrafficLight {\n >> during before {\n a = 0;\n }\n >> during before abstract FFT;\n >> during before abstract TTT;\n >> during after {\n a = 0xff;\n b = 0x1;\n }\n\n !InService -> [*] :: Error;\n\n state InService {\n enter {\n a = 0;\n b = 0;\n round_count = 0;\n }\n\n enter abstract InServiceAbstractEnter /*\n Abstract Operation When Entering State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n\n // for non-leaf state, either 'before' or 'after' aspect keyword should be used for during block\n during before abstract InServiceBeforeEnterChild /*\n Abstract Operation Before Entering Child States of State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n\n during after abstract InServiceAfterEnterChild /*\n Abstract Operation After Entering Child States of State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n\n exit abstract InServiceAbstractExit /*\n Abstract Operation When Leaving State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n\n state Red {\n during { // no aspect keywords ('before', 'after') should be used for during block of leaf state\n a = 0x1 << 2;\n }\n }\n state Yellow;\n state Green;\n [*] -> Red :: Start effect {\n b = 0x1;\n };\n Red -> Green effect {\n b = 0x3;\n };\n Green -> Yellow effect {\n b = 0x2;\n };\n Yellow -> Red : if [a >= 10] effect {\n b = 0x1;\n round_count = round_count + 1;\n };\n Green -> Yellow : /Idle.E2;\n Yellow -> Yellow : /E2;\n }\n state Idle;\n\n [*] -> InService;\n InService -> Idle :: Maintain;\n Idle -> Idle :: E2;\n Idle -> [*];\n}\n```\n\n* Generate Code With Given Template\n\n```shell\npyfcstm generate -i test_dsl_code.fcstm -t template_dir/ -o generated_code_dir/\n```\n\n### Use With Pythonic API\n\nYou can use this with pythonic API.\n\n```python\nfrom pyfcstm.dsl import parse_with_grammar_entry\nfrom pyfcstm.model.model import parse_dsl_node_to_state_machine\nfrom pyfcstm.render import StateMachineCodeRenderer\n\nif __name__ == '__main__':\n # Load AST Node From DSL Code\n ast_node = parse_with_grammar_entry(\"\"\"\n def int a = 0;\n def int b = 0x0;\n def int round_count = 0; // define variables\n state TrafficLight {\n state InService {\n enter {\n a = 0;\n b = 0;\n round_count = 0;\n }\n \n enter abstract InServiceAbstractEnter /*\n Abstract Operation When Entering State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n \n // for non-leaf state, either 'before' or 'after' aspect keyword should be used for during block\n during before abstract InServiceBeforeEnterChild /*\n Abstract Operation Before Entering Child States of State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n \n during after abstract InServiceAfterEnterChild /*\n Abstract Operation After Entering Child States of State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n \n exit abstract InServiceAbstractExit /*\n Abstract Operation When Leaving State 'InService'\n TODO: Should be Implemented In Generated Code Framework\n */\n \n state Red {\n during { // no aspect keywords ('before', 'after') should be used for during block of leaf state\n a = 0x1 << 2;\n }\n }\n state Yellow;\n state Green;\n [*] -> Red :: Start effect {\n b = 0x1;\n };\n Red -> Green effect {\n b = 0x3;\n };\n Green -> Yellow effect {\n b = 0x2;\n };\n Yellow -> Red : if [a >= 10] effect {\n b = 0x1;\n round_count = round_count + 1;\n };\n }\n state Idle;\n \n [*] -> InService;\n InService -> Idle :: Maintain;\n Idle -> [*];\n }\n \"\"\", entry_name='state_machine_dsl')\n # Load DSL Model From DSL AST Node\n model = parse_dsl_node_to_state_machine(ast_node)\n\n # Load Template Directory\n renderer = StateMachineCodeRenderer(\n template_dir='../fsm_generation_template'\n )\n # Render to Given Directory Via Template Directory\n renderer.render(model, 'test_output_x')\n```\n\nFor more information about this DSL,\nsee: [PyFCSTM DSL Syntax Tutorial](https://hansbug.github.io/pyfcstm/main/tutorials/dsl/index.html).\n",
"bugtrack_url": null,
"license": "GNU Lesser General Public License v3 (LGPLv3)",
"summary": "A Python framework for parsing finite state machine DSL and generating executable code in multiple target languages.",
"version": "0.1.2",
"project_urls": {
"Bug Reports": "https://github.com/hansbug/pyfcstm/issues",
"CI": "https://github.com/hansbug/pyfcstm/actions",
"Contributing": "https://github.com/hansbug/pyfcstm/blob/main/CONTRIBUTING.md",
"Coverage": "https://codecov.io/gh/hansbug/pyfcstm",
"Documentation": "https://hansbug.github.io/pyfcstm/",
"Download": "https://pypi.org/project/pyfcstm/#files",
"Homepage": "https://github.com/hansbug/pyfcstm",
"License": "https://github.com/hansbug/pyfcstm/blob/main/LICENSE",
"Pull Requests": "https://github.com/hansbug/pyfcstm/pulls",
"Source": "https://github.com/hansbug/pyfcstm",
"Wiki": "https://github.com/hansbug/pyfcstm/wiki"
},
"split_keywords": [
"state-machine",
" code-generation",
" compiler",
" template-engine",
" modelling"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "54464c49aeb5a118e2f7a7d2db41f8345464e5632ce0b23837361c0e84d0bb4b",
"md5": "dad4dcbe2ab8566e6bd6e658650b9864",
"sha256": "77e4e08c16785b42a3551eac498e41815bc5a87befa0eed50dee52f82c56776f"
},
"downloads": -1,
"filename": "pyfcstm-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "dad4dcbe2ab8566e6bd6e658650b9864",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 94488,
"upload_time": "2025-09-17T16:18:03",
"upload_time_iso_8601": "2025-09-17T16:18:03.611968Z",
"url": "https://files.pythonhosted.org/packages/54/46/4c49aeb5a118e2f7a7d2db41f8345464e5632ce0b23837361c0e84d0bb4b/pyfcstm-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "fcb77bd87cf405133685ed3d510a427d02e9969e1a4289bb2000635ed11c27af",
"md5": "630bb313159bb3deb0564fa19532b0c3",
"sha256": "d9b2f3683f3649f50ae0e5227791a5f8a5136265e8e8532cd57a201d0cc0822d"
},
"downloads": -1,
"filename": "pyfcstm-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "630bb313159bb3deb0564fa19532b0c3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 87959,
"upload_time": "2025-09-17T16:18:04",
"upload_time_iso_8601": "2025-09-17T16:18:04.755914Z",
"url": "https://files.pythonhosted.org/packages/fc/b7/7bd87cf405133685ed3d510a427d02e9969e1a4289bb2000635ed11c27af/pyfcstm-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-17 16:18:04",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hansbug",
"github_project": "pyfcstm",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "hbutils",
"specs": []
},
{
"name": "natsort",
"specs": []
},
{
"name": "cachetools",
"specs": []
},
{
"name": "pyyaml",
"specs": []
},
{
"name": "antlr4-python3-runtime",
"specs": [
[
"==",
"4.9.3"
]
]
},
{
"name": "jinja2",
"specs": [
[
">=",
"3"
]
]
},
{
"name": "unidecode",
"specs": []
},
{
"name": "pathspec",
"specs": []
},
{
"name": "click",
"specs": [
[
">=",
"8"
]
]
},
{
"name": "chardet",
"specs": []
}
],
"lcname": "pyfcstm"
}