# Regular expressions

This chapter covers the regular expressions or regex syntax and programming use. The regex is an original implementation with its own syntax and execution model.

## Regular expression syntax

implements a regular expression engine via a special `Regex` object. A regular expression can be built implicitly or explicitly with the use of the `Regex` object. The regex syntax uses the `[` and `]` characters as block delimiters. When used in a source file, the lexical analyzer automatically recognizes a regex and built the object accordingly. In other word, the regex system is builtin in the language. The following example shows two equivalent way to define the same regex expression.

# syntax builtin regex (== [$d+] 2000) # true # explicit builtin regex (== (Regex "$d+") 2000) # true

In its first form, the `[` and `]` characters are used as syntax delimiters. The lexical analyzer automatically recognizes this token as a regex and built the equivalent `Regex` object. The second form is the explicit construction of the `Regex` object. Note also that the `[` and `]` characters are also used as regex block delimiters.

### Regex characters and meta-characters

Any character, except the one used as operators can be used in a regex. The `$` character is used as a meta-character -- or control character -- to represent a particular set of characters. For example, `[hello world]` is a regex which match only the `"hello world"` string. The `[$d+]` regex matches one or more digits. The following meta characters are builtin in the regex engine.

### Regular expression meta-characters

Character | Description
--- | ---
$a | matches any letter or digit
$b | matches any blank characters
$d | matches any digit
$e | matches eol, cr and eof
$l | matches any lower case letter
$n | matches eol or cr
$s | matches any letter
$u | matches any upper case letter
$v | matches any valid afnix constituent
$w | matches any word constituent
$x | matches any hexadecimal characters

The uppercase version is the complement of the corresponding lowercase character set.

### Regular expression meta-characters complement

Character | Description
--- | ---
$A | any character except letter or digit
$B | any character except blank characters
$D | any character except digit
$E | any character except eol, cr and eof
$L | any character except lower case letter
$N | any character except eol or cr
$S | any character except letter
$U | any character except upper case letter
$V | any character except afnix constituent
$W | any character except word constituent
$X | any character except hex characters

A character which follows a `$` character and that is not a meta character is treated as a normal character. For example `$[` is the `[` character. A quoted string can be used to define character matching which could otherwise be interpreted as control characters or operator. A quoted string also interprets standard escaped sequences but not meta characters.

(== [$d+] 2000) # true (== ["$d+"] 2000) # false

### Regex character set

A character set is defined with the `<` and `>` characters. Any enclosed character defines a character set. Note that meta characters are also interpreted inside a character set. For example, `<$d+->` represents any digit or a plus or minus. If the first character is the `^` character in the character set, the character set is complemented with regards to its definition.

### Regex blocks and operators

The `[` and `]` characters are the regex sub-expressions delimiters. When used at the top level of a regex definition, they can identify an implicit object. Their use at the top level for explicit construction is optional. The following example is strictly equivalent.

# simple real number check const real-1 (Regex "$d*.$d+") # another way with [] characters const real-2 (Regex "[$d*.$d+]")

Sub-expressions can be nested -- that's their role -- and combined with operators. There is no limit in the nesting level.

# pair of digit testing (== [$d$d[$d$d]+] 2000) # true (== [$d$d[$d$d]+] 20000) # false

The following unary operators can be used with single character, control characters and sub-expressions.

### Regular expression operators

Operator | Description
--- | ---
* | match 0 or more times
+ | match 1 or more times
? | match 0 or 1 time
| | alternation

Alternation is an operator which work with a secondary expression. Care should be taken when writing the right sub-expression. For example the following regex `[$d|hello]` is equivalent to `[[$d|h]ello]`. In other word, the minimal first sub-expression is used when compiling the regex.

### Grouping

Groups of sub-expressions are created with the `(` and `)` characters. When a group is matched, the resulting sub-string is placed on a stack and can be used later. In this respect, the regex engine can be used to extract sub-strings. The following example extracts the month, day and year from a particular date format: `[($d$d):($d$d):($d$d$d$d)]`. This regex assumes a date in the form mm:dd:yyyy.

if (== (const re [($d$d):($d$d)]) "12:31") { trans hr (re:get 0) trans mn (re:get 1) }

Grouping is the mechanism to retrieve sub-strings when a match is successful. If the regex is bound to a symbol, the `get` method can be used to get the sub-string by index.

## Regex object

Although a regex can be built implicitly, the `Regex` object can also be used to build a new regex. The argument is a string which is compiled during the object construction.

### Literal object

A `Regex` object is a literal object. This means that the `to-string` method is available and that a call to the `println` special form will work directly.

const re (Regex "$d+") println re # $d+ println re:to-string # [$d+]

### Regex operators

The `==` and `!=` operators are the primary operators to perform a regex match. The `==` operator returns `true` if the regex matches the string argument from the beginning to the end of string. Such operator implies the begin and end of string anchoring. The `<` operator returns true if the regex matches the string or a substring or the string argument.

### Regex methods

The primary regex method is the `get` method which returns by index the sub-string when a group has been matched. The `length` method returns the number of group match.

if (== (const re [($d$d):($d$d)]) "12:31") { re:length # 2 re:get 0 # 12 re:get 1 # 31 }

The `match` method returns the first string which is matched by the regex.

const regex [$d+] regex:match "Happy new year 2000" # 2000

The `replace` method any occurrence of the matching string with the string argument.

const regex [$d+] regex:replace "Hello year 2000" "3000" # hello year 3000

### Argument conversion

The use of the `Regex` operators implies that the arguments are evaluated as literal object. For this reason, an implicit string conversion is made during such operator call. For example, passing the integer `12` or the string `"12"` is strictly equivalent. Care should be taken when using this implicit conversion with real numbers.