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

TypeExampleNotes
number42, 3.14, -764-bit floating point. All numeric literals are numbers.
string"hello", "world"Double-quoted. Supports Unicode.
booleantrue, falseCase-sensitive lowercase.
datedate("2026-05-01")ISO 8601 date. Use today() for current date.
timetime("14:30:00")ISO 8601 time.
date and timedate and time("2026-05-01T14:30:00")Combined date-time value.
durationduration("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.
nullnullAbsence 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

FunctionExampleResult
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

FunctionDescription
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

FunctionExampleResult
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))
}