FEEL Reference
FEEL (Friendly Enough Expression Language) is the standard expression language defined by the OMG for use in DMN and BPMN. All expressions in Priostack — conditions, output expressions, variable mappings — use FEEL.
Interactive Playground: Test FEEL expressions live at
/designer/feel. Enter any expression and see the evaluated result instantly.
Types
| Type | Example | Notes |
number | 42, 3.14, -7 | 64-bit floating point. All numeric literals are numbers. |
string | "hello", "world" | Double-quoted. Supports Unicode. |
boolean | true, false | Case-sensitive lowercase. |
date | date("2026-05-01") | ISO 8601 date. Use today() for current date. |
time | time("14:30:00") | ISO 8601 time. |
date and time | date and time("2026-05-01T14:30:00") | Combined date-time value. |
duration | duration("P1D"), duration("PT2H30M") | ISO 8601 duration. P=period, T=time part. |
list | [1, 2, 3], ["a", "b"] | Ordered collection. One-based indexing. |
context | { name: "Alice", age: 30 } | Key-value map. Access with dot notation: person.name. |
null | null | Absence of a value. Comparisons with null are always false. |
Arithmetic Operators
// Basic arithmetic
1 + 2 // => 3
10 - 3 // => 7
4 * 5 // => 20
10 / 3 // => 3.3333...
10 ** 2 // => 100 (exponentiation)
// With variables
amount * 1.2 // apply 20% markup
(price - cost) / cost * 100 // percentage margin
// Duration arithmetic
date("2026-05-01") + duration("P30D") // => date("2026-05-31")
now() - duration("PT1H") // one hour ago
Comparison Operators
amount = 100 // equal
amount != 100 // not equal
amount < 100 // less than
amount <= 100 // less than or equal
amount > 100 // greater than
amount >= 100 // greater than or equal
// Range expressions (shorthand for comparisons)
amount in [0..100] // 0 <= amount <= 100 (inclusive)
amount in (0..100) // 0 < amount < 100 (exclusive)
amount in [0..100) // 0 <= amount < 100 (mixed)
// Membership test
status in ["pending", "review", "approved"] // any of these values
Logical Operators
true and false // => false
true or false // => true
not(true) // => false
// Compound conditions
amount > 0 and status = "approved"
(tier = "gold" or tier = "platinum") and amount > 100
String Functions
| Function | Example | Result |
string length(s) | string length("hello") | 5 |
substring(s, start) | substring("hello world", 7) | "world" |
substring(s, start, len) | substring("hello world", 1, 5) | "hello" |
contains(s, match) | contains("hello", "ell") | true |
starts with(s, prefix) | starts with("hello", "hel") | true |
ends with(s, suffix) | ends with("hello", "llo") | true |
matches(s, pattern) | matches("hello", "hel+") | true |
upper case(s) | upper case("hello") | "HELLO" |
lower case(s) | lower case("HELLO") | "hello" |
trim(s) | trim(" hi ") | "hi" |
string join(list, delim) | string join(["a","b","c"], ",") | "a,b,c" |
split(s, delim) | split("a,b,c", ",") | ["a","b","c"] |
Date and Time Functions
| Function | Description |
now() | Current date and time |
today() | Current date (without time) |
day of week(date) | Day name: "Monday", "Tuesday", etc. |
day of year(date) | Day number (1–365) |
month of year(date) | Month name: "January", etc. |
week of year(date) | ISO week number (1–53) |
years and months duration(from, to) | Duration between two dates in years and months |
// Check if date is a weekday
day of week(today()) in ["Saturday", "Sunday"] // => true if weekend
// Calculate age from birthdate
years and months duration(date("1990-01-15"), today()).years // => age in years
// Check if overdue
dueDate < today() // => true if past due
List Functions
| Function | Example | Result |
count(list) | count([1, 2, 3]) | 3 |
sum(list) | sum([1, 2, 3]) | 6 |
min(list) | min([3, 1, 2]) | 1 |
max(list) | max([3, 1, 2]) | 3 |
append(list, item) | append([1,2], 3) | [1,2,3] |
concatenate(l1, l2) | concatenate([1,2],[3,4]) | [1,2,3,4] |
insert before(list, pos, item) | insert before([1,3], 2, 2) | [1,2,3] |
remove(list, pos) | remove([1,2,3], 2) | [1,3] |
reverse(list) | reverse([1,2,3]) | [3,2,1] |
index of(list, item) | index of([1,2,3], 2) | [2] |
distinct values(list) | distinct values([1,2,2,3]) | [1,2,3] |
flatten(list) | flatten([[1,2],[3]]) | [1,2,3] |
sort(list, fn) | sort([3,1,2], function(x,y) x < y) | [1,2,3] |
Filter and Quantifier Expressions
// Filter: keep items matching a condition
items[price > 100] // all items where price > 100
items[status = "approved"] // all approved items
// Some/Every quantifiers
some x in items satisfies x.price > 100 // true if any item has price > 100
every x in items satisfies x.valid = true // true if all items are valid
// For expression: transform a list
for item in items return item.name // list of names
for i in 1..5 return i * i // [1, 4, 9, 16, 25]
// Access first element
items[1].name // name of first item (1-based)
items[-1].name // name of last item
Context Operations
// Create a context
{ name: "Alice", age: 30, address: { city: "Paris" } }
// Access fields
person.name // => "Alice"
person.address.city // => "Paris"
// Merge contexts
context merge({ a: 1 }, { b: 2 }) // => { a: 1, b: 2 }
// Context from list of pairs
context([["a", 1], ["b", 2]]) // => { a: 1, b: 2 }
// Get keys and values
get entries({ a: 1, b: 2 }) // => [{key:"a",value:1},{key:"b",value:2}]
get value({ a: 1 }, "a") // => 1
Conditional Expressions
// if/then/else
if amount > 1000 then "high" else "low"
// Nested conditions
if tier = "gold" then
if amount > 500 then 15 else 10
else
if amount > 200 then 8 else 5
// Null-safe access (returns null instead of error)
if customer != null then customer.email else null
Function Definitions
// Define and immediately call a function
(function(x, y) x + y)(3, 4) // => 7
// Named function (in DMN context or FEEL context)
{
discount: function(tier, amount)
if tier = "gold" and amount > 500 then 0.15
else if tier = "gold" then 0.10
else 0,
finalPrice: amount * (1 - discount(customerTier, amount))
}