DECLARE and CALL

Overview of the DECLARE and CALL Operators

Use the DECLARE operator to create parameterized pieces of GLASS code that can form complex, context-specific expressions from simple and easy-to-understand base expressions. These parameterized blocks of code can be referenced in multiple places using the CALL operator.

The generic GLASS syntax for DECLARE and CALL is:

DECLARE '<label>', ${param1}, ${param2}, , ${paramN} {
  <expression>
}

CALL '<label>', param1, param2, , paramN

Defining the Parameters

  • Parameters are delimited by a dollar sign $ followed immediately by a matched pair of curly braces {} (e.g. ${parameter}).
  • The parameter identifier can only consist of one or more alphanumeric a-zA-Z0-9 or underscore _ characters but cannot start with a digit 0-9.
  • If the GLASS code to be called requires a parameter to be used in an integer context, an integer parameter should be specified or it will result in a compilation error.
  • An integer parameter can be used in a string context, only if the parameter is embedded within a string context.
  • Ranges may be provided as single parameters, e.g. 1-2.
  • Parameters can be pieces of GLASS code, as long as the code contains no unquoted commas ,.
  • If a positional parameter is omitted, that parameter will be not be included in the resultant code.

DECLARE and CALL Example 1

You want to define a reusable GLASS expression that searches for an individual by first name then last name, or last name then first name, to effectively handle subject access requests (SARs).

In certain instances, the search needs to be case-sensitive, or the subject's name may contain different accents on various letters. The first name and last name can be joined by the tab \t, whitespace  , comma ,, or pipe | character, and should be matched across line breaks.

Part 1 - Identifying and Defining the Variable Parameters

Based on the requirements for the SAR data type, we identify the components or code that can be parameterized, and define the outline for the DECLARE template.

  1. The option to search for the subject's full name case insensitively.
  2. The option to match the subject's full name in its original and normalized form.
  3. The subject's first and last name.
  4. The ALIAS label that can be referenced by the REFER operator.
DECLARE 'SAR_FULLNAME_TEMPLATE', ${case}, ${decompose}, ${first_name}, ${last_name}, ${identifier} {
  # Main GLASS code to be added.
}

Part 2 - Search for First Name Followed By Last Name

Next, we define the GLASS expression that searches for the subject's first name followed by the last name, with valid separators.

DECLARE 'SAR_FULLNAME_TEMPLATE', ${identifier}, ${case}, ${decompose}, ${first_name}, ${last_name} {
  ALIAS 'SAR_FIRST_LAST_NAME_${identifier}' \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${first_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${last_name}' BOUND RIGHT NONALNUM)
}  

Notes on the GLASS expression:

  1. The ${identifier} parameter is included in the ALIAS label to enable the use of the SAR_FULLNAME_TEMPLATE template more than once in a single data type.
  2. The ALIAS keyword is used to improve readability of the GLASS expression. This will become more noticeable as we build out this data type.

Part 3 - Search for Last Name Followed By First Name

Following a similar structure as Part 2, we define the GLASS expression that searches for the subject's last name followed by the first name, with valid separators.

DECLARE 'SAR_FULLNAME_TEMPLATE', ${identifier}, ${case}, ${decompose}, ${first_name}, ${last_name} {
  ALIAS 'SAR_FIRST_LAST_NAME_${identifier}' \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${first_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${last_name}' BOUND RIGHT NONALNUM)

  ALIAS 'SAR_LAST_FIRST_NAME_${identifier}' \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${last_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${first_name}' BOUND RIGHT NONALNUM)
}  

Part 4 - Reference the ALIAS Expressions

Lastly, we need to reference the ALIAS labels for pattern matching to actually happen.

DECLARE 'SAR_FULLNAME_TEMPLATE', ${identifier}, ${case}, ${decompose}, ${first_name}, ${last_name} {
  ALIAS 'SAR_FIRST_LAST_NAME_${identifier}' \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${first_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${last_name}' BOUND RIGHT NONALNUM)

  ALIAS 'SAR_LAST_FIRST_NAME_${identifier}' \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${last_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${first_name}' BOUND RIGHT NONALNUM)

  REFER 'SAR_FIRST_LAST_NAME_${identifier}' OR \
  REFER 'SAR_LAST_FIRST_NAME_${identifier}'
}  

Part 5 - Reference the DECLARE Template with the CALL Operator

Use the CALL operator to reference and use the defined template.

DECLARE 'SAR_FULLNAME_TEMPLATE', ${identifier}, ${case}, ${decompose}, ${first_name}, ${last_name} {
  ALIAS 'SAR_FIRST_LAST_NAME_${identifier}' \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${first_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${last_name}' BOUND RIGHT NONALNUM)

  ALIAS 'SAR_LAST_FIRST_NAME_${identifier}' \
    # Search for the subject's last name, bounded by non-alphanumeric characters to the left.
    (WORD ${case} ${decompose} '${last_name}' BOUND LEFT NONALNUM) THEN \
    # Search for 1-5 valid separators between the first name and last name.
    (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
    # Search for the subject's first name, bounded by non-alphanumeric characters to the right.
    (WORD ${case} ${decompose} '${first_name}' BOUND RIGHT NONALNUM)

  REFER 'SAR_FIRST_LAST_NAME_${identifier}' OR \
  REFER 'SAR_LAST_FIRST_NAME_${identifier}'
}  

CALL 'SAR_FULLNAME_TEMPLATE', 'BRUCE_WAYNE', NOCASE, , 'Bruce', 'Wayne'

The last line of GLASS code resolves to:

ALIAS 'SAR_FIRST_LAST_NAME_BRUCE_WAYNE' \
  # Search for the subject's first name, bounded by non-alphanumeric characters to the left.
  (WORD NOCASE 'Bruce' BOUND LEFT NONALNUM) THEN \
  # Search for 1-5 valid separators between the first name and last name.
  (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
  # Search for the subject's last name, bounded by non-alphanumeric characters to the right.
  (WORD NOCASE 'Wayne' BOUND RIGHT NONALNUM)

ALIAS 'SAR_FIRST_LAST_NAME_BRUCE_WAYNE' \
  # Search for the subject's last name, bounded by non-alphanumeric characters to the left.
  (WORD NOCASE 'Wayne' BOUND LEFT NONALNUM) THEN \
  # Search for 1-5 valid separators between the first name and last name.
  (RANGE ' ,|\t\r\n\f\v' TIMES 1-5) THEN \
  # Search for the subject's first name, bounded by non-alphanumeric characters to the right.
  (WORD NOCASE 'Bruce' BOUND RIGHT NONALNUM)

REFER 'SAR_FIRST_LAST_NAME_BRUCE_WAYNE' OR \
REFER 'SAR_LAST_FIRST_NAME_BRUCE_WAYNE'

Example 1 - Match Samples

1
2
The CEO of Wayne Corporations is Bruce, Wayne.
Customer name: Wayne Bruce

DECLARE and CALL Example 2

You want to define a GLASS template that searches for 15-digit American Express (AMEX) card numbers that are (i) straight 15 digits, (ii) grouped in 4-6-5 digits separated by a whitespace   character, and (iii) grouped in 4-6-5 digits separated by a hyphen - character.

The LUHNCHKSUM checksum module should be applied to validate the check digit for potential AMEX card number matches.

Part 1 - Identifying and Defining the Variable Parameters

Based on the requirements for the AMEX data type, we identify the components or code that can be parameterized, and define the outline for the DECLARE template.

  1. The ALIAS label identifier for the different 15-digit card number formats.
  2. The GLASS expression for different separator characters (e.g. no separator, whitespace, or hyphen).
DECLARE 'CHD_AMEX_15DIGIT_TEMPLATE', ${separator_type}, ${separator_exp} {
  # Main GLASS code to be added.
}

Part 2 - Define the Prefix for AMEX Numbers

Before building out the rest of the AMEX data type template, we can define a namespace for valid 2-digit prefixes (34 and 37) for AMEX card numbers using the MAP operator. This will then be referenced in the main GLASS expression for the data type.

MAP 'CHD_AMEX_PREFIX' 34, 37

DECLARE 'CHD_AMEX_15DIGIT_TEMPLATE', ${separator_type}, ${separator_exp} {
  # Main GLASS code to be added.
}

Part 3 - Define the ALIAS Label

Next, we define the ALIAS label which contains the ${separator_type} parameter to differentiate the three AMEX card number formats.

MAP 'CHD_AMEX_PREFIX' 34, 37

DECLARE 'CHD_AMEX_15DIGIT_TEMPLATE', ${separator_type}, ${separator_exp} {
  ALIAS 'CHD_AMEX_${separator_type}' \
  # Main GLASS code to be added.
}

Part 4 - Define Main Expression To Search for AMEX Card Numbers

1 MAP 'CHD_AMEX_PREFIX' 34, 37
2  
3 DECLARE 'CHD_AMEX_15DIGIT_TEMPLATE', ${separator_type}, ${separator_exp} {
4   ALIAS 'CHD_AMEX_${separator_type}' \
5     ( \
6       GROUP 'CHD_AMEX_PREFIX' THEN RANGE DIGIT TIMES 2 \
7       ${separator_exp} \
8       THEN RANGE DIGIT TIMES 6 \
9       ${separator_exp} \
10       THEN RANGE DIGIT TIMES 5 \
11     ) CHECK 'LUHNCHKSUM'
12 }

Notes on the GLASS expression:

  1. For AMEX card number formats with whitespace or hyphen separators, the 15-digit number is grouped into 4-6-5 digits. This is expressed in line 6, line 8, and line 10.
  2. To account for the various number formats, we include the ${separator_exp} parameter on line 7 and line 9. For the straight 15-digit card number format, the expression would be left blank. For card number formats with separator characters, the ${separator_exp} value would be replaced with the relevant GLASS code. For example, THEN WORD ' ', or THEN WORD '-'.

Part 5 - Reference the DECLARE Template with the CALL Operator

Use the CALL operator to reference and use the defined template for the different AMEX card number formats.

1 MAP 'CHD_AMEX_PREFIX' 34, 37
2  
3 DECLARE 'CHD_AMEX_15DIGIT_TEMPLATE', ${separator_type}, ${separator_exp} {
4   ALIAS 'CHD_AMEX_${separator_type}' \
5     ( \
6       GROUP 'CHD_AMEX_PREFIX' THEN RANGE DIGIT TIMES 2 \
7       ${separator_exp} \
8       THEN RANGE DIGIT TIMES 6 \
9       ${separator_exp} \
10       THEN RANGE DIGIT TIMES 5 \
11     ) CHECK 'LUHNCHKSUM'
12 }
13  
14 CALL 'CHD_AMEX_15DIGIT_TEMPLATE', 'STRAIGHT',
15 CALL 'CHD_AMEX_15DIGIT_TEMPLATE', 'SPACE', THEN WORD ' '
16 CALL 'CHD_AMEX_15DIGIT_TEMPLATE', 'HYPHEN', THEN WORD '-'

Based on the above GLASS code, line 14 resolves to:

ALIAS 'CHD_AMEX_STRAIGHT' \
  ( \
    GROUP 'CHD_AMEX_PREFIX' THEN RANGE DIGIT TIMES 2 \
     \
    THEN RANGE DIGIT TIMES 6 \
     \
    THEN RANGE DIGIT TIMES 5 \
  ) CHECK 'LUHNCHKSUM'

Line 15 resolves to:

ALIAS 'CHD_AMEX_SPACE' \
  ( \
    GROUP 'CHD_AMEX_PREFIX' THEN RANGE DIGIT TIMES 2 \
    THEN WORD ' ' \
    THEN RANGE DIGIT TIMES 6 \
    THEN WORD ' ' \
    THEN RANGE DIGIT TIMES 5 \
  ) CHECK 'LUHNCHKSUM'

Line 16 resolves to:

ALIAS 'CHD_AMEX_HYPHEN' \
  ( \
    GROUP 'CHD_AMEX_PREFIX' THEN RANGE DIGIT TIMES 2 \
    THEN WORD '-' \
    THEN RANGE DIGIT TIMES 6 \
    THEN WORD '-' \
    THEN RANGE DIGIT TIMES 5 \
  ) CHECK 'LUHNCHKSUM'

Part 6 - Reference the ALIAS Labels

Lastly, we need to reference the ALIAS labels for pattern matching to actually happen.

MAP 'CHD_AMEX_PREFIX' 34, 37

DECLARE 'CHD_AMEX_15DIGIT_TEMPLATE', ${separator_type}, ${separator_exp} {
  ALIAS 'CHD_AMEX_${separator_type}' \
    ( \
      GROUP 'CHD_AMEX_PREFIX' THEN RANGE DIGIT TIMES 2 \
      ${separator_exp} \
      THEN RANGE DIGIT TIMES 6 \
      ${separator_exp} \
      THEN RANGE DIGIT TIMES 5 \
    ) CHECK 'LUHNCHKSUM'
}

CALL 'CHD_AMEX_15DIGIT_TEMPLATE', 'STRAIGHT',
CALL 'CHD_AMEX_15DIGIT_TEMPLATE', 'SPACE', THEN WORD ' '
CALL 'CHD_AMEX_15DIGIT_TEMPLATE', 'HYPHEN', THEN WORD '-'

# AMEX card number data type.
REFER 'CHD_AMEX_STRAIGHT' OR \
REFER 'CHD_AMEX_SPACE' OR \
REFER 'CHD_AMEX_HYPHEN'

Example 2 - Match Samples

1 Straight AMEX card number 371020503324823
2 AMEX card number with whitespace separators 3710 205033 24823
3 AMEX card number with hyphen separators 3710-205033-24823

Declare and Call Challenge 1

You want to build a GLASS data type that searches for 16-digit payment card numbers issued by various card networks.

  • The simplified requirements for this data type are as below:
  • The card numbers are in groups of 4 digits, separated by a whitespace   or hyphen - character.
  • 8-digit BIN ranges for the card networks of interest are:
    • Mastercard - 5100_0000-5599_9999
    • Visa - 4000_0000-4999_9999
    • Diners Club International - 3600_0000-3699_9999
  • The Luhn checksum algorithm must be applied to validate the payment card numbers.
  • Payment card numbers are bounded by non-alphanumeric characters.

Note: The BIN ranges here may not be up-to-date. These values are intended only for use in this example.

Example GLASS Code

MAP 'CHD_BIN_DINERSCLUBINT' 3600_0000_0000_0000-3699_9999_9999_9999
MAP 'CHD_BIN_MASTERCARD' 5100_0000_0000_0000-5599_9999_9999_9999
MAP 'CHD_BIN_VISA' 4000_0000_0000_0000-4999_9999_9999_9999

DECLARE 'CHD_4_GROUP_SEPARATOR_TEMPLATE', \
    ${chd_network}, ${separator_label}, ${separator_character} {
  ALIAS 'CHD_${chd_network}_16DIGIT_SEPARATOR_${separator_label}' \
  ( \
    RANGE DIGIT TIMES 4 THEN WORD '${separator_character}' THEN \
    RANGE DIGIT TIMES 4 THEN WORD '${separator_character}' THEN \
    RANGE DIGIT TIMES 4 THEN WORD '${separator_character}' THEN \
    RANGE DIGIT TIMES 4 \
  ) REQUIRE STRIP 'CHD_BIN_${chd_network}' BOUND NONALNUM CHECK 'LUHNCHKSUM'

  REFER 'CHD_${chd_network}_16DIGIT_SEPARATOR_${separator_label}'
}

CALL 'CHD_4_GROUP_SEPARATOR_TEMPLATE', 'DINERSCLUBINT', 'HYPHEN', '-'
CALL 'CHD_4_GROUP_SEPARATOR_TEMPLATE', 'DINERSCLUBINT', 'SPACE', ' '

CALL 'CHD_4_GROUP_SEPARATOR_TEMPLATE', 'MASTERCARD', 'HYPHEN', '-'
CALL 'CHD_4_GROUP_SEPARATOR_TEMPLATE', 'MASTERCARD', 'SPACE', ' '

CALL 'CHD_4_GROUP_SEPARATOR_TEMPLATE', 'VISA', 'HYPHEN', '-'
CALL 'CHD_4_GROUP_SEPARATOR_TEMPLATE', 'VISA', 'SPACE', ' '