Metadata-Version: 2.1
Name: pyfcstm
Version: 0.1.0
Summary: A Python framework for parsing finite state machine DSL and generating executable code in multiple target languages.
Home-page: https://github.com/hansbug/pyfcstm
Author: HansBug
Author-email: hansbug@buaa.edu.cn
License: GNU Lesser General Public License v3 (LGPLv3)
Project-URL: Homepage, https://github.com/hansbug/pyfcstm
Project-URL: Documentation, https://hansbug.github.io/pyfcstm/
Project-URL: Source, https://github.com/hansbug/pyfcstm
Project-URL: Download, https://pypi.org/project/pyfcstm/#files
Project-URL: Bug Reports, https://github.com/hansbug/pyfcstm/issues
Project-URL: Contributing, https://github.com/hansbug/pyfcstm/blob/main/CONTRIBUTING.md
Project-URL: Pull Requests, https://github.com/hansbug/pyfcstm/pulls
Project-URL: CI, https://github.com/hansbug/pyfcstm/actions
Project-URL: Coverage, https://codecov.io/gh/hansbug/pyfcstm
Project-URL: Wiki, https://github.com/hansbug/pyfcstm/wiki
Project-URL: License, https://github.com/hansbug/pyfcstm/blob/main/LICENSE
Keywords: state-machine,code-generation,compiler,template-engine,modelling
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Manufacturing
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Software Development :: Compilers
Classifier: Topic :: Software Development :: Interpreters
Classifier: Topic :: Software Development :: Pre-processors
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Text Processing
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Topic :: Text Processing :: Markup
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: Utilities
Classifier: Topic :: Documentation
Classifier: Typing :: Typed
Classifier: Natural Language :: English
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: hbutils
Requires-Dist: natsort
Requires-Dist: cachetools
Requires-Dist: pyyaml
Requires-Dist: antlr4-python3-runtime==4.9.3
Requires-Dist: jinja2>=3
Requires-Dist: unidecode
Requires-Dist: pathspec
Requires-Dist: click>=8
Requires-Dist: chardet
Provides-Extra: doc
Requires-Dist: Jinja2>=3.0.0; extra == "doc"
Requires-Dist: sphinx>=3.2.0; extra == "doc"
Requires-Dist: sphinx_rtd_theme>=0.4.3; extra == "doc"
Requires-Dist: enum_tools>=0.9.0; extra == "doc"
Requires-Dist: sphinx-toolbox; extra == "doc"
Requires-Dist: plantumlcli>=0.0.2; extra == "doc"
Requires-Dist: packaging; extra == "doc"
Requires-Dist: sphinx-multiversion>=0.2.4; extra == "doc"
Requires-Dist: where>=1.0.2; extra == "doc"
Requires-Dist: easydict<2,>=1.7; extra == "doc"
Requires-Dist: responses>=0.20.0; extra == "doc"
Requires-Dist: natsort; extra == "doc"
Requires-Dist: nbsphinx>=0.8.8; extra == "doc"
Requires-Dist: ipython>=7.16.3; extra == "doc"
Requires-Dist: psutil>=5.8.0; extra == "doc"
Requires-Dist: ipykernel>=6.15; extra == "doc"
Requires-Dist: py-cpuinfo>=8.0.0; extra == "doc"
Requires-Dist: click>=7.0.0; extra == "doc"
Requires-Dist: pandas; extra == "doc"
Provides-Extra: build
Requires-Dist: pyinstaller>=4.7; extra == "build"
Requires-Dist: setuptools; extra == "build"
Requires-Dist: hbutils; extra == "build"
Provides-Extra: dev
Requires-Dist: ruff; extra == "dev"
Requires-Dist: antlr4-python3-runtime==4.9.3; extra == "dev"
Provides-Extra: test
Requires-Dist: coverage>=5; extra == "test"
Requires-Dist: mock>=4.0.3; extra == "test"
Requires-Dist: flake8>=3.5; extra == "test"
Requires-Dist: testfixtures>=6.18.5; extra == "test"
Requires-Dist: pytest>=6.2.5; extra == "test"
Requires-Dist: pytest-cov>=3.0.0; extra == "test"
Requires-Dist: pytest-mock>=3.6.1; extra == "test"
Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
Requires-Dist: pytest-rerunfailures>=10.2; extra == "test"
Requires-Dist: pytest-timeout>=2.0.2; extra == "test"
Requires-Dist: pytest-benchmark>=3.4.0; extra == "test"
Requires-Dist: easydict<2,>=1.7; extra == "test"
Requires-Dist: testtools>=2; extra == "test"
Requires-Dist: where>=1.0.2; extra == "test"
Requires-Dist: natsort; extra == "test"

# pyfcstm

[![PyPI](https://img.shields.io/pypi/v/pyfcstm)](https://pypi.org/project/pyfcstm/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pyfcstm)
![PyPI - Implementation](https://img.shields.io/pypi/implementation/pyfcstm)
![PyPI - Downloads](https://img.shields.io/pypi/dm/pyfcstm)

![Loc](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/HansBug/7eb8c32d6549edaa09592ca2a5a47187/raw/loc.json)
![Comments](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/HansBug/7eb8c32d6549edaa09592ca2a5a47187/raw/comments.json)
[![Maintainability](https://api.codeclimate.com/v1/badges/5b6e14a915b63faeae90/maintainability)](https://codeclimate.com/github/HansBug/pyfcstm/maintainability)
[![codecov](https://codecov.io/gh/hansbug/pyfcstm/graph/badge.svg?token=NYSTMMTC2F)](https://codecov.io/gh/hansbug/pyfcstm)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/HansBug/pyfcstm)

[![Docs Deploy](https://github.com/hansbug/pyfcstm/workflows/Docs%20Deploy/badge.svg)](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Docs+Deploy%22)
[![Code Test](https://github.com/hansbug/pyfcstm/workflows/Code%20Test/badge.svg)](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Code+Test%22)
[![Badge Creation](https://github.com/hansbug/pyfcstm/workflows/Badge%20Creation/badge.svg)](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Badge+Creation%22)
[![Package Release](https://github.com/hansbug/pyfcstm/workflows/Package%20Release/badge.svg)](https://github.com/hansbug/pyfcstm/actions?query=workflow%3A%22Package+Release%22)

[![GitHub stars](https://img.shields.io/github/stars/hansbug/pyfcstm)](https://github.com/hansbug/pyfcstm/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/hansbug/pyfcstm)](https://github.com/hansbug/pyfcstm/network)
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/hansbug/pyfcstm)
[![GitHub issues](https://img.shields.io/github/issues/hansbug/pyfcstm)](https://github.com/hansbug/pyfcstm/issues)
[![GitHub pulls](https://img.shields.io/github/issues-pr/hansbug/pyfcstm)](https://github.com/hansbug/pyfcstm/pulls)
[![Contributors](https://img.shields.io/github/contributors/hansbug/pyfcstm)](https://github.com/hansbug/pyfcstm/graphs/contributors)
[![GitHub license](https://img.shields.io/github/license/hansbug/pyfcstm)](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).
