Rhai can be successfully used as a domain-specific language (DSL).
In many DSL scenarios, only evaluation of expressions is needed.
Engine::eval_expression_XXX API can be used to restrict a script to
Variable names and other identifiers do not necessarily need to be ASCII-only.
This is sometimes useful in a non-English DSL.
In some DSL scenarios, it is necessary to further restrict the language to exclude certain language features that are not necessary or dangerous to the application.
For example, a DSL may disable the
while loop while keeping all other statement types intact.
It is possible, in Rhai, to surgically disable keywords and operators.
Some DSL scenarios require special operators that make sense only for that specific environment. In such cases, it is possible to define custom operators in Rhai.
let animal = "rabbit"; let food = "carrot"; animal eats food // custom operator 'eats' eats(animal, food) // <- the above actually de-sugars to this let x = foo # bar; // custom operator '#' let x = #(foo, bar) // <- the above actually de-sugars to this
Although a custom operator always de-sugars to a simple function call, nevertheless it makes the DSL syntax much simpler and expressive.
For advanced DSL scenarios, it is possible to define entire expression syntax – essentially custom statement types.
For example, the following is a SQL-like syntax for some obscure DSL operation:
let table = [..., ..., ..., ...]; // Syntax = calculate $ident$ ( $expr$ -> $ident$ ) => $ident$ : $expr$ let total = calculate sum(table->price) => row : row.weight > 50; // Note: There is nothing special about those symbols; to make it look exactly like SQL: // Syntax = SELECT $ident$ ( $ident$ ) AS $ident$ FROM $expr$ WHERE $expr$ let total = SELECT sum(price) AS row FROM table WHERE row.weight > 50;
After registering this custom syntax with Rhai, it can be used anywhere inside a script as a normal expression.
For its evaluation, the callback function will receive the following list of inputs:
inputs = "sum"– math operator
inputs = "price"– field name
inputs = "row"– loop variable name
inputs = Expression(table)– data source
inputs = Expression(row.weight > 50)– filter predicate
Other identifiers, such as
"FROM", as well as symbols such as
are parsed in the order defined within the custom syntax.