Expression.AST
(expression v2.49.0)
Copy Markdown
Type definitions for the Expression abstract syntax tree.
The AST is produced by Expression.Parser and consumed by Expression.Eval.
It is also used by consumers for transpilation (e.g., to Elasticsearch queries)
and static analysis (e.g., function validation). This module formalizes the
AST as a public API.
Top-Level Structure
Expression.Parser.parse/1 returns a keyword list of :text and :expression
entries:
[text: "hello ", expression: [atom: "world"]]Expression.parse_expression!/1 returns the inner expression AST without
the :text/:expression wrappers.
Node Types
Literals
{:literal, value} — a constant value (integer, float, string, boolean, Date, DateTime, Time).
{:literal, 42}
{:literal, "hello"}
{:literal, true}
{:literal, ~D[2022-01-31]}Variables
{:atom, name} — a variable reference. Names are always lowercased strings.
{:atom, "contact"}
{:atom, "name"}Attribute Access (dot notation)
{:attribute, [parent, child]} — property access via . notation.
Each element is itself an AST node.
# @contact.name
{:attribute, [{:atom, "contact"}, {:atom, "name"}]}
# @contact.details.age
{:attribute, [{:attribute, [{:atom, "contact"}, {:atom, "details"}]}, {:atom, "age"}]}Key Access (bracket notation)
{:key, [subject, key_expr]} — index access via [expr] notation.
# @items[0]
{:key, [{:atom, "items"}, {:literal, 0}]}Function Calls
{:function, [name: name, args: args]} — a function invocation.
Name is a lowercased string. Args is a list of AST nodes.
# SUM(1, 2)
{:function, [name: "sum", args: [literal: 1, literal: 2]]}
# upper(contact.name)
{:function, [name: "upper", args: [{:attribute, [{:atom, "contact"}, {:atom, "name"}]}]]}Infix and/or/not also produce function nodes:
# a and b
{:function, [name: "and", args: [atom: "a", atom: "b"]]}
# not a
{:function, [name: "not", args: [{:atom, "a"}]]}Operators
{operator, [left, right]} — binary arithmetic and comparison operators.
# 1 + 2
{:+, [literal: 1, literal: 2]}
# age > 18
{:>, [{:atom, "age"}, {:literal, 18}]}Supported operators: :+, :-, :*, :/, :^, :&,
:>, :>=, :<, :<=, :==, :!=
Lists
{:list, [args: elements]} — a list literal. Empty list: {:list, []}.
# [1, 2, 3]
{:list, [args: [literal: 1, literal: 2, literal: 3]]}Ranges
{:range, [first, last]} or {:range, [first, last, step]} — a numeric range.
# 1..10
{:range, [1, 10]}
# 1..10//2
{:range, [1, 10, 2]}Lambdas
{:lambda, [args: body]} — an anonymous function using &(...) syntax.
# &(&1 + 1)
{:lambda, [args: {:+, [{:capture, 1}, {:literal, 1}]}]}Captures
{:capture, index} — a lambda parameter reference (&1, &2, etc.).
{:capture, 1}
{:capture, 2}Operator Precedence (lowest to highest)
or(infix logical)and(infix logical)not(prefix logical)==,!=,>,>=,<,<=(comparison)+,-,&(addition, concatenation)*,/(multiplication)^(exponentiation)
Summary
Types
Any AST node
Dot-notation property access
Binary operator expression
A parsed expression block — the output of Expression.parse_expression!/1
A lambda parameter reference
An expression segment in a parsed template
A function call
Bracket-notation index access
A lambda function
A list literal
A literal value
A numeric range
A parsed template — the output of Expression.parse!/1
A text segment in a parsed template
A variable reference (always lowercased)
Types
@type ast_node() :: literal() | variable() | attribute() | key() | function_call() | binary_op() | list_node() | range() | lambda() | capture()
Any AST node
@type attribute() :: {:attribute, [ast_node()]}
Dot-notation property access
@type binary_op() :: {:+, [ast_node()]} | {:-, [ast_node()]} | {:*, [ast_node()]} | {:/, [ast_node()]} | {:^, [ast_node()]} | {:&, [ast_node()]} | {:>, [ast_node()]} | {:>=, [ast_node()]} | {:<, [ast_node()]} | {:<=, [ast_node()]} | {:==, [ast_node()]} | {:!=, [ast_node()]}
Binary operator expression
@type block() :: [ast_node()]
A parsed expression block — the output of Expression.parse_expression!/1
@type capture() :: {:capture, pos_integer()}
A lambda parameter reference
@type expression() :: {:expression, [ast_node()]}
An expression segment in a parsed template
A function call
@type key() :: {:key, [ast_node()]}
Bracket-notation index access
@type lambda() :: {:lambda, [{:args, ast_node()}]}
A lambda function
A list literal
@type literal() :: {:literal, number() | String.t() | boolean() | Date.t() | DateTime.t() | Time.t()}
A literal value
@type range() :: {:range, [integer()]}
A numeric range
@type template() :: [text() | expression()]
A parsed template — the output of Expression.parse!/1
@type text() :: {:text, String.t()}
A text segment in a parsed template
@type variable() :: {:atom, String.t()}
A variable reference (always lowercased)