Operators

  • Operators that the valid expressions can use are defined in property System.Collections.Generic.IReadOnlyList<UniversalExpressionParser.IOperatorInfo> Operators { get; } in interface UniversalExpressionParser.IExpressionLanguageProvider (an instance of this interface is passed to the parser).

  • The interface UniversalExpressionParser.IOperatorInfo has properties for operator name (i.e., a collection of texts that operator consists of, such as [“IS”, “NOT”, “NUL”] or [“+=”]), priority, unique Id, operator type (i.e., binary, unary prefix or unary postfix).

  • Two different operators can have similar names, as long as they have different operator. For example “++” can be used both as unary prefix as well as unary postfix operator.

Example of defining operators in an implementation of UniversalExpressionParser.IExpressionLanguageProvider

 1public class TestExpressionLanguageProviderBase : ExpressionLanguageProviderBase
 2{
 3    //...
 4    // Some other method and property implementations here
 5    // ...
 6    public override IReadOnlyList<IOperatorInfo> Operators { get; } = new IOperatorInfo[]
 7    {
 8           // The third parameter (e.g., 0) is the priority.
 9           new OperatorInfo(1, new [] {"!"}, OperatorType.PrefixUnaryOperator, 0),
10           new OperatorInfo(2, new [] {"IS", "NOT", "NULL"}, OperatorType.PostfixUnaryOperator, 0),
11
12           new OperatorInfo(3, new [] {"*"}, OperatorType.BinaryOperator, 10),
13           new OperatorInfo(4, new [] {"/"}, OperatorType.BinaryOperator, 10),
14
15           new OperatorInfo(5, new [] {"+"}, OperatorType.BinaryOperator, 30),
16       new OperatorInfo(6, new [] {"-"}, OperatorType.BinaryOperator, 30),
17    }
18}
  • Operator expression (e.g., “a * b + c * d”) is parsed to an expression item of type UniversalExpressionParser.ExpressionItems.IOperatorExpressionItem (a subclass of UniversalExpressionParser.ExpressionItems.IComplexExpressionItem).

Click here to see the definition of UniversalExpressionParser.ExpressionItems.IOperatorExpressionItem

For example the expression “a * b + c * d”, will be parsed to an expression logically similar to “(+(a, b), +(x,d))”. This is so since the binary operator “+” has lower priority (the value of **IOperatorInfo.Priority* is larger), than the binary operator “*”.

In other words this expression will be parsed to a binary operator expression item for “+” (i.e., an instance of IOperatorExpressionItem) with Operand1 and Operand2 also being binary operator expression items of type UniversalExpressionParser.ExpressionItems.IOperatorExpressionItem for expression items “a * b” and “c * d”.

Example of considering priorities when parsing operators

1// The binary operator + has priority 30 and * has priority 20. Therefore,
2// in expression below,  * is applied first and + is applied next.
3// The following expression is parsed to an expression equivalent to
4// "=(var y, +(x1, *(f1(x2, +(x3, 1)), x4)))"
5var y = x1 + f1(x2,x3+1)*x4;

Click here to see the visualized instance of UniversalExpressionParser.IParseExpressionResult

Example of using braces to change order of application of operators

1// Without the braces, the expression below would be equivalent to x1+(x2*x3)-x4.
2var y1 = [x1+x2]*(x3-x4);

Click here to see the visualized instance of UniversalExpressionParser.IParseExpressionResult

Example of operators with multiple parts in operator names

1// The expression below is similar to
2// z = !((x1 IS NOT NULL) && (x2 IS NULL);
3z = !(x1 IS NOT NULL && x2 IS NULL);

Click here to see the visualized instance of UniversalExpressionParser.IParseExpressionResult

Example of two operators (e.g., postfix operators, then a binary operator) used next to each other without spaces in between

1// The spaces between two ++ operators, and + was omitted intentionally to show that the parser will parse the expression
2// correctly even without the space.
3// The expression below is similar to  println(((x1++)++)+x2). To avoid confusion, in some cases it is better to use braces.
4println(x1+++++x2)

Click here to see the visualized instance of UniversalExpressionParser.IParseExpressionResult

Example of unary prefix operator used to implement “return” statement

 1// return has priority int.MaxValue which is greater then any other operator priority, therefore
 2// the expression below is equivalent to "return (x+(2.5*x))";
 3return x+2.5*y;
 4
 5// another example within function body
 6f1(x:int, y:int) : bool
 7{
 8   // return has priority int.MaxValue which is greater then any other operator priority, therefore
 9   // the expression below is equivalent to "return (x+(2.5*x))";
10   return f(x)+y > 10;
11}

Click here to see the visualized instance of UniversalExpressionParser.IParseExpressionResult