Complete language specification for TinyExpression v1.4.15.
- Literals
- Variables
- Operators
- Conditional Expressions
- String Functions
- Variable Declarations
- User-Defined Methods
- External Java Methods
- Java Code Blocks
- Comments
- Type Hints
123 integer
3.14 decimal
-42 negative integer
1.5e3 scientific notation (= 1500.0)
- Signed prefix (
+,-) supported - Scientific notation (
e/E) supported - Default type is controlled by
numberTypeinFormulaInfo(default:float)
'hello' single-quoted
"hello" double-quoted
- Either quote style accepted; they are interchangeable
- Basic Java escape sequences apply (
\n,\t,\\, etc.)
true
false
Variables are prefixed with $.
$age
$name
$isMember
- Values are resolved from
CalculationContext - A variable reference to a name not set in context returns
null - Variable names are case-sensitive
| Operator | Description | Example |
|---|---|---|
+ |
Addition | 1 + 2 |
- |
Subtraction | 5 - 3 |
* |
Multiplication | 2 * 3 |
/ |
Division | 10 / 3 |
| Operator | Description | Example |
|---|---|---|
== |
Equal | $age == 20 |
!= |
Not equal | $age != 20 |
> |
Greater than | $age > 18 |
>= |
Greater or equal | $age >= 18 |
< |
Less than | $age < 65 |
<= |
Less or equal | $age <= 65 |
String equality (==, !=) uses String.equals() internally.
| Operator | Description | Example |
|---|---|---|
& |
Logical AND | $a & $b |
| |
Logical OR | $a | $b |
^ |
Logical XOR | $a ^ $b |
not() |
Logical NOT | not($flag) |
()— parenthesesnot()— negation*,/— multiplicative+,-— additive>,>=,<,<=— relational==,!=— equality^— XOR&— AND|— OR
if(condition){thenValue}else{elseValue}
conditionmust be a boolean expression- Both
thenandelsebranches are required - Returns the value of the matching branch
Example:
if($age >= 20){100}else{0}
condition ? thenValue : elseValue
Equivalent to if/else. Supported in P4 backends.
match{
condition1 -> value1,
condition2 -> value2,
default -> defaultValue
}
- Evaluated top to bottom; first matching condition wins
defaultbranch is strongly recommended (SHOULD)- Cases separated by commas
Example:
match{
$countryCode == 'JP' -> 1,
$countryCode == 'US' -> 2,
default -> 0
}
| Function | Description | Example |
|---|---|---|
toUpperCase(s) |
Uppercase | toUpperCase($name) |
toLowerCase(s) |
Lowercase | toLowerCase($name) |
trim(s) |
Trim whitespace | trim($input) |
length(s) |
String length | length($name) |
toNum(s) |
Parse to number | toNum($numStr) |
| Method | Description | Example |
|---|---|---|
.startsWith(str) |
Prefix match | $msg.startsWith('hello') |
.endsWith(str) |
Suffix match | $msg.endsWith('world') |
.contains(str) |
Substring match | $msg.contains('abc') |
.isPresent() |
Non-null / non-empty check | $name.isPresent() |
$message[0:3] characters at index 0, 1, 2 (end exclusive)
$firstName + ' ' + $lastName
The + operator performs string concatenation when operands are strings.
Variable declarations define defaults and type hints for formula inputs.
variable $name as type set [if not exists] defaultValue description='description';
var $name as type set defaultValue description='description';
| Part | Description |
|---|---|
variable / var |
Declaration keyword |
$name |
Variable name (must start with $) |
as type |
Type hint: number, string, boolean, object, float |
set |
Assign default value |
if not exists |
Only set if the variable has no current value in context |
description='...' |
Human-readable description (used by LSP hover) |
Examples:
variable $gender as string set if not exists 'male' description='gender';
variable $age as number set 18 description='age in years';
variable $isMember as boolean description='membership flag';
Formulas can define multiple named methods.
returnType methodName($param as type, ...){
body
}
- The entry point must be named
main - Method calls use
call methodName(args) - Supported return types:
float,string,boolean,object
Example:
float main(){
match{
$age < 18 -> 500,
default -> call feeByGender($gender)
}
}
float feeByGender($gender as string){
match{
$gender == 'female' -> 1000,
default -> 1800
}
}
Call Java methods from the host application inside a formula.
import package.ClassName#methodName as alias;
external returning as returnType alias(arg1, arg2, ...)
Formula:
import sample.v1.CheckDigits#check as checkDigits;
if(external returning as boolean checkDigits($input)){1}else{0}
Java setup:
// Register the object in CalculationContext before executing the formula
context.set(new sample.v1.CheckDigits());Java class:
package sample.v1;
import org.unlaxer.tinyexpression.CalculationContext;
public class CheckDigits {
public boolean check(CalculationContext context, String target) {
return target.matches("\\d+");
}
}Security Warning: Java code blocks compile and execute arbitrary Java code on the JVM at formula evaluation time. Only enable this feature when formula authors are fully trusted. Do not expose this capability to untrusted users.
Risk: Any Java code, including file system access, network calls, or
System.exit(), can be embedded. Sandbox control is the responsibility of the host application.
Execution is disabled by default. Trusted hosts must explicitly call JavaCodeBlockPolicy.setEnabled(true); the VS Code debugger equivalently requires allowJavaCodeBlocks: true in launch.json.
A Java class can be embedded directly inside a formula field using triple-backtick syntax:
formula:
```java:sample.v1.CheckDigits
package sample.v1;
import org.unlaxer.tinyexpression.CalculationContext;
public class CheckDigits {
public boolean check(CalculationContext context, String target) {
return target.matches("\\d+");
}
}
```
import sample.v1.CheckDigits#check as checkDigits;
if(external returning as boolean checkDigits($input)){1}else{0}
The class is compiled in-memory and loaded via MemoryClassLoader. The compiled bytecode is scoped to the formula's class loader and is not persisted to disk.
See decisions/ADR-003-java-codeblock-safety.md for the security decision record.
| Context | Syntax | Scope |
|---|---|---|
| FormulaInfo metadata | # comment |
Lines starting with # in the key-value block |
| Formula body | /* comment */ |
Block comment anywhere in the formula |
| Type Name | Java Type | Notes |
|---|---|---|
byte |
Byte |
|
short |
Short |
|
int |
Integer |
|
long |
Long |
|
float |
Float |
Recommended default |
double |
Double |
|
number |
Float |
Alias for float |
string |
String |
|
boolean |
Boolean |
|
object |
Object |
|
bigDecimal |
BigDecimal |
Limited expression support |
bigInteger |
BigInteger |
Limited expression support |
timestamp |
Timestamp |
Special purpose |
When two operands have different numeric types, the wider type wins:
double > float > long > int
Example: 1 + 2.0 → result type is float (or double if operand is double).
| Function | Description | Example |
|---|---|---|
min(a, b, ...) |
Minimum (2+ arguments) | min($a, $b, 0) |
max(a, b, ...) |
Maximum (2+ arguments) | max($a, $b, 100) |
abs(n) |
Absolute value | abs($score) |
floor(n) |
Floor | floor($value) |
ceil(n) |
Ceiling | ceil($value) |
| Function | Description |
|---|---|
inTimeRange($ts, start, end) |
True if timestamp is in range |
inDayTimeRange($ts, start, end) |
True if time-of-day is in range |