Rules Grammar
The rules validation system is an implementation of the RETS 1.8 specification for Validation Expressions. The design consists of three key components: a Field that the rule is defined for (E.g. ListPrice), a keyword or Action (as used in spark) to apply to the Field and (optionally) an Expression for determining if or how to apply the Action. The expression language is documented here for reference.
The following grammar is spark's implementation of the expression grammar referenced in the RETS specification. The expression language provides a means to express criteria for requiring an Action, or to set the value for a rule's Field. The Expression may reference the rule's Field or other fields to enable the rule builder to access the new or existing values for a resource.
RESO 1.8 Grammar Rules Implementation
This document explains the grammar rules for the rules expression language syntax. We take a few shortcuts to accomodate a LALR(1) implentation using RACC. Refer back to the full spec in the RESO_1.8.md reference document.
Grammar Rules
Root: Each expression is a full fledged expression result
rule
target
: exp
| /* none */
;
Expressions
Expressions are boolean or arithemetic operations, or special system functions that return a literal value.
exp
: orExp
;
Conjunctive expressions using .AND.
or .OR.
.
orExp
: andExp
| orExp OR andExp
;
andExp
: notExp
| andExp AND notExp
;
Logic expressions using .NOT.
, =
, !=
, >
, >=
, <
, <=
, .CONTAINS.
or .IN.
.
notExp
: eqExpr
| NOT notExp
;
eqExpr
: cmpExp
| cmpExp EQ cmpExp
| cmpExp NE cmpExp
;
cmpExp
: cntExp
| cntExp GE cntExp
| cntExp LE cntExp
| cntExp LT cntExp
| cntExp GT cntExp
;
cntExp
: sumExp
| sumExp CONTAINS sumExp
| sumExp IN list
| sumExp IN funcExp
;
Arithmetic expressions using +
, -
, *
, /
or %
.
sumExp
: prodExp
| sumExp PLUS prodExp
| sumExp MINUS prodExp
| sumExp CONCAT prodExp
;
prodExp
: atomExp
| prodExp MULTIPLY atomExp
| prodExp DIVIDE atomExp
| prodExp MODULUS atomExp
;
Functions
Functions can take the place of an expression and must have a single return type (although some may return an list of one type).
Name | Description | Example |
---|---|---|
fbsAbs | Return the absolute value for a number. | fbsAbs(-1.0) = 1 |
fbsCoalesce | Return the default value if the first argument is nil | fbsCoalesce(.EMPTY., 100) |
fbsCustomField | Find a custom field for the record being processed. This function requires a group name and field name. | fbsCustomField('Group Name', 'Field Name') |
fbsGetOldValue | Return the existing value of a field. | fbsGetOldValue(StandardStatus) = 'Pending' .AND. StandardStatus = 'Active' |
fbsInterval | Add or substract a well defined time interval from a time. Supports hours , days , and weeks . |
ListDate + interval('90 days') |
fbsLookup | Returns the current restricted list of values for a PICKLIST field, as it has been modified by any SET_PICKLIST or RESTRICT_PICKLIST actions. | fbsLookup(City) |
fbsNumSelected | Returns the the count of fields in a group that are present with a value. | fbsNumSelected("Custom Field Group")) > 2 .AND. StandardStatus = 'Active' |
fbsPicklist | Return all the list values for a single field. For fields that require a related field, the function supports passing this field as a second parameter. | fbsPicklist(PostalCode,City) |
fbsSize | Return how many elements are in a list. | fbsSize((1,0,3,9)) = 4 |
fbsType | Return the type of the field as a character string (one of 'CHAR', 'INT', 'FLOAT', 'TIME','DATE','TIMESTAMP', 'BOOLEAN', and 'PICKLIST') The types are a string reflecting their namings as defined in 11.4.9.1 of the RETS 1.8 document | fbsType(City) = 'CHAR' |
IFF | Return one of two possible values based on a condition. | IFF(ListPrice > 0.0 .AND. StandardStatus = 'Active', .EMPTY., .ENTRY.) |
LOWER | Convert a character value to lowercase | LOWER('Fargo') = 'fargo' |
STRLEN | Return the length of a character string | STRLEN('Fargo') = 5 |
SUBSTR | Return a portion of a character string. The second parameter is a 1-indexe location to start, and the option final parameter is for the length of the substring. | SUBSTR('Fargo', 2, 3) = 'arg |
UPPER | Convert a character value to uppercase | UPPER('Fargo') = 'FARGO' |
funcExp
: func LPAR params RPAR
;
func
: FUNCTION
;
Nesting
This rule handles wrapping nested values and expressions
atomExp
: list
| value
| funcExp
;
Lists
Lists are used for .IN.
actions. They differ from nested
expressions in that they are comma delimmited and are associated with a list
action. They are similar to function parameters, but those are processed
separately below.
list
: LPAR RPAR
| LPAR list_items RPAR
;
list_items
: exp
| list_items COMMA exp
;
Params
Parameters are specifically for function input. These can be expressions, but they are evaluated prior to calling the function.
params
: param
| params COMMA param
;
param
: exp
;
Values
Values contain literals, fields and special context values. These are static in nature and should generally be predetermined before the rule evaluation begins.
value
: specValue
| charValue
| intValue
| floatValue
| fieldName
| timeValue
| dateValue
;
Variables
Variable special values are either user or rule specific. For example, use
.OLDVALUE.
to access the old record value of the current rule field.
specValue
: TRUE
| FALSE
| VARIABLE
| NULL
;
charValue: CHARACTER ;
intValue: INTEGER ;
floatValue: DECIMAL ;
Times
The format for time is ISO-8601, surrounded by pound signs.
- RETSDATETIME ::= "#" (date-time | partial-date-time) "#"
timeValue
: RETSDATETIME
;
Dates
NOTE: Experimental and subject to change or removal. The RESO docs do not indicate the presence of a date type, however the SparkAPI has one. This is to align with that.
- DATE ::= #YYYY-MM-DD#
dateValue
: DATE
;
Fields
The field names refer to the value of the field in the new record. Accessing
the old record is possible using the fbsGetOldValue(FieldName)
function.
fieldName
: FIELD
| VARIABLE FIELD
;