3.1 KiB
Use Rhai as a Domain-Specific Language (DSL)
{{#include ../links.md}}
Rhai can be successfully used as a domain-specific language (DSL).
Expressions Only
In many DSL scenarios, only evaluation of expressions is needed.
The [Engine::eval_expression_XXX
][eval_expression
] API can be used to restrict a script to
expressions only.
Unicode Standard Annex #31 Identifiers
[Variable] names and other identifiers do not necessarily need to be ASCII-only.
The [unicode-xid-ident
] feature, when turned on, causes Rhai to allow [variable] names and
identifiers that follow Unicode Standard Annex #31.
This is sometimes useful in a non-English DSL.
Disable Keywords and/or Operators
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].
Custom 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.
Custom Syntax
For advanced DSL scenarios, it is possible to define entire expression [syntax][custom 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[0] = "sum"
– math operatorinputs[1] = "price"
– field nameinputs[2] = "row"
– loop variable nameinputs[3] = Expression(table)
– data sourceinputs[4] = Expression(row.weight > 50)
– filter predicate
Other identifiers, such as "calculate"
, "FROM"
, as well as symbols such as ->
and :
etc.,
are parsed in the order defined within the [custom syntax].