Skip to content

Latest commit

 

History

History
215 lines (177 loc) · 12.5 KB

grammar.md

File metadata and controls

215 lines (177 loc) · 12.5 KB

Expr grammar

Expr implements 4 interlaced recursive descent parser for parsing numeric, datetime, string and boolean expressions. When the type is unknow in advance, these are attempted sequentially until a type parser reports success.

This grammar allows dangerous entries:

  • Elevated number of recursive calls (ex. ((...(1)...))) can cause a program crash when the maximum stack size is exceeded
  • Elevated number of nested indefinite expressions (ex. ifelse(ifelse(...))) lead to an exponential time resolution

To avoid these problems, expr limits the number recursive calls and nested indefinite expressions. Fixed maximum values should be sufficient for the vast majority of cases.

Grammar for types

number      = (0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?
datetime    = '"' (19[7-9][0-9]|2[0-9]{3})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(.[0-9]{1,3}Z?)?)? '"'
boolean     = 'true' | 'True' | 'TRUE' | 'false' | 'False| 'FALSE'
string      = '"' ([^\\] | '\n' | '\t' | '\"' | '\\')* '"'
variable    = '$' ( [a-zA-Z][a-zA-Z0-9_]* | '{' [^{}]+ '}' )
timePart    = '"' ('year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'millis') '"'

Number: double-precision floating point in JSON-format (RFC-7159 , section 6 -numbers-)

  • Examples: 42, -0.5, 314e-2, 0.314e1
  • Not supported: 03, .5, 42., 1.e1, 1e04

Datetime: UTC millis from epoch-time in ISO-8601

  • Examples: 2024-08-24T08:19:25.402Z, 2024-08-24T08:19:25.402, 2024-08-24T08:19:25, 2024-08-24
  • Not supported: 24/08/2024, 08/24/2024, 24 August 2024, etc.

String: double-quoted string supporting escape characters (\n, \t, \", \\)

  • Examples: "I am a string", "val=\"xxx\""
  • Not supported: A string surrounded by quotes containing a NUL.

Boolean: true, True, TRUE, false, False, FALSE

  • Examples: true, false
  • Not supported: 1, 0, TrUe

Variable: Variable name prefixed by '$'

  • Examples: $x, $sum_values, ${x}, ${free var name, yep}
  • Not supported: $a-b, $_a, ${x}d}, ${}

Grammar for numeric expressions

numExpr     = numTerm (numInfixOp numTerm)*
numTerm     = number | 
              numConst | 
              varExpr | 
              numFunc | 
              '(' numExpr ')' | 
              numPrefixOp numTerm
numInfixOp  = '+' | '-' | '*' | '/' | '^' | '%'
numPrefixOp = '+' | '-'
numFunc     = <see list below>
numConst    = <see list below>

Consecutive operators are not supported (example: 1+-1 is not valid)

Return Function Params Description
number - (numExpr) Minus (infix operator)
number abs (numExpr) Absolute value
number sin (numExpr) Sine
number cos (numExpr) Cosine
number tan (numExpr) Tangent
number sqrt (numExpr) Square root
number exp (numExpr) Base-e exponential
number log (numExpr) Natural logarithm
number ceil (numExpr) Smallest int not less than num
number floor (numExpr) Largest int not less than num
number trunc (numExpr) Round to integer, toward zero
number + (numExpr, numExpr) Addition
number - (numExpr, numExpr) Subtraction
number * (numExpr, numExpr) Multiplication
number / (numExpr, numExpr) Division
number %, mod (numExpr, numExpr) Modulus
number ^, pow (numExpr, numExpr) Power
number min (numExpr, numExpr) Returns the smaller of two given values
number max (numExpr, numExpr) Returns the larger of two given values
number random (numExpr, numExpr) Returns a random value in range [min,max)
number clamp (numExpr, numExpr, numExpr) Coerce a value to be in a fixed range
number length (strExpr) Length of a string
number find (strExpr, strExpr, numExpr) Locate a text string into another text
number datepart (timeExpr, timePart) Returns a part from a datetime
number datediff (timeExpr, timeExpr, timePart) Difference between two datetimes
number ifelse (boolExpr, numExpr, numExpr) Conditional value
Type Constant Value
number E 2.71828...
number PI 3.14159...
number Inf Infinite
number NaN Not-a-number

Grammar for datetime expressions

timeExpr    = timeTerm
timeTerm    = datetime | 
              varExpr | 
              timeFunc
timeFunc    = <see list below>

Parenthesis are not supported because there are not operators nor precedence to consider.

Return Function Params Description
datetime now (<none>) Current UTC time
datetime dateadd (timeExpr, numExpr, timePart) Increments/decrements a date part
datetime dateset (timeExpr, numExpr, timePart) Modifies a date part
datetime datetrunc (timeExpr, timePart) Returns a date truncated to datepart
datetime clamp (timeExpr, timeExpr, timeExpr) Coerce a datetime to be in a fixed range
datetime min (timeExpr, timeExpr) Returns the smaller of two given values
datetime max (timeExpr, timeExpr) Returns the larger of two given values
datetime ifelse (boolExpr, timeExpr, timeExpr) Conditional value

Grammar for string expressions

strExpr     = strTerm ('+' strTerm)*
strTerm     = string | 
              varExpr | 
              strFunc | 
              '(' strExpr ')'
strFunc     = <see list below>
Return Function Params Description
string trim (strExpr) Removes leading and trailing whitespaces
string lower (strExpr) Converts all characters to lowercase
string upper (strExpr) Converts all characters to uppercase
string unescape (strExpr) Replaces '\\', '\n', '\t' and '\"'
string + (strExpr, strExpr) Concatenate two strings
string min (strExpr, strExpr) Returns the smaller of two given values
string max (strExpr, strExpr) Returns the larger of two given values
string substr (strExpr, numExpr, numExpr) Extracts a substring from a given string
string replace (strExpr, strExpr, strExpr) Replaces all ocurrences of x in a string
string ifelse (boolExpr, strExpr, strExpr) Conditional value
string str (numExpr)
(timeExpr)
(boolExpr)
(strExpr)
Converts value to string

Grammar for boolean expressions

boolExpr     = boolTerm (boolInfixOp boolTerm)*
boolTerm     = (numExpr | timeExpr | strExpr) <  (numExpr | timeExpr | strExpr) |
               (numExpr | timeExpr | strExpr) <= (numExpr | timeExpr | strExpr) |
               (numExpr | timeExpr | strExpr) >  (numExpr | timeExpr | strExpr) |
               (numExpr | timeExpr | strExpr) >= (numExpr | timeExpr | strExpr) |
               (numExpr | timeExpr | strExpr) == (numExpr | timeExpr | strExpr) |
               (numExpr | timeExpr | strExpr) != (numExpr | timeExpr | strExpr) |
               boolean | 
               varExpr |
               boolFunc |
               '(' boolExpr ')'
boolInfixOp  = '&&' | '||' | '==' | '!='
boolFunc     = <see list below>
Return Function Params Description
boolean && (boolExpr, boolExpr) And
boolean || (boolExpr, boolExpr) Or
boolean < (numExpr, numExpr)
(timeExpr, timeExpr)
(strExpr, strExpr)
Less-than
boolean <= (numExpr, numExpr)
(timeExpr, timeExpr)
(strExpr, strExpr)
Less-than-or-equal
boolean > (numExpr, numExpr)
(timeExpr, timeExpr)
(strExpr, strExpr)
Greater-than
boolean >= (numExpr, numExpr)
(timeExpr, timeExpr)
(strExpr, strExpr)
Greater-than-or-equal
boolean == (numExpr, numExpr)
(timeExpr, timeExpr)
(strExpr, strExpr)
(boolExpr, boolExpr)
Equal-to
boolean != (numExpr, numExpr)
(timeExpr, timeExpr)
(strExpr, strExpr)
(boolExpr, boolExpr)
Not-equal-to
boolean not (boolExpr) Negate
boolean isinf (numExpr) Checks if a number is ± infinite
boolean isnan (numExpr) Checks if a number is a NaN
boolean iserror (numExpr)
(timeExpr)
(boolExpr)
(strExpr)
Checks if there is an error
boolean ifelse (boolExpr, boolExpr, boolExpr) Conditional value

Grammar for variable expressions

varExpr      = varTerm
varTerm      = variable | 
               varFunc
varFunc      = <see list below>
Return Function Params Description
variable variable (strExpr) Creates a reference to the variable name

Utility function to create references to variables on-the-fly.
variable("x[" + str($index) + "]")${x[1]}

Operators precedence

Expr implements the standard operators precedence

Precedence Type Symbols Associativity
1 Grouping (, ) left-to-right
2 Power ^ left-to-right
3 Not, plus, minus !, +, - right-to-left
4 Prod, div, mod *, /, % left-to-right
5 Add, subtract +, - left-to-right
6 Comparison <, <=, >, >= left-to-right
7 Equal ==, != left-to-right
8 And && left-to-right
9 Or || left-to-right