Skip to content

Repository files navigation

FSMLang

A domain-specific language for defining and executing finite state machines.

Requirements

  • Python 3.8 or higher
  • No external dependencies — standard library only

Project Structure

fsmlang/
├── main.py # Entry point — run this
├── lexer.py # Tokenizer
├── ast_nodes.py # AST node definitions + printer
├── recursive_descent_parser.py # Recursive descent parser
├── example_programs/ # Valid example programs
│ ├── program1_traffic.fsm
│ ├── program2_vending.fsm
│ └── program3_gameai.fsm
└── malformed_programs/ # Programs with intentional errors
├── malformed1_no_initial.fsm
├── malformed2_bad_arrow.fsm
├── malformed3_no_machine_kw.fsm
├── malformed4_unclosed_brace.fsm
└── malformed5_invalid_token.fsm

Usage

# Parse a program and check for errors
python main.py <source_file># Parse and print the AST
python main.py <source_file> --dump-ast
# Show help
python main.py --help

Examples

# Parse the traffic light example
python main.py example_programs/program1_traffic.fsm
# Dump its AST
python main.py example_programs/program1_traffic.fsm --dump-ast
# See a parse error
python main.py malformed_programs/malformed1_no_initial.fsm

Language Overview

FSMLang programs consist of global variable declarations, machine definitions, and run statements.

// Global variable — accessible by all machines
int threshold = 10
machine MyMachine {
// Local variable — accessible only within this machine
int counter = 0
state Idle {
on_enter: output "Entering Idle"
on_step: counter = counter + 1
on_exit: output "Leaving Idle"
}
state Active {
on_enter: output "Now Active"
}
initial: Idle
transition Idle -> Active if counter > threshold
}
// Run for a fixed number of steps
run MyMachine for 20 steps
// Or run until Ctrl+C
// run MyMachine forever

State hooks

HookWhen it runs
on_enterOnce, when the machine enters this state
on_stepEvery step while this state is active (optional)
on_exitOnce, when the machine leaves this state

Transitions

Transitions fire when their guard expression evaluates to true. If no guard is given, the transition fires unconditionally on the next step.

transition StateA -> StateB if counter > 10
transition StateA -> StateB // unconditional

Run modes

run MyMachine for 100 steps // runs exactly 100 steps
run MyMachine forever // runs until Ctrl+C

Types

TypeExample
intint x = 0
floatfloat rate = 0.5
boolbool active = true
stringstring label = "hello"

Operators

CategoryOperators
Arithmetic+-*/
Comparison==!=<><=>=
Logicalandornot
Unary- (negation)

Error Messages

The lexer and parser produce informative error messages with line and column numbers.

[Lexer Error] Line 5, Col 12: Unexpected character '@'
[Parse Error] Line 8, Col 9: Machine 'A' has no 'initial' declaration
[Parse Error] Line 12, Col 20: Expected '->' but got '-'

About

A domain-specific language for defining and executing finite state machines.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages