This document describes the syntax and semantics of the FUSE programming language using Extended Backus-Naur Form (EBNF).
Token = Number | String | Identifier | Keyword | Operator | Punctuation | Comment | Eol ;Number = DecimalNumber | HexNumber ;
DecimalNumber = Digit+ [ "." Digit+ ] [ Exponent ] ;
HexNumber = "0" ("x" | "X") HexDigit+ ;
Exponent = ("e" | "E") [ "+" | "-" ] Digit+ ;
Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
HexDigit = Digit | "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" ;String = '"' StringChar* '"' | "'" StringChar* "'" ;
StringChar = EscapeSequence | (AnyChar - ('"' | "'" | "\\")) ;
EscapeSequence = "\\" ("n" | "t" | "r" | '"' | "'" | "\\" | UnicodeEscape) ;
UnicodeEscape = "u" HexDigit HexDigit HexDigit HexDigit ;Identifier = Letter (Letter | Digit | "_")* ;
Letter = UnicodeLetterCategory ;Keyword = "fn" | "let" | "global" | "if" | "else" | "while" | "for" | "loop"
| "return" | "true" | "false" | "once" | "namespace" ;Operator = ".." | "+" | "-" | "*" | "/" | "%"
| "=" | "==" | "!=" | "<" | ">" | "<=" | ">="
| "&&" | "||" | "!" | "."
| "->" | "+=" | "-=" | "*=" | "/=" | "%=" | "..="
| "++" | "--" ;Punctuation = "(" | ")" | "{" | "}" | "[" | "]" | "," | ":" | "@" ;Comment = SingleLineComment | MultiLineComment ;
SingleLineComment = "//" (AnyChar - "\n")* ;
MultiLineComment = "/*" (AnyChar | MultiLineComment)* "*/" ;Eol = "\n" | ";" ;Program = TopLevelStatement* ;
TopLevelStatement = VariableDeclaration
| FunctionDeclaration
| HatBlock
| NamespaceDeclaration ;VariableDeclaration = ("let" | "global") Identifier "=" Expression Eol ;FunctionDeclaration = [ DecoratorStatement ] "fn" Identifier "(" ParameterList? ")" [ "once" ] "->" Type BlockStatement ;
ParameterList = Parameter ("," Parameter)* ;
Parameter = Identifier ":" Type ;
Type = Identifier ;NamespaceDeclaration = "namespace" Identifier "=" "{" NamespaceBody "}" ;
NamespaceBody = NamespaceProperty* ;
NamespaceProperty = Identifier "=" NamespaceValue Eol ;
NamespaceValue = Object | Array | String | Number | Boolean ;
Object = "{" [ ObjectProperty ("," ObjectProperty)* ] "}" ;
ObjectProperty = String ":" NamespaceValue ;
Array = "[" [ NamespaceValue ("," NamespaceValue)* ] "]" ;
Boolean = "true" | "false" ;DecoratorStatement = "@" Identifier "(" ArgumentList? ")" Target ;
Target = FunctionDeclaration | VariableDeclaration ;
ArgumentList = Literal ("," Literal)* ;Note: Currently, only the @export decorator is supported.
HatBlock = Expression BlockStatement ;Examples:
event.start { /* statements */ }
event.keyPressed("space") { /* statements */ }
Statement = VariableDeclaration
| AssignmentStatement
| IncrementStatement
| IfStatement
| WhileStatement
| ForStatement
| LoopStatement
| ReturnStatement
| BlockStatement
| ExpressionStatement
| NoopStatement ;AssignmentStatement = Expression AssignmentOperator Expression Eol ;
AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "..=" ;IncrementStatement = IncrementOperator Expression Eol
| Expression IncrementOperator Eol ;
IncrementOperator = "++" | "--" ;IfStatement = "if" "(" Expression ")" Statement [ "else" Statement ] ;WhileStatement = "while" "(" Expression ")" Statement ;ForStatement = "for" "(" [ ForInit ] ";" [ Expression ] ";" [ ForUpdate ] ")" Statement ;
ForInit = AssignmentStatement | IncrementStatement ;
ForUpdate = AssignmentStatement | IncrementStatement ;LoopStatement = "loop" Statement ;ReturnStatement = "return" [ Expression ] Eol ;BlockStatement = "{" Statement* "}" ;ExpressionStatement = Expression Eol ;NoopStatement = Eol ;Expression = LogicalOrExpression ;
LogicalOrExpression = LogicalAndExpression ( "||" LogicalAndExpression )* ;
LogicalAndExpression = EqualityExpression ( "&&" EqualityExpression )* ;
EqualityExpression = ComparisonExpression ( ("==" | "!=") ComparisonExpression )* ;
ComparisonExpression = TermExpression ( (">" | ">=" | "<" | "<=") TermExpression )* ;
TermExpression = FactorExpression ( ("+" | "-" | "..") FactorExpression )* ;
FactorExpression = UnaryExpression ( ("*" | "/" | "%") UnaryExpression )* ;
UnaryExpression = ( ("+" | "-" | "!") UnaryExpression ) | CallExpression ;
CallExpression = PrimaryExpression ( "(" ArgumentList? ")" [ BlockStatement ]
| "[" Expression "]"
| "." Identifier )* ;
PrimaryExpression = Literal
| Identifier
| ArrayLiteral
| "(" Expression ")" ;
ArgumentList = Expression ("," Expression)* ;
ArrayLiteral = "[" [ Expression ("," Expression)* ] "]" ;
Literal = Number | String | Boolean ;The FUSE program structure allows only the following at the top level:
-
Variable Declarations (
letorglobal)letdeclares a local variable (sprite/stage specific)globaldeclares a global variable (accessible across all sprites)
-
Function Declarations (
fn)- Define custom blocks/procedures
- Can have
oncemodifier to indicate the function runs without screen refresh
-
Hat Blocks (Event Handlers)
- Event-driven code execution
- Syntax:
expression { statements } - Examples:
event.start { ... },event.keyPressed("space") { ... }
-
Namespace Declarations
- Define configuration or mapping data
- Used for metadata or built-in block definitions
globalvariables: Shared across all sprites and the stageletvariables: Local to the current sprite or stage- Function parameters: Local to the function scope
FUSE uses a simple type system:
void: No return valueany: Any Scratch value (string, number, boolean)bool: Boolean values (trueorfalse)
The @export decorator is used to export Scratch blocks.
@export("test [params]") fn functionName(params: any) once -> returnType {
// The function will appear as a Scratch block with the given name and parameters
}
@export("variable description") let variableName = initialValue ;
+: Addition-: Subtraction*: Multiplication/: Division%: Modulo
..: String concatenation
==: Equal!=: Not equal<: Less than>: Greater than<=: Less than or equal>=: Greater than or equal
&&: Logical AND||: Logical OR!: Logical NOT
=: Assignment+=,-=,*=,/=,%=,..=: Compound assignment
++: Increment by 1--: Decrement by 1
if (condition) {
// statements
} else {
// statements
}
while (condition) {
// statements
}
for (init; condition; update) {
// statements
}
loop {
// statements
}
Functions can be called with arguments:
functionName(arg1, arg2, arg3)
Some Scratch blocks can have a "then" block:
someBlock(args) {
// then statements
}
Access namespace members or object properties:
namespace.property
object.method(args)
array[index]
FUSE provides several built-in namespaces that map to Scratch blocks:
motion: Motion blockslooks: Looks blockssound: Sound blocksevent: Event blocks (hat blocks)control: Control blockssensing: Sensing blocksmath: Math operationspen: Pen extension blockstranslate: Translation blocks
For detailed API documentation, see the builtin.fuse file.
fn greet(name: any) once -> void {
looks.say("Hello, " .. name .. "!")
}
event.start {
greet("World")
}
global score = 0
let lives = 3
fn updateScore(points: any) once -> void {
score += points
}
fn checkWinCondition() once -> void {
if (score >= 100) {
looks.say("You win!")
} else if (score >= 50) {
looks.say("Almost there!")
} else {
looks.say("Keep going!")
}
}
fn countdown() once -> void {
let i = 10
while (i > 0) {
looks.say(i)
i--
}
looks.say("Blast off!")
}
fn processArray() once -> void {
global items = [1, 2, 3, 4, 5]
for (let i = 0; i < items.length; i++) {
looks.say(items[i])
}
}
@export("custom block [arg1] and [arg2]")
fn customBlock(arg1: any, arg2: any) once -> any {
return arg1 + arg2
}
(* Program Structure *)
Program = TopLevelStatement* ;
TopLevelStatement = VariableDeclaration | FunctionDeclaration | HatBlock | NamespaceDeclaration ;
(* Declarations *)
VariableDeclaration = ("let" | "global") Identifier "=" Expression Eol ;
FunctionDeclaration = [ DecoratorStatement ] "fn" Identifier "(" ParameterList? ")" [ "once" ] "->" Type BlockStatement ;
ParameterList = Parameter ("," Parameter)* ;
Parameter = Identifier ":" Type ;
Type = Identifier ;
(* Decorators *)
DecoratorStatement = "@" Identifier "(" ArgumentList? ")" Target ;
Target = FunctionDeclaration | VariableDeclaration ;
(* Hat Blocks *)
HatBlock = Expression BlockStatement ;
(* Statements *)
Statement = VariableDeclaration | AssignmentStatement | IncrementStatement
| IfStatement | WhileStatement | ForStatement | LoopStatement
| ReturnStatement | BlockStatement | ExpressionStatement | NoopStatement ;
AssignmentStatement = Expression AssignmentOperator Expression Eol ;
AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "..=" ;
IncrementStatement = IncrementOperator Expression Eol | Expression IncrementOperator Eol ;
IncrementOperator = "++" | "--" ;
IfStatement = "if" "(" Expression ")" Statement [ "else" Statement ] ;
WhileStatement = "while" "(" Expression ")" Statement ;
ForStatement = "for" "(" [ ForInit ] ";" [ Expression ] ";" [ ForUpdate ] ")" Statement ;
ForInit = AssignmentStatement | IncrementStatement ;
ForUpdate = AssignmentStatement | IncrementStatement ;
LoopStatement = "loop" Statement ;
ReturnStatement = "return" [ Expression ] Eol ;
BlockStatement = "{" Statement* "}" ;
ExpressionStatement = Expression Eol ;
NoopStatement = Eol ;
(* Expressions *)
Expression = LogicalOrExpression ;
LogicalOrExpression = LogicalAndExpression ( "||" LogicalAndExpression )* ;
LogicalAndExpression = EqualityExpression ( "&&" EqualityExpression )* ;
EqualityExpression = ComparisonExpression ( ("==" | "!=") ComparisonExpression )* ;
ComparisonExpression = TermExpression ( (">" | ">=" | "<" | "<=") TermExpression )* ;
TermExpression = FactorExpression ( ("+" | "-" | "..") FactorExpression )* ;
FactorExpression = UnaryExpression ( ("*" | "/" | "%") UnaryExpression )* ;
UnaryExpression = ( ("+" | "-" | "!") UnaryExpression ) | CallExpression ;
CallExpression = PrimaryExpression ( "(" ArgumentList? ")" [ BlockStatement ] | "[" Expression "]" | "." Identifier )* ;
PrimaryExpression = Literal | Identifier | ArrayLiteral | "(" Expression ")" ;
ArgumentList = Expression ("," Expression)* ;
ArrayLiteral = "[" [ Expression ("," Expression)* ] "]" ;
Literal = Number | String | Boolean ;
(* Lexical Elements *)
Number = DecimalNumber | HexNumber ;
DecimalNumber = Digit+ [ "." Digit+ ] [ Exponent ] ;
HexNumber = "0" ("x" | "X") HexDigit+ ;
Exponent = ("e" | "E") [ "+" | "-" ] Digit+ ;
String = '"' StringChar* '"' | "'" StringChar* "'" ;
StringChar = EscapeSequence | (AnyChar - ('"' | "'" | "\\")) ;
EscapeSequence = "\\" ("n" | "t" | "r" | '"' | "'" | "\\" | UnicodeEscape) ;
UnicodeEscape = "u" HexDigit HexDigit HexDigit HexDigit ;
Identifier = Letter (Letter | Digit | "_")* ;
Boolean = "true" | "false" ;
(* Namespace Declaration *)
NamespaceDeclaration = "namespace" Identifier "=" "{" NamespaceBody "}" ;
NamespaceBody = NamespaceProperty* ;
NamespaceProperty = Identifier "=" NamespaceValue Eol ;
NamespaceValue = Object | Array | String | Number | Boolean ;
Object = "{" [ ObjectProperty ("," ObjectProperty)* ] "}" ;
ObjectProperty = String ":" NamespaceValue ;
Array = "[" [ NamespaceValue ("," NamespaceValue)* ] "]" ;