Last updated:
0 purchases
expression language
expression_language #
Dart library for parsing and evaluating expressions.
Main goal #
Main goal of this library is to be able to parse and evaluate expressions like:
4 * 2.5 + 8.5 + 1.5 / 3.0
copied to clipboard
3* @control1.numberProperty1 < (length(@control2.stringProperty1 + "test string") - 42)
copied to clipboard
([email protected] && length(@control2.stringProperty1) == 21) ? "string1" : "string2"
copied to clipboard
Features #
Currently there are multiple supported data types and operations.
Data types #
String -> maps directly to the Dart String
bool -> maps directly to the Dart bool
Integer -> wrapper around the Dart int
Decimal -> Custom type
DateTime -> maps directly to the Dart DateTime
Duration -> maps directly to the Dart Duration
All the data types above are non-nullable. Since veresion 1.0 we also support nullable types that are mapped to the Dart nullable types. To cast away nullability you can use postfix exclamation mark operator ! in an expression.
Note: To be able to easily work with financial data and not to lose precision we decided to use Decimal data type taken from dart-decimal instead of double. To keep our expression definitions strongly typed and to have a common way to work with all number data types we introduced base Number data type class which is simmilar to Dart num class. Since we can't modify definition of the Dart int we have also introduced Integer data type which is a simple wrapper around the int and which also extends Number. There is a conversion expression from Integer to int and from Decimal to double so higher layers can hide those data types as an implementation detail.
To learn more about DateTime data type in expressions see this merge request.
Operations #
There are most of the standard operations working on the data types above. For example you can use most of the arithmetic operators like +,-, *, / , ~/, % or the logical operators like &&, ||, !, <, >, <=, >=, ==.
To be able to reference another expression from the expression itself we use a construct @element.propertyName. The element can map to any type extending ExpressionProviderElement.
Both element and propertyName must consist only from alpha numeric characters or an underscore and can't start with a number.
There are also special functions like length which returns length of the string. Each function paramter can also come from an expression.
Here is the complete list:
Function
Description
Sample
bool contains(String value, String searchValue)
Returns true if value constains searchValue
contains("abcd", "bc")
String toString<T>(<T> value)
Returns .toString of the value
toString(5)
int durationInDays(Duration value)
Returns duration in days of a given duration value
durationInDays(duration("P5D1H"))
int durationInHours(Duration value)
Returns duration in hours of a given duration value
durationInHours(duration("P5D1H"))
int durationInMinutes(Duration value)
Returns duration in minutes of a given duration value
durationInMinutes(duration("P5D1H"))
int durationInSeconds(Duration value)
Returns duration in seconds of a given duration value
durationInSeconds(duration("P5D1H"))
bool startsWith(String value, String searchValue)
Returns true if value starts with searchValue
startsWith("Hello", "He")
bool endsWith(String value, String searchValue)
Returns true if value ends with searchValue
startsWith("Hello", "lo")
bool isEmpty(String value)
Returns true if value is empty String
isEmpty("")
bool isNull(String value)
Returns true if value is null
isNull(someNullExpression)
bool isNullOrEmpty(String value)
Returns true if value is null or empty String
isNullOrEmpty("")
bool matches(String value, String regex)
Returns true if value fully matches regex expression
matches("[email protected]","^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-]+$")
int length(String value)
length of the string
length("Hi")
int length(String value)
length of the string
length("Hi")
int count<T>(List<T> value)
length of the string
count(@element.array)
DateTime dateTime(String value)
Try to parse value into DateTime, throws InvalidParameterException if it fails
dateTime("1978-03-20 00:00:00.000")
DateTime now()
Returns DateTime.now()
now()
DateTime nowInUtc()
Returns DateTime.now().toUtc()
nowInUtc()
Duration diffDateTime(DateTime left, DateTime right)
Returns difference between two dates - value is always positive
diff(dateTime("1978-03-20"), dateTime("1976-03-20"))
Duration duration(String value)
Returns duration from Iso8601 String, thows InvalidParameterException if it fails
duration("P5D1H")
num round(num value, int precision, int roundingMode)
Rounds the value with given precision and rounding mode as an int (described below)
round(1.5, 2, 0)
num round(num value, int precision, String roundingMode)
Rounds the value with given precision and rounding mode as a String (described below)
round(13.5, 0, "nearestEven")
Table of the roundingModes used in the round function:
Name
Integer representation
Description
nearestEven
0
Rounds to the nearest value; if the number falls midway, it is rounded to the nearest value with an even least significant digit
nearestOdd
1
Rounds to the nearest value; if the number falls midway, it is rounded to the nearest value with an odd least significant digit
nearestFromZero
2
Rounds to the nearest value; if the number falls midway, it is rounded to the value which is the farthest from zero
nearestToZero
3
Rounds to the nearest value; if the number falls midway, it is rounded to the value which is the closest to zero
nearestDownward
4
Rounds to the nearest value; if the number falls midway, it rounds down
nearestUpward
5
Rounds to the nearest value; if the number falls midway, it rounds down
towardsZero
6
Directed rounding towards zero
fromZero
7
Directed rounding from zero
up
8
Directed rounding towards positive infinity
down
9
Directed rounding towards negative infinity
Usage #
//Create expression parser and pass a map of the types extending ExpressionProviderElement which can hold other expressions.
var expressionGrammarDefinition =
ExpressionGrammarParser({"element": TestFormElement()});
var parser = expressionGrammarDefinition.build();
//Parse the expression.
var result = parser
.parse("(1 + @element.value < 3*5) && false || (2 + 3*(4 + 21)) >= 15");
//The expression now contains strongly typed expression tree representing the expression above.
var expression = result.value as Expression<bool>;
//Evaluate the expression.
bool value = expression.evaluate();
copied to clipboard
Writing custom expressions #
You can write your custom expressions simmilar to the ones in the list above.
First you need to extend the Expression<T> class, where T is the return value of the Expression. Here is the example of String concatenation expression (in case you don't want to use already implemented + operator):
import 'package:expression_language/expression_language.dart';
class StringConcatenationExpression extends Expression<String> {
final Expression<String> left;
final Expression<String> right;
StringConcatenationExpression(this.left, this.right);
@override
String evaluate() {
return left.evaluate() + right.evaluate();
}
@override
Expression<String> clone(Map<String, ExpressionProviderElement> elementMap) {
return StringConcatenationExpression(left.clone(elementMap), right.clone(elementMap));
}
@override
List<Expression> getChildren() {
return [left, right];
}
}
copied to clipboard
Now you just need to tell the parser how to create this expression.
To do this you need to pass subclass of FunctionExpressionFactory<T> to the ExpressionGrammarParser constructor - there is a customFunctionExpressionFactories parameter which takes List<FunctionExpressionFactory>.
In case of a simple expressions you can use already existing subclass ExplicitFunctionExpressionFactory<T> which takes all the parameters in the constructor so you can avoid subclassing.
This is the registration code for StringConcatenationExpression:
var expressionGrammarDefinition =
ExpressionGrammarParser({},
customFunctionExpressionFactories: [
ExplicitFunctionExpressionFactory(
name: 'concat',
createFunctionExpression: (parameters) =>
StringConcatenationExpression(parameters[0], parameters[1]),
parametersLength: 2),
],
);
copied to clipboard
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.