11 stable releases (4 major)
Uses new Rust 2024
| 4.1.0 | Aug 16, 2025 |
|---|---|
| 4.0.0 | Aug 16, 2025 |
| 3.0.0 | Aug 9, 2025 |
| 2.1.0 | Jul 16, 2025 |
| 0.3.3 |
|
#311 in Programming languages
Used in stck-interpreter
200KB
5.5K
SLoC
A simple scripting language made to be embedded in other rust programs.
It's also made to be as simple as possible to parse and execute.
It's recommended usage is to import a standard libraby and make your own definitions for easier interoperability with the container software system. Then, before every run modify the stack to include that 'input' variables, and after executing the user's script, getting the stack values as output.
It's also possible to add rust bindings to be executable by user script
Execution pipeline
STCK has several modules for breaking up each important step, from reading files until executing the code
Tokenizer
Everything must begin with the tokenizer reading a string. It reads the content
character by character and arranges them in blocks of Tokens and specify
where their text is taken from within the string.
It is able to cluster character into:
| Token name | Description |
|---|---|
| Ident | Identifier of user function, builtin or function argument |
| Str | A string |
| Number | A positive natural number |
| Keyword | A raw keyword |
| FnArgs | Text within brackets |
| Block | Tokens within curly brackets |
| EndOfBlock | End of text or a closing curly bracket |
| IncludedBlock | Not created by tokenizer |
Preprocessor
The tokenizer and preprocessor work together to assemble all the tokens needed to evaluate the code.
The preprocessor's job is to search the original tokens for specific keyword,
like include and pragma and to modify the code or state accordingly.
When the preprocessor finds a pragma keyword it changes it's own state or
variables. Depending on the preprocessor's state it can ignore all other tokens
to enable conditional inclusion of code or safeguard against multiple
inclusions of the same files
When the preprocessor finds a include keyword, that file is read, tokenized
and it's tokens are included in a IncludedBlock token. However during the
preprocessing step of an included file, the pragma variables are passed down
to the included program's preprocessor. The included files' modifications to
pragma variables are also passed up to the file that included them
Parser
The parser is responsible for joining the tokens into executable expressions and updating their spans over their source files.
Technical detail
There are many tokens with implicit endings, like (ifs) who end with any non-code block token when searching for check blocks,
or (switch) tokens that end with tokens that aren't immediates or code blocks.
These tokens must add their parsed expression to the output and unget the last token, to re-parse it with a different state.
Execution
The expression executioner handles every runtime element and the definition of every builtin
The context of execution is preserved after all the code is ran. So it is possible to reuse the runtime::Context and even to utilize previously defined functions.
The recommended usage for context reusage is to send variables to STCK code as values in the stack and to clear the stack after every execution, since a faulty program could polute another's input.
Dependencies
~0–9MB
~47K SLoC