◷ Reading Time: 12 minutes
Natural Language (NL) is a language used to model business rules that are close to your spoken language. The intention is to remove all of the noise of an XML model and emphasize the actual business rules using a business glossary, terms, and logic that are reusable across other types of logic.
As a result, rules are simpler to understand with less noise related to structure and/or types of the rule logic.
@name Test a person's identity
input person
output valid
when Person has identity
(
Person has name or
Person has family
) and
Email of person match "\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
/* Birth city must be available */
and
(
Name of City of BirthPlace of person is not null and
Name of City of BirthPlace of person is not empty
) or
Age of person lt 18
then
set valid to true
end
when Person has name
Name of person is not null and
Name of person is not empty
end
when Person has family
Family of person is not null and
Family of person is not empty
end
Rule Entry
- Use
to create a new business rule.
- Use [CTRL]+[SPACE BAR] to bring up the suggestion box
- To navigate between rules argument, press [TAB]
- Select Parameter from the suggestion box and hit [ENTER]
- Press [.] after parameter name and suggestion box navigates through the elements

Structure
Body
The body of the rule contains:
- the name of the rule
- context
- set of logic
@name "name of rule document"
/* enable attribute is not mandatory, if it’s not set the default value will be added automatically. Default value is true. */
@enable {true | false}
{context}
{logic 1}
{logic 2}
...
{logic n}
Logic
The logic is a when-then-otherwise-end block. then and otherwise are optional.
/* There might be one or more when the condition is available in the rule document */
when {name of logic}
{Body of condition}
then
{body of actions}
otherwise
{body of actions}
end
Please note that logic can have no name. In that case, remove the {name of logic} from after when.
When the {body of condition} is left empty, the actions on then will be executed automatically. If the {body of condition} is provided, they will be executed when {body of condition} is met otherwise the otherwise will be executed.
Parameterized Logic
In defining logic with parameters, { and } are used to enclose the parameter name
/*A logic with parameter named amount*/
when Add bonus of {amount} to total amount
end
/*A logic with NO parameters*/
when Print total
end
Logic
In calling a logic, just use its name. If the logic is parameterized then ( and ) are used to pass values
when
Add bonus of (12.3) to total amount and
Print total
end
Context
Adding {context} to rules has the following format:
/* List of input parameters */
given | input variable1, variable2, …
/* List of output parameteres */
output variable1, variable2, …
input output variable1, variable2, …
Body of condition
{Body of condition} has the following format:
{compare expression-1} {or|and|nor|xor|xnor}
{compare expression-2} {or|and|nor|xor|xnor}
…
{compare expression-n}
/* Or may contains groups or nested groups. Group starts with ( and ends with ) */
(
{Body of condition-1} {or|and|nor|xor|xnor}
{Body of condition-2} {or|and|nor|xor|xnor}
…
{Body of condition-n}
) {or|and|nor|xor|xnor}
{Body of condition}
Group
With using (
and )
, Boolean logic can be grouped into sub-groups with higher priority. Also, groups/sub-groups can have their own negate attributes.
(
@negate {true | false}
{logic 1} {or|and|nor|xor|xnor}
{logic 2} {or|and|nor|xor|xnor}
...
{logic n}
)
Compare expression
{compare expression} has the following format:
case 1: {left hand expression} {operator} {right hand expression}
or
case 2: name of logic
or
case 3: Any expression
case 1
{Right hand expression} can be any expression or {Value}.
{operator} can be
- Comparison operators
- Or any of: is, is not, match, not match
{left-hand expression} can be a {term} or can be any expression or {Value}.
case 2
When multiple logic is defined in a document, then it can have a name and call each other by name. In these cases, the parameter can be called by parentheses.
When multiple actions are expected as part of the consequence, then they should be separated or connected by either of the following:
- and
- ; (semicolon)
- set
Value
Value can be primitive, constant values, or complex expressions (e.g., value [3; 45] is a range expression value).
Expression
{value} can be any Expression
Of Operator
{left or right hand expression} may have:
/* Flat property access */
{Property name} of {variable}
/* Or nested property access */
{Property name} of {Property name} of {Property name} of … {variable}
Samples
Logic with names:

Logic with no name:

Where r1, r2, r3, r4, and r5 are some other logic that is used in this logic.
Iterations
Iterating over the list is available only on the then section of logic. If you need to iterate on a list (i.e., an array or collection of objects) you can use for.
for variableName in listName
(
/* do your tasks */
)
When there is a condition to break the iteration, you include until to the for.
for variableName in listName until (expression)
(
/* do your tasks */
)
The loop executes while the evaluated expression is false.
Comments
Comments can be added to the rule document using /* and */.
Sample

Parameters
Parameters can be defined in a standard way using the Declaration section or inside the Dsl section.
Or alternatively, they can be defined as part of the NL with the following keywords:
- input: defines input parameters.
- give: defines input parameters.
- output: defines output parameters.
Format:
[input|give|output] list of parameters, separated by comma
Example:

Local Parameters
Local [Parameter]s can be added at two different levels:
- Root scope
- Logic scope
In the example shown below ‘g’ is defined as a local parameter in the logic scope.
when split {names} into groups
then
/* defining a local parameter in a Logic scope. */
local g;
g = split(names,',');
/* rest of your logic */
end
Operators
In the body of logic, all of the operators that are described in the Expression section are accepted. On top of that, there are some specific operators in NL, as follows:
- is: To check equality
- is not: To check inequality
- match: To check the Regex pattern is matched
- match not: To check Regex pattern is not matched
- of: access to field and property on a parameter
- set/to: set a value to a parameter or its underlying structure. An alias to Val.
Match
Format
[value|parameter|Term] [match | not match] pattern
Example
Email of person match "\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
where Email is a property on person parameter.
Evaluation
Boolean expressions can be chained in the body of logic.
Format
exp = [boolean value | term [is|is not] value | boolean expression]
condition = exp [and|or|nor|xor] | exp...
Samples
Sample 1
A rule like this:
R4: If all of the following are true, then the car’s potential theft rating is *low*.
* car model is *not* on HTPA list
* car’s price is between $20,000 and $45,000,
can be modelled as shown below:

Sample 2
In this example, we need to produce the result shown below (right) from a source (left):

We have two questions to answer:
- Cars in both groups (commonCars)
- Unique cars in each group (allUniqueCars)
input cars
/*
commonCars: cars in both groups
allUniqueCars: unique cars in each groups
*/
output commonCars, allUniqueCars
local g1,g2,ab,ba,groups
when main
then
split into groups;
/* Intersect of two groups */
commonCars = g1
|select(x, x.Make, x.Model)
|intersect (
g2 |select(x, x.Make, x.Model)
);
/* difference of first group from second one */
ab = g1
|select (x, x.Make, x.Model)
|except (
g2 |select (x, x.Make, x.Model)
);
/* difference of second group from first one*/
ba = g2
|select (x, x.Make, x.Model)
|except (
g1 |select (x, x.Make, x.Model)
);
/* union the differences */
allUniqueCars = ab |union (ba);
end
when split into groups
then
/* As you see here, it allows you to split the logic
and then you call it later by its name */
groups = cars |groupBy (x, x.Group);
g1 = groups[0];
g2 = groups[1];
end
Sample 3: Auto premium
Calculation of the auto premium of a car in Natural Language: Add a bonus of (12.3) to the total amount
input car
when main
@processAll false
test for Compact or
test for Sedan or
test for Luxury
end
when test for Compact
(car.Style != 'Compact') or ((car.Model == 'abcd') and (car.ModelYear == 1999)) or
car.ModelYear == 2002
then
increase premium by (250) amount
end
when test for Sedan
car.Style=='Sedan'
then
increase premium by (400) amount
end
when test for Luxury
car.Style=='Luxury'
then
increase premium by (500) amount
end
when increase premium by {n} amount
then
car.AutoPremium += n;
end
Notification
In an NL document, $context can be used to write notifications.
Format: $context.WriteInfo(groupName, message)
$context.WriteWarning(groupName, message)
$context.WriteError(groupName, message)
- groupName: to categorize a set of notices in notification collection. null when it is not needed.
- message: any text, expression, or value for the notice
Example: $context.WriteError(null, '$Assets is imputed.');
The other option is to use notification functions
Inference
The Inference capability allows rules dependencies to each other within a ruleset to be resolved at runtime, which means that the order of rules definition becomes irrelevant to the order of rules execution. To use the inference command, run on can be used:
run goal on {r1, r2, r3...}
- goal (optional): Name of the parameter that is the goal to be answered
- r1,r2…: name of the rules (i.e., when names)
Example
when main
run on {test for Compact, test for Sedan, test for Luxury}
end