REGEX <- BEGIN_ANCHOR REGEX_BODY END_ANCHOR
NONEMPTY_REGEX_BODY <- DOLLAR NONEMPTY_REGEX_BODY / QUANT_SYMBOLS REGEX_BODY
REGEX_BODY <- NONEMPTY_REGEX_BODY /
BEGIN_ANCHOR <- '^'?
END_ANCHOR <- '$'*
DOLLAR <- '$'
QUANT_SYMBOLS <- QUANT_SYMBOL QUANT_SYMBOLS / QUANT_SYMBOL
QUANT_SYMBOL <- SYMBOL QUANTIFIER / TOP_SYMBOL
SYMBOL <- DOLLAR / TOP_SYMBOL
TOP_SYMBOL <- !'$' MACHINE_SYMBOL
MACHINE_SYMBOL <- NEGATED_CHAR_CLASS / CHAR_CLASS / IMPLICIT_CHAR_CLASS / ALTERNATION / MACHINE_CHAR
MACHINE_CHAR <- ESCAPED_OR_SINGLE_CHAR
QUANTIFIER <- '*' / '+' / ('{' INTEGER '}') / ('{' INTEGER ',' INTEGER '}')
INTEGER <- '0' / [1-9] [0-9]*
CHAR_CLASS <- '[' CHARS ']'
NEGATED_CHAR_CLASS <- '[' '^' CHARS ']'
IMPLICIT_CHAR_CLASS <- PRESET_CHAR_CLASS
PRESET_CHAR_CLASS <- DIGIT_CHAR / WHITE_CHAR / NONWHITE_CHAR / WILD_CHAR
CHARS <- CHAR CHARS / CHAR
CHAR <- PRESET_CHAR_CLASS / CHAR_RANGE / CHAR_INSIDE_CLASS
DIGIT_CHAR <- '\\d'
WHITE_CHAR <- '\\s'
NONWHITE_CHAR <- '\\S'
WILD_CHAR <- '.'
CHAR_RANGE <- CHAR_INSIDE_CLASS '-' CHAR_INSIDE_CLASS
CHAR_INSIDE_CLASS <- !']' ESCAPED_OR_SINGLE_CHAR
ESCAPED_OR_SINGLE_CHAR <- ESCAPED_CHAR / SINGLE_CHAR
ESCAPED_CHAR <- '\\' OCTAL / '\\' 'x' HEX / '\\' ESCAPE_CHAR
SINGLE_CHAR <- .
ESCAPE_CHAR <- .
OCTAL <- [0-2][0-7][0-7] / [0-7][0-7]
HEX <- [0-9a-fA-F] [0-9a-fA-F]
ALTERNATION <- '(' ALT_OPTIONS ')'
ALT_OPTIONS <- ALT_SYMBOLS '|' ALT_OPTIONS / ALT_SYMBOLS
ALT_SYMBOLS <- ALT_SYMBOL ALT_SYMBOLS /
ALT_SYMBOL <- !'|' !')' QUANT_ALT_SYMBOL
QUANT_ALT_SYMBOL <- MACHINE_SYMBOL QUANTIFIER / MACHINE_SYMBOL
