mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-04 00:56:31 +02:00
Add proper docs
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
# YesNt
|
# YesNt
|
||||||
|
|
||||||
> YesNt is a imperative and interpreted language inspired by the Assembly language.
|
> YesNt is a imperative and interpreted language inspired by the Assembly language.
|
||||||
|
|
||||||
## Syntax
|
## Documentation
|
||||||
|
|
||||||
Current language syntax is documented in [SYNTAX_V2.md](SYNTAX_V2.md).
|
| Document | Description |
|
||||||
|
| -------------------------------------------------------- | ----------------------------------------- |
|
||||||
|
| [docs/README.md](docs/README.md) | Getting started |
|
||||||
|
| [docs/language-reference.md](docs/language-reference.md) | Full language reference |
|
||||||
|
| [docs/library-api.md](docs/library-api.md) | Embedding the interpreter as a C# library |
|
||||||
|
| [docs/editor.md](docs/editor.md) | Using the terminal code editor |
|
||||||
|
|
||||||
Example:
|
## Quick example
|
||||||
|
|
||||||
```ynt
|
```ynt
|
||||||
var name = world
|
var name = world
|
||||||
@@ -16,6 +21,5 @@ print_line Hello ${name}
|
|||||||
## Run
|
## Run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dotnet run --project YesNt.Interpreter -- path/to/script.ynt
|
dotnet run --project YesNt.Interpreter.App -- path/to/script.ynt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,14 @@ internal class InputHandler(TextEditor textEditor)
|
|||||||
textEditor.CursorPosition.X = textEditor.Lines.Count > textEditor.CursorPosition.Y ? textEditor.Lines[textEditor.CursorPosition.Y].TrimEnd().Length : 0;
|
textEditor.CursorPosition.X = textEditor.Lines.Count > textEditor.CursorPosition.Y ? textEditor.Lines[textEditor.CursorPosition.Y].TrimEnd().Length : 0;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case ConsoleKey.R:
|
||||||
|
ExecuteWithDebugScreen("run", false, false);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ConsoleKey.D:
|
||||||
|
ExecuteWithDebugScreen("debug", true, false);
|
||||||
|
return true;
|
||||||
|
|
||||||
case ConsoleKey.F:
|
case ConsoleKey.F:
|
||||||
textEditor.FormatLines();
|
textEditor.FormatLines();
|
||||||
textEditor.Display(true);
|
textEditor.Display(true);
|
||||||
@@ -352,6 +360,8 @@ internal class InputHandler(TextEditor textEditor)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mode previousMode = textEditor.EditMode;
|
||||||
|
|
||||||
textEditor.EditMode = Mode.Debug;
|
textEditor.EditMode = Mode.Debug;
|
||||||
textEditor.IsStepDebugMode = stepMode;
|
textEditor.IsStepDebugMode = stepMode;
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
@@ -373,6 +383,6 @@ internal class InputHandler(TextEditor textEditor)
|
|||||||
_ = Console.ReadKey();
|
_ = Console.ReadKey();
|
||||||
WriteStatus(string.Empty);
|
WriteStatus(string.Empty);
|
||||||
textEditor.IsStepDebugMode = false;
|
textEditor.IsStepDebugMode = false;
|
||||||
textEditor.EditMode = Mode.Command;
|
textEditor.EditMode = previousMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ internal static partial class Evaluator
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Evaluates a numeric arithmetic expression string and returns the result as a string.
|
/// Evaluates a numeric arithmetic expression string and returns the result as a string.
|
||||||
/// Supports <c>+</c>, <c>-</c>, <c>*</c>, and <c>/</c> operators.
|
/// Supports <c>+</c>, <c>-</c>, <c>*</c>, <c>/</c>, <c>%</c> (modulo), and <c>^</c> (power) operators
|
||||||
|
/// with standard precedence (<c>^</c> highest, <c>+</c>/<c>-</c> lowest) and parentheses.
|
||||||
/// Adjacent sign characters (<c>++</c>, <c>--</c>, <c>-+</c>, <c>+-</c>) are normalised before evaluation.
|
/// Adjacent sign characters (<c>++</c>, <c>--</c>, <c>-+</c>, <c>+-</c>) are normalised before evaluation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">The arithmetic expression to evaluate.</param>
|
/// <param name="input">The arithmetic expression to evaluate.</param>
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# YesNt Documentation
|
||||||
|
|
||||||
|
YesNt is a line-based, interpreted scripting language inspired by assembly.
|
||||||
|
Each line is one statement. There are no multi-line expressions.
|
||||||
|
|
||||||
|
## Guides
|
||||||
|
|
||||||
|
| Document | Description |
|
||||||
|
| ------------------------------------------- | ---------------------------------------------------- |
|
||||||
|
| [Language Reference](language-reference.md) | Every statement, token, and operator in the language |
|
||||||
|
| [Library API](library-api.md) | How to embed the interpreter in a C# project |
|
||||||
|
| [Editor](editor.md) | How to use the terminal code editor |
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
### Running a script from the command line
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet run --project YesNt.Interpreter.App -- path/to/script.ynt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hello world
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print_line Hello, world!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables and output
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var name = Alice
|
||||||
|
print_line Hello, ${name}!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Functions
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
func greet:
|
||||||
|
var msg = Hello, ${name}!
|
||||||
|
print_line ${msg}
|
||||||
|
return
|
||||||
|
|
||||||
|
var name = Bob
|
||||||
|
call greet
|
||||||
|
```
|
||||||
|
|
||||||
|
Script files use the `.ynt` extension by convention.
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# YesNt Code Editor
|
||||||
|
|
||||||
|
`YesNt.CodeEditor` is a terminal editor for writing, formatting, running, and debugging YesNt scripts.
|
||||||
|
|
||||||
|
## Start the editor
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet run --project YesNt.CodeEditor -- [optional-path-to-file.ynt]
|
||||||
|
```
|
||||||
|
|
||||||
|
If you pass a file path, it is loaded on startup.
|
||||||
|
|
||||||
|
## Modes
|
||||||
|
|
||||||
|
- **Command mode:** enter editor commands in the `>>>` prompt.
|
||||||
|
- **Edit mode:** direct text editing with keyboard navigation.
|
||||||
|
- **Debug mode:** script output/debug information while running.
|
||||||
|
|
||||||
|
## Command mode commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| --------------------- | --------------------------------------------------------- |
|
||||||
|
| `edit` | Switch to edit mode |
|
||||||
|
| `line <n>` | Jump to line `n` and switch to edit mode |
|
||||||
|
| `save [path]` | Save to current path or a new path |
|
||||||
|
| `load <path>` | Load a file |
|
||||||
|
| `new` | Create new file |
|
||||||
|
| `format` | Auto-format indentation |
|
||||||
|
| `run [path]` | Run script |
|
||||||
|
| `debug [path] [step]` | Run in debug mode (`step` enables step-by-step execution) |
|
||||||
|
| `exit` | Close the editor |
|
||||||
|
|
||||||
|
## Edit mode controls
|
||||||
|
|
||||||
|
- Arrow keys: move cursor
|
||||||
|
- Enter: split line
|
||||||
|
- Backspace/Delete: remove characters/merge lines
|
||||||
|
- **Alt+C:** return to command mode
|
||||||
|
- **Alt+T:** jump to top
|
||||||
|
- **Alt+B:** jump to bottom
|
||||||
|
- **Alt+S:** jump to start of line
|
||||||
|
- **Alt+E:** jump to end of line
|
||||||
|
- **Alt+R:** run script
|
||||||
|
- **Alt+D:** run debug mode
|
||||||
|
- **Alt+F:** format current file
|
||||||
|
|
||||||
|
## Formatter behavior (quick summary)
|
||||||
|
|
||||||
|
- Indents `func`, `if`, `else`, and `while` blocks.
|
||||||
|
- Dedents on `return`, `end_if`, and `end_while`.
|
||||||
|
- `exit` / `throw` / `error` close active non-function blocks for following lines.
|
||||||
|
- Comment lines (`# ...`) are kept unindented.
|
||||||
@@ -0,0 +1,811 @@
|
|||||||
|
# YesNt Language Reference
|
||||||
|
|
||||||
|
YesNt is a line-based scripting language. Every non-empty, non-comment line is one statement.
|
||||||
|
Execution proceeds top-to-bottom unless a control-flow statement changes the line counter.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
1. [Basic rules](#basic-rules)
|
||||||
|
2. [Comments](#comments)
|
||||||
|
3. [String literals](#string-literals)
|
||||||
|
4. [Variables](#variables)
|
||||||
|
5. [Console I/O](#console-io)
|
||||||
|
6. [Arithmetic](#arithmetic)
|
||||||
|
7. [Conditions](#conditions)
|
||||||
|
8. [Control flow](#control-flow)
|
||||||
|
9. [Functions](#functions)
|
||||||
|
10. [Lists](#lists)
|
||||||
|
11. [Processing](#processing)
|
||||||
|
12. [System](#system)
|
||||||
|
13. [Predefined tokens](#predefined-tokens)
|
||||||
|
14. [Termination](#termination)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Basic rules
|
||||||
|
|
||||||
|
- Lines are trimmed of leading and trailing whitespace before execution.
|
||||||
|
- Blank lines are silently skipped.
|
||||||
|
- Lines starting with `#` are comments and are silently skipped.
|
||||||
|
- Variable interpolation uses `${name}` and is evaluated before the statement runs.
|
||||||
|
- Special characters inside string literals are encoded internally and decoded on output — this is transparent to scripts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
# This is a comment.
|
||||||
|
print_line Hello # inline comments are NOT supported — everything after print_line is the argument
|
||||||
|
```
|
||||||
|
|
||||||
|
Only whole-line comments (lines whose first non-whitespace character is `#`) are supported.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## String literals
|
||||||
|
|
||||||
|
Double-quoted strings protect their content from keyword matching and allow escape sequences.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print_line "Hello, world!"
|
||||||
|
print_line "Line one\nLine two"
|
||||||
|
print_line "She said \"hi\""
|
||||||
|
```
|
||||||
|
|
||||||
|
| Escape | Meaning |
|
||||||
|
| ------ | -------------------- |
|
||||||
|
| `\n` | Newline |
|
||||||
|
| `\r` | Carriage return |
|
||||||
|
| `\t` | Horizontal tab |
|
||||||
|
| `\"` | Literal double-quote |
|
||||||
|
| `\\` | Literal backslash |
|
||||||
|
|
||||||
|
Variable interpolation (`${name}`) is **not** evaluated inside string literals — the braces
|
||||||
|
and content are passed through verbatim.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var x = world
|
||||||
|
print_line "${x}" # prints the literal text: ${x}
|
||||||
|
print_line "hello " ${x} # prints: hello world (interpolation outside the literal)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
### Local variables — `var`
|
||||||
|
|
||||||
|
```
|
||||||
|
var <name> = <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Defines or updates a variable scoped to the current function (or the top level if called outside a function).
|
||||||
|
The value is everything after `=`, trimmed.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var count = 0
|
||||||
|
var greeting = Hello, world!
|
||||||
|
```
|
||||||
|
|
||||||
|
Variable names may only contain letters and digits (`[a-zA-Z0-9]`).
|
||||||
|
|
||||||
|
### Global variables — `global`
|
||||||
|
|
||||||
|
```
|
||||||
|
global <name> = <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Defines or updates a variable that is visible across all function scopes and background tasks.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
global total = 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reading a variable — `${name}`
|
||||||
|
|
||||||
|
`${name}` is an inline token that is replaced with the variable's value before the statement executes.
|
||||||
|
It can appear anywhere in a line and multiple occurrences are replaced left to right.
|
||||||
|
Local variables are checked first; if not found, the global table is checked.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var a = 5
|
||||||
|
var b = 10
|
||||||
|
print_line ${a} plus ${b}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deleting a variable — `delete`
|
||||||
|
|
||||||
|
```
|
||||||
|
delete <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes the variable. Local scope is checked first; if not found, the global table is used.
|
||||||
|
Raises an error if the variable does not exist in either scope.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var temp = scratch
|
||||||
|
delete temp
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Console I/O
|
||||||
|
|
||||||
|
### Print with newline — `print_line`
|
||||||
|
|
||||||
|
```
|
||||||
|
print_line <text>
|
||||||
|
print_line
|
||||||
|
```
|
||||||
|
|
||||||
|
Writes `<text>` followed by a newline. With no argument, writes a blank line.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print_line Hello!
|
||||||
|
print_line
|
||||||
|
print_line Done.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Print without newline — `print`
|
||||||
|
|
||||||
|
```
|
||||||
|
print <text>
|
||||||
|
```
|
||||||
|
|
||||||
|
Writes `<text>` without a trailing newline.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print Enter your name:
|
||||||
|
var name = %read_line
|
||||||
|
print_line Hello, ${name}!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read a line of input — `%read_line`
|
||||||
|
|
||||||
|
`%read_line` is an inline token that is replaced with one line of text read from standard input.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var answer = %read_line
|
||||||
|
print_line You typed: ${answer}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read a single key — `%read_key`
|
||||||
|
|
||||||
|
`%read_key` is an inline token that is replaced with the single character pressed by the user (no Enter required).
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print Press any key...
|
||||||
|
var key = %read_key
|
||||||
|
print_line You pressed: ${key}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clear the console — `clear`
|
||||||
|
|
||||||
|
```
|
||||||
|
clear
|
||||||
|
```
|
||||||
|
|
||||||
|
Clears the console window.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arithmetic
|
||||||
|
|
||||||
|
Arithmetic is a **postfix** modifier applied at the end of a line with the `calc` keyword.
|
||||||
|
|
||||||
|
```
|
||||||
|
<expression> calc
|
||||||
|
```
|
||||||
|
|
||||||
|
Any numeric sub-expression matching the pattern `number op number [op number …]` is evaluated
|
||||||
|
and replaced with the result. Supported operators (highest to lowest precedence):
|
||||||
|
|
||||||
|
| Operator | Operation |
|
||||||
|
| -------- | ----------------------------- |
|
||||||
|
| `(…)` | Parentheses (evaluated first) |
|
||||||
|
| `^` | Exponentiation |
|
||||||
|
| `%` | Modulo |
|
||||||
|
| `/` | Division |
|
||||||
|
| `*` | Multiplication |
|
||||||
|
| `-` | Subtraction |
|
||||||
|
| `+` | Addition (lowest precedence) |
|
||||||
|
|
||||||
|
Adjacent sign characters (`++`, `--`, `-+`, `+-`) are normalised before evaluation.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var x = 3
|
||||||
|
var y = 4
|
||||||
|
var sum = ${x} + ${y} calc # 7
|
||||||
|
var expr = 2 + 3 * 4 calc # 14 (* before +)
|
||||||
|
var parens = (2 + 3) * 4 calc # 20
|
||||||
|
var power = 2 ^ 10 calc # 1024
|
||||||
|
var remainder = 17 % 5 calc # 2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conditions
|
||||||
|
|
||||||
|
Conditions are used in `if` and `while` statements. A condition is a string of the form:
|
||||||
|
|
||||||
|
```
|
||||||
|
<left> <operator> <right>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Operator | Meaning |
|
||||||
|
| -------- | --------------------------------------------- |
|
||||||
|
| `==` | Equal (string comparison, case-sensitive) |
|
||||||
|
| `!=` | Not equal (string comparison, case-sensitive) |
|
||||||
|
| `<` | Less than (numeric) |
|
||||||
|
| `>` | Greater than (numeric) |
|
||||||
|
| `<=` | Less than or equal (numeric) |
|
||||||
|
| `>=` | Greater than or equal (numeric) |
|
||||||
|
|
||||||
|
Numeric comparisons (`<`, `>`, `<=`, `>=`) parse both sides with
|
||||||
|
culture-invariant decimal rules (`.` or `,` as decimal separator).
|
||||||
|
|
||||||
|
A bare value of `True` or `False` (case-insensitive) is also a valid condition.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var x = 10
|
||||||
|
if ${x} > 5:
|
||||||
|
print_line x is greater than 5
|
||||||
|
end_if
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Control flow
|
||||||
|
|
||||||
|
### If / else / end_if
|
||||||
|
|
||||||
|
```
|
||||||
|
if <condition>:
|
||||||
|
<body>
|
||||||
|
else:
|
||||||
|
<alternative>
|
||||||
|
end_if
|
||||||
|
```
|
||||||
|
|
||||||
|
`else:` is optional. `if` / `else:` / `end_if` blocks can be nested.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var score = 75
|
||||||
|
if ${score} >= 60:
|
||||||
|
print_line Pass
|
||||||
|
else:
|
||||||
|
print_line Fail
|
||||||
|
end_if
|
||||||
|
```
|
||||||
|
|
||||||
|
### While loop
|
||||||
|
|
||||||
|
```
|
||||||
|
while <condition>:
|
||||||
|
<body>
|
||||||
|
end_while
|
||||||
|
```
|
||||||
|
|
||||||
|
The condition is checked before each iteration. `while` / `end_while` blocks can be nested.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var i = 1
|
||||||
|
while ${i} <= 5:
|
||||||
|
print_line ${i}
|
||||||
|
var i = ${i} + 1 calc
|
||||||
|
end_while
|
||||||
|
```
|
||||||
|
|
||||||
|
### Labels and goto
|
||||||
|
|
||||||
|
```
|
||||||
|
label <name>:
|
||||||
|
goto <name>
|
||||||
|
```
|
||||||
|
|
||||||
|
`label` marks a target. `goto` performs an unconditional jump to that label.
|
||||||
|
Labels are scoped to the current function; you cannot jump to a label outside the calling function.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
label loop:
|
||||||
|
print_line tick
|
||||||
|
goto loop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional goto
|
||||||
|
|
||||||
|
```
|
||||||
|
if <condition> goto <label>
|
||||||
|
```
|
||||||
|
|
||||||
|
Jumps to `<label>` only when the condition is true.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var n = 0
|
||||||
|
label start:
|
||||||
|
var n = ${n} + 1 calc
|
||||||
|
if ${n} < 10 goto start
|
||||||
|
print_line done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional function call
|
||||||
|
|
||||||
|
```
|
||||||
|
if <condition> call <function>
|
||||||
|
```
|
||||||
|
|
||||||
|
Calls `<function>` only when the condition is true.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var debug = True
|
||||||
|
if ${debug} == True call dump_state
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
### Declaring a function — `func`
|
||||||
|
|
||||||
|
```
|
||||||
|
func <name>:
|
||||||
|
<body>
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
|
A function declaration registers the function name and the line it starts on.
|
||||||
|
The body runs until `return` is reached.
|
||||||
|
**Nested function declarations are not allowed.**
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
func add:
|
||||||
|
var result = %in + %in calc
|
||||||
|
push_out ${result}
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
|
### Calling a function — `call`
|
||||||
|
|
||||||
|
```
|
||||||
|
call <name>
|
||||||
|
call <name> with <arg1>, <arg2>, …
|
||||||
|
```
|
||||||
|
|
||||||
|
`call` without `with` uses any values previously pushed with `push_in`.
|
||||||
|
`call … with …` pushes the comma-separated arguments and then calls the function.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
call greet
|
||||||
|
call add with 3, 7
|
||||||
|
```
|
||||||
|
|
||||||
|
### Input arguments
|
||||||
|
|
||||||
|
#### Push an input argument — `push_in`
|
||||||
|
|
||||||
|
```
|
||||||
|
push_in <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Pushes a value onto the input argument stack. Values are consumed in the order they were pushed —
|
||||||
|
the first `push_in` call is the first value consumed by `%in` inside the function.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
push_in Alice
|
||||||
|
call greet
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Pop the next input argument — `%in`
|
||||||
|
|
||||||
|
`%in` is an inline token (only valid inside a function) that is replaced with the next value
|
||||||
|
popped from the argument stack.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
func greet:
|
||||||
|
var name = %in
|
||||||
|
print_line Hello, ${name}!
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Check if input argument exists — `%has_in`
|
||||||
|
|
||||||
|
`%has_in` is replaced with `True` or `False` depending on whether the input stack is non-empty.
|
||||||
|
Only valid inside a function.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
func greet:
|
||||||
|
if %has_in == True call do_greet
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output values
|
||||||
|
|
||||||
|
#### Push an output value — `push_out`
|
||||||
|
|
||||||
|
```
|
||||||
|
push_out <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Only valid inside a function. Pushes a return value onto the output stack.
|
||||||
|
|
||||||
|
#### Consume an output value — `%out`
|
||||||
|
|
||||||
|
`%out` is an inline token that pops and inserts the top value from the output stack.
|
||||||
|
Valid anywhere after a function call or list/processing statement that pushes to the output stack.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
call add with 3, 7
|
||||||
|
var total = %out
|
||||||
|
print_line ${total}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Check if output value exists — `%has_out`
|
||||||
|
|
||||||
|
`%has_out` is replaced with `True` or `False` depending on whether the output stack is non-empty.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
call maybe_produce
|
||||||
|
if %has_out == True call consume_result
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clear the call stack — `clear_call_stack`
|
||||||
|
|
||||||
|
```
|
||||||
|
clear_call_stack
|
||||||
|
```
|
||||||
|
|
||||||
|
Discards all frames on the function call stack. Useful for error recovery.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lists
|
||||||
|
|
||||||
|
Lists are ordered, mutable sequences of strings. All list operations start with the keyword `list`.
|
||||||
|
|
||||||
|
### Create or reset — `list … new`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> new
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates an empty list. If the list already exists it is cleared.
|
||||||
|
|
||||||
|
### Add an item — `list … add`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> add <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Appends `<value>` to the end of the list.
|
||||||
|
|
||||||
|
### Get an item — `list … get`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> get <index>
|
||||||
|
```
|
||||||
|
|
||||||
|
Pushes the item at zero-based `<index>` onto the output stack. Access it with `%out`.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
list fruits new
|
||||||
|
list fruits add apple
|
||||||
|
list fruits add banana
|
||||||
|
list fruits get 0
|
||||||
|
var first = %out
|
||||||
|
print_line ${first}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set an item — `list … set`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> set <index> <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Replaces the item at `<index>` with `<value>`.
|
||||||
|
|
||||||
|
### Remove an item — `list … remove`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> remove <index>
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes the item at `<index>`. Subsequent items shift down.
|
||||||
|
|
||||||
|
### Insert an item — `list … insert`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> insert <index> <value>
|
||||||
|
```
|
||||||
|
|
||||||
|
Inserts `<value>` before position `<index>`.
|
||||||
|
|
||||||
|
### Get the length — `list … length`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> length
|
||||||
|
```
|
||||||
|
|
||||||
|
Pushes the number of items onto the output stack.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
list fruits length
|
||||||
|
var n = %out
|
||||||
|
print_line ${n} items
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clear all items — `list … clear`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> clear
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes all items but keeps the list alive.
|
||||||
|
|
||||||
|
### Delete a list — `list … delete`
|
||||||
|
|
||||||
|
```
|
||||||
|
list <name> delete
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes the list entirely.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Processing
|
||||||
|
|
||||||
|
### Arithmetic — `calc`
|
||||||
|
|
||||||
|
See [Arithmetic](#arithmetic).
|
||||||
|
|
||||||
|
### Decode a safe string — `eval`
|
||||||
|
|
||||||
|
```
|
||||||
|
<expression> eval
|
||||||
|
```
|
||||||
|
|
||||||
|
Decodes any internally-encoded characters in the current line back to their plain-text form.
|
||||||
|
Useful after producing text from string literal operations that you want to re-use as plain text.
|
||||||
|
|
||||||
|
### Run from the current line in a background task — `task`
|
||||||
|
|
||||||
|
```
|
||||||
|
<line> task
|
||||||
|
```
|
||||||
|
|
||||||
|
Starts a background interpreter from the current line. In that background run, the current line is
|
||||||
|
executed without the trailing `task`, and execution then continues through the remaining lines.
|
||||||
|
The main script continues immediately. The task shares the global variable table with the main script.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print_line Starting background work... task
|
||||||
|
print_line Main thread continues.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Important behavior
|
||||||
|
|
||||||
|
- `task` does **not** run just one statement; it starts a second execution flow from that point onward.
|
||||||
|
- Without careful control flow, lines after the `task` statement may run twice:
|
||||||
|
once on the main thread and once in the background task.
|
||||||
|
- Global variables are shared between both flows.
|
||||||
|
|
||||||
|
#### Recommended pattern
|
||||||
|
|
||||||
|
Use a direct function call with `task`, and terminate inside that function with `exit`.
|
||||||
|
This keeps the worker logic isolated and avoids `goto` scaffolding.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
call background_job task
|
||||||
|
print_line Main thread keeps going
|
||||||
|
|
||||||
|
func background_job:
|
||||||
|
print_line Work in background
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
This works well for task-only worker flows. In non-task/shared flows, prefer `return` if you want
|
||||||
|
to return to the caller instead of terminating that execution flow with `exit`.
|
||||||
|
|
||||||
|
### Sleep — `sleep`
|
||||||
|
|
||||||
|
```
|
||||||
|
sleep <milliseconds>
|
||||||
|
```
|
||||||
|
|
||||||
|
Pauses execution for the given number of milliseconds. Respects cancellation: if the script is
|
||||||
|
stopped (e.g. via `abort_all` from another task), `sleep` returns early.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
sleep 1000
|
||||||
|
print_line One second later.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get string length — `length`
|
||||||
|
|
||||||
|
```
|
||||||
|
length <text>
|
||||||
|
```
|
||||||
|
|
||||||
|
Pushes the character count of `<text>` onto the output stack.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
length Hello, world!
|
||||||
|
var len = %out
|
||||||
|
print_line ${len}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import another script — `import`
|
||||||
|
|
||||||
|
```
|
||||||
|
import <path>
|
||||||
|
```
|
||||||
|
|
||||||
|
Inlines the contents of another `.ynt` file at the current position.
|
||||||
|
The extension `.ynt` is appended automatically if omitted.
|
||||||
|
The path is resolved relative to the directory of the importing script.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
import utils
|
||||||
|
import lib/math.ynt
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## System
|
||||||
|
|
||||||
|
### Execute a program — `exec`
|
||||||
|
|
||||||
|
```
|
||||||
|
exec <program>
|
||||||
|
exec <program> with <arg1>, <arg2>, …
|
||||||
|
```
|
||||||
|
|
||||||
|
Runs an external program and waits for it to finish.
|
||||||
|
Standard output and standard error are forwarded to the console in real time.
|
||||||
|
The exit code and each line of output are pushed onto the output stack (exit code on top).
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
exec notepad
|
||||||
|
exec git with status, --short
|
||||||
|
var exit_code = %out
|
||||||
|
print_line Exited with ${exit_code}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also stage arguments with `push_in` before a bare `exec`:
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
push_in --version
|
||||||
|
exec python
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Predefined tokens
|
||||||
|
|
||||||
|
These inline tokens are replaced with their value before the statement executes.
|
||||||
|
|
||||||
|
| Token | Replaced with |
|
||||||
|
| ------- | --------------------------------------------------- |
|
||||||
|
| `%time` | Current Unix timestamp (seconds) |
|
||||||
|
| `%os` | Operating system platform name (e.g. `Win32NT`) |
|
||||||
|
| `%cpu` | Processor architecture (e.g. `X64`) |
|
||||||
|
| `%is64` | `True` if the OS is 64-bit, otherwise `False` |
|
||||||
|
| `%pi` | The value of π |
|
||||||
|
| `%rand` | A random integer in the range `[32767, 2147483647)` |
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
print_line Time: %time
|
||||||
|
print_line OS: %os
|
||||||
|
print_line PI: %pi
|
||||||
|
var roll = %rand
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Termination
|
||||||
|
|
||||||
|
### Normal exit — `exit`
|
||||||
|
|
||||||
|
```
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
Terminates the script gracefully. Background tasks that are still running are not cancelled.
|
||||||
|
|
||||||
|
### Exit and cancel all tasks — `abort_all`
|
||||||
|
|
||||||
|
```
|
||||||
|
abort_all
|
||||||
|
```
|
||||||
|
|
||||||
|
Terminates the script and signals all background tasks to stop.
|
||||||
|
|
||||||
|
### Throw an error — `throw`
|
||||||
|
|
||||||
|
```
|
||||||
|
throw <message>
|
||||||
|
```
|
||||||
|
|
||||||
|
Terminates the script and all tasks with `<message>` as the error description.
|
||||||
|
A stack trace is printed showing the line and file where the error occurred.
|
||||||
|
|
||||||
|
```ynt
|
||||||
|
var x = -1
|
||||||
|
if ${x} < 0 call validate_fail
|
||||||
|
|
||||||
|
func validate_fail:
|
||||||
|
throw x must not be negative
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
|
### Non-fatal error — `error`
|
||||||
|
|
||||||
|
```
|
||||||
|
error <message>
|
||||||
|
```
|
||||||
|
|
||||||
|
Like `throw` but does **not** cancel background tasks.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Full statement reference
|
||||||
|
|
||||||
|
| Statement | Form | Description |
|
||||||
|
| ------------------ | ------------------------------ | ------------------------------------------------------------ |
|
||||||
|
| `var` | `var name = value` | Define/update local variable |
|
||||||
|
| `global` | `global name = value` | Define/update global variable |
|
||||||
|
| `delete` | `delete name` | Delete variable |
|
||||||
|
| `print_line` | `print_line [text]` | Print line (optional text) |
|
||||||
|
| `print` | `print text` | Print without newline |
|
||||||
|
| `clear` | `clear` | Clear console |
|
||||||
|
| `if … :` | `if cond:` | Start conditional block |
|
||||||
|
| `else:` | `else:` | Else branch |
|
||||||
|
| `end_if` | `end_if` | End conditional block |
|
||||||
|
| `while … :` | `while cond:` | Start while loop |
|
||||||
|
| `end_while` | `end_while` | End while loop |
|
||||||
|
| `label` | `label name:` | Declare a jump target |
|
||||||
|
| `goto` | `goto name` | Unconditional jump |
|
||||||
|
| `if … goto` | `if cond goto name` | Conditional jump |
|
||||||
|
| `func` | `func name:` | Declare a function |
|
||||||
|
| `call` | `call name` | Call a function |
|
||||||
|
| `call … with` | `call name with a, b` | Call a function with arguments |
|
||||||
|
| `if … call` | `if cond call name` | Conditional function call |
|
||||||
|
| `push_in` | `push_in value` | Push input argument |
|
||||||
|
| `push_out` | `push_out value` | Push output value (inside function) |
|
||||||
|
| `return` | `return` | Return from function |
|
||||||
|
| `clear_call_stack` | `clear_call_stack` | Clear call stack |
|
||||||
|
| `list … new` | `list name new` | Create/reset list |
|
||||||
|
| `list … add` | `list name add value` | Append to list |
|
||||||
|
| `list … get` | `list name get index` | Get item → `%out` |
|
||||||
|
| `list … set` | `list name set index value` | Replace item |
|
||||||
|
| `list … remove` | `list name remove index` | Remove item |
|
||||||
|
| `list … insert` | `list name insert index value` | Insert item |
|
||||||
|
| `list … length` | `list name length` | Get count → `%out` |
|
||||||
|
| `list … clear` | `list name clear` | Clear all items |
|
||||||
|
| `list … delete` | `list name delete` | Delete list |
|
||||||
|
| `calc` | `expr calc` | Evaluate arithmetic |
|
||||||
|
| `eval` | `expr eval` | Decode string encoding |
|
||||||
|
| `task` | `line task` | Run current line (without `task`) and continue in background |
|
||||||
|
| `sleep` | `sleep ms` | Sleep N milliseconds |
|
||||||
|
| `length` | `length text` | Get char count → `%out` |
|
||||||
|
| `import` | `import path` | Inline-include a `.ynt` file |
|
||||||
|
| `exec` | `exec prog` | Run external program |
|
||||||
|
| `exec … with` | `exec prog with a, b` | Run external program with args |
|
||||||
|
| `exit` | `exit` | Graceful exit |
|
||||||
|
| `abort_all` | `abort_all` | Exit and cancel all tasks |
|
||||||
|
| `throw` | `throw message` | Fatal error (cancels all tasks) |
|
||||||
|
| `error` | `error message` | Non-fatal error |
|
||||||
|
| `%read_line` | inline | Insert one line of user input |
|
||||||
|
| `%read_key` | inline | Insert one keypress |
|
||||||
|
| `%in` | inline | Pop next function input argument |
|
||||||
|
| `%has_in` | inline | `True`/`False` if input stack non-empty |
|
||||||
|
| `%out` | inline | Pop top output value |
|
||||||
|
| `%has_out` | inline | `True`/`False` if output stack non-empty |
|
||||||
|
| `%time` | inline | Unix timestamp |
|
||||||
|
| `%os` | inline | OS platform |
|
||||||
|
| `%cpu` | inline | Processor architecture |
|
||||||
|
| `%is64` | inline | `True` if 64-bit OS |
|
||||||
|
| `%pi` | inline | Value of π |
|
||||||
|
| `%rand` | inline | Random integer |
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
# YesNt Library API
|
||||||
|
|
||||||
|
The `YesNt.Interpreter` project is a .NET 8 class library. You can reference it from any C# project
|
||||||
|
to embed the YesNt interpreter and run scripts programmatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
1. [Adding the reference](#adding-the-reference)
|
||||||
|
2. [Running a script file](#running-a-script-file)
|
||||||
|
3. [Running an in-memory script](#running-an-in-memory-script)
|
||||||
|
4. [Capturing output (debug mode)](#capturing-output-debug-mode)
|
||||||
|
5. [Adding custom statements](#adding-custom-statements)
|
||||||
|
6. [Stopping a script](#stopping-a-script)
|
||||||
|
7. [Reading registered statements](#reading-registered-statements)
|
||||||
|
8. [API reference](#api-reference)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Adding the reference
|
||||||
|
|
||||||
|
Add a project reference to `YesNt.Interpreter` in your `.csproj`:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\YesNt.Interpreter\YesNt.Interpreter.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
```
|
||||||
|
|
||||||
|
Then add the using directive:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using YesNt.Interpreter.Runtime;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Running a script file
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var interpreter = new YesNtInterpreter();
|
||||||
|
interpreter.Execute("path/to/script.ynt");
|
||||||
|
```
|
||||||
|
|
||||||
|
`Execute` is synchronous - it returns when the script finishes (or terminates with an error).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Running an in-memory script
|
||||||
|
|
||||||
|
Supply a `List<string>` instead of a file path:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var lines = new List<string>
|
||||||
|
{
|
||||||
|
"var x = 42",
|
||||||
|
"print_line The answer is ${x}",
|
||||||
|
};
|
||||||
|
|
||||||
|
var interpreter = new YesNtInterpreter();
|
||||||
|
interpreter.Execute(lines);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Capturing output (debug mode)
|
||||||
|
|
||||||
|
Pass `isDebugMode: true` to suppress direct console writes. Output is delivered through the
|
||||||
|
`OnDebugOutput` event instead, and `OnLineExecuted` fires after executed lines.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var interpreter = new YesNtInterpreter();
|
||||||
|
var output = new System.Text.StringBuilder();
|
||||||
|
|
||||||
|
interpreter.OnDebugOutput += text => output.Append(text);
|
||||||
|
interpreter.OnLineExecuted += args =>
|
||||||
|
{
|
||||||
|
if (args is null)
|
||||||
|
{
|
||||||
|
// null means execution reached end-of-file (EOF)
|
||||||
|
Console.WriteLine("Script reached EOF.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Console.WriteLine($"Line {args.LineNumber}: {args.CurrentLine}");
|
||||||
|
};
|
||||||
|
|
||||||
|
interpreter.Execute(new List<string> { "print_line hello" }, isDebugMode: true);
|
||||||
|
Console.Write(output);
|
||||||
|
```
|
||||||
|
|
||||||
|
`OnLineExecuted` receives a `DebugEventArgs` with:
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| -------------- | -------- | ------------------------------------------- |
|
||||||
|
| `LineNumber` | `int` | 1-based line number |
|
||||||
|
| `OriginalLine` | `string` | Raw source text |
|
||||||
|
| `CurrentLine` | `string` | Text after all substitutions |
|
||||||
|
| `IsTask` | `bool` | `true` if executed inside a background task |
|
||||||
|
| `TaskId` | `int` | Task identifier (0 for the main thread) |
|
||||||
|
|
||||||
|
`OnLineExecuted` is invoked with `null` only when execution reaches end-of-file (EOF).
|
||||||
|
If execution stops via `exit`, `throw`, `error`, or `Stop()`, no terminal `null` event is emitted.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Adding custom statements
|
||||||
|
|
||||||
|
Use `AddStatement` to register keywords before calling `Execute`.
|
||||||
|
|
||||||
|
### Simple keyword at the start of a line
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using YesNt.Interpreter.Enums;
|
||||||
|
|
||||||
|
var interpreter = new YesNtInterpreter();
|
||||||
|
|
||||||
|
interpreter.AddStatement("log", SearchMode.StartOfLine, SpaceAround.End, args =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[LOG] {args}");
|
||||||
|
});
|
||||||
|
|
||||||
|
interpreter.Execute(new List<string> { "log Hello from custom statement" });
|
||||||
|
```
|
||||||
|
|
||||||
|
### With a syntax-highlight colour
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
interpreter.AddStatement("log", SearchMode.StartOfLine, SpaceAround.End,
|
||||||
|
ConsoleColor.Cyan,
|
||||||
|
args => Console.WriteLine($"[LOG] {args}"));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using a pre-built `StatementAttribute`
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using YesNt.Interpreter.Attributes;
|
||||||
|
|
||||||
|
var attr = new StatementAttribute("log", SearchMode.StartOfLine, SpaceAround.End)
|
||||||
|
{
|
||||||
|
Priority = Priority.VeryLow,
|
||||||
|
};
|
||||||
|
|
||||||
|
interpreter.AddStatement(attr, args => Console.WriteLine($"[LOG] {args}"));
|
||||||
|
```
|
||||||
|
|
||||||
|
### `SearchMode` values
|
||||||
|
|
||||||
|
| Value | The keyword matches when… |
|
||||||
|
| ------------- | -------------------------------------------- |
|
||||||
|
| `StartOfLine` | the line **starts with** the keyword |
|
||||||
|
| `EndOfLine` | the line **ends with** the keyword |
|
||||||
|
| `Contains` | the keyword appears **anywhere** in the line |
|
||||||
|
| `Exact` | the line is **exactly** the keyword |
|
||||||
|
|
||||||
|
### `SpaceAround` values
|
||||||
|
|
||||||
|
| Value | Space requirement |
|
||||||
|
| ---------- | -------------------------------- |
|
||||||
|
| `None` | No surrounding spaces required |
|
||||||
|
| `Start` | A space must precede the keyword |
|
||||||
|
| `End` | A space must follow the keyword |
|
||||||
|
| `StartEnd` | Spaces required on both sides |
|
||||||
|
|
||||||
|
Custom statements run at `Priority.Normal` by default. Lower priority values run first.
|
||||||
|
Use `StatementAttribute.Priority` to control ordering relative to built-in statements.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stopping a script
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var interpreter = new YesNtInterpreter();
|
||||||
|
|
||||||
|
// Start the script on a background thread so we can stop it from this thread.
|
||||||
|
var thread = new System.Threading.Thread(() =>
|
||||||
|
interpreter.Execute(new List<string> { "while True:", "sleep 100", "end_while" }));
|
||||||
|
|
||||||
|
thread.Start();
|
||||||
|
System.Threading.Thread.Sleep(500);
|
||||||
|
interpreter.Stop(); // signals the script to terminate at the next line boundary
|
||||||
|
thread.Join();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reading registered statements
|
||||||
|
|
||||||
|
`StatementInformation` returns a read-only snapshot of every registered statement.
|
||||||
|
This is useful for building syntax highlighters or tooling.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var interpreter = new YesNtInterpreter();
|
||||||
|
|
||||||
|
foreach (var info in interpreter.StatementInformation)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{info.Name,-20} {info.SearchMode,-12} color={info.Color}");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Each `StatementInformation` object exposes:
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
| -------------------------- | -------------- | ---------------------------- |
|
||||||
|
| `Name` | `string` | The keyword |
|
||||||
|
| `SearchMode` | `SearchMode` | Where the keyword is matched |
|
||||||
|
| `SpaceAround` | `SpaceAround` | Required surrounding spaces |
|
||||||
|
| `Color` | `ConsoleColor` | Syntax-highlight colour |
|
||||||
|
| `IgnoreSyntaxHighlighting` | `bool` | Whether to skip highlighting |
|
||||||
|
| `Separator` | `string?` | Optional required sub-string |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API reference
|
||||||
|
|
||||||
|
### `YesNtInterpreter`
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class YesNtInterpreter
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Constructor
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public YesNtInterpreter()
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a new interpreter instance and registers all built-in statements.
|
||||||
|
|
||||||
|
#### Events
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public event Action<string> OnDebugOutput;
|
||||||
|
public event Action<DebugEventArgs> OnLineExecuted;
|
||||||
|
```
|
||||||
|
|
||||||
|
Only raised in debug mode (`isDebugMode: true`).
|
||||||
|
`OnLineExecuted` receives `null` only on EOF completion.
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Execute a .ynt file
|
||||||
|
public void Execute(string path, bool isDebugMode = false);
|
||||||
|
|
||||||
|
// Execute in-memory lines
|
||||||
|
public void Execute(List<string> lines, bool isDebugMode = false);
|
||||||
|
|
||||||
|
// Register a custom statement (full control)
|
||||||
|
public void AddStatement(StatementAttribute attribute, Action<string> handler);
|
||||||
|
|
||||||
|
// Register a custom statement (convenience overloads)
|
||||||
|
public void AddStatement(string name, SearchMode searchMode, SpaceAround spaceAround, Action<string> handler);
|
||||||
|
public void AddStatement(string name, SearchMode searchMode, SpaceAround spaceAround, ConsoleColor color, Action<string> handler);
|
||||||
|
|
||||||
|
// Request graceful stop
|
||||||
|
public void Stop();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Properties
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Read-only snapshot of all registered statements
|
||||||
|
public ReadOnlyCollection<StatementInformation> StatementInformation { get; }
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user