zena:regex

zena
import {…} from 'zena:regex';

Classes

Ast

zena
final class Ast
Constructors
zena
new(op: Op)
#
Properties
zena
var op: Op
#
zena
var flags
#
zena
var sub
#
zena
var runes
#
zena
var min
#
zena
var max
#
zena
var cap
#
zena
var name
#
Methods
zena
static create(op: Op, flags: Flags): Ast
#

Match

zena
final class Match
Constructors
zena
new(value: String, index: i32, groups: Array<String>, groupNames: Array<String>)
#
Properties
zena
value: String
#
zena
index: i32
#
zena
groups: Array<String>
#
Methods
zena
group(name: String): String | null
#

Regex

zena
final class Regex

Regular expression engine for pattern matching in strings.

This is a Thompson NFA-based engine (similar to RE2 and Go's regexp) that guarantees O(n*m) time complexity where n is input length and m is pattern size. It never backtracks exponentially, making it safe for untrusted input.

Basic Usage

text
let re = new Regex('\\d+');          // Match one or more digits
re.test('abc123');                   // true
let m = re.exec('abc123');           // Match object with value='123'

Use the regex tag to avoid double-escaping backslashes:

text
import {regex} from 'zena:regex';
let re = regex`\d+`;                 // No double backslash needed
let email = regex`\w+@\w+\.\w+`;

Supported Features

  • Literals: abc matches "abc"
  • Alternation: cat|dog matches "cat" or "dog"
  • Character classes: [a-z], [^0-9], \d, \D, \w, \W, \s, \S
  • Quantifiers: * (0+), + (1+), ? (0-1), {n}, {n,}, {n,m}
  • Non-greedy: *?, +?, ??, {n,m}?
  • Groups: (...) capturing, (?:...) non-capturing
  • Named groups: (?P<name>...) with match.group('name')
  • Anchors: ^ start, $ end, \b word boundary, \B non-boundary
  • Any char: . (any except newline), with (?s) matches newline too
  • Escapes: \n, \t, \r, \., \\, etc.
  • Flags: (?i) case-insensitive, (?m) multiline, (?s) dot-all

Main API

  • test(input) - Returns true if pattern matches anywhere in input
  • exec(input, startIndex?) - Returns Match object or null
  • matchAll(input) - Returns array of all Match objects
  • replace(input, replacement) - Replace first match
  • replaceAll(input, replacement) - Replace all matches
  • split(input) - Split string around matches

Stateless Design

Unlike JavaScript's RegExp, this class is stateless - there is no lastIndex property. Each method call is independent. To match from a specific position, pass startIndex to exec():

text
let re = regex`\w+`;
let m1 = re.exec('foo bar', 0);      // matches 'foo' at 0
let m2 = re.exec('foo bar', 4);      // matches 'bar' at 4

Escaping in String Literals

When using new Regex(pattern), backslashes must be doubled because string literals process escapes first:

text
new Regex('\\d+');     // Correct: matches digits
new Regex('\d+');      // Wrong: \d is not a valid string escape

The regex template tag avoids this by using raw strings.

Constructors
zena
new(pattern: String, flags: String = '')
#
Methods
zena
test(input: String): boolean
#
zena
exec(input: String, startIndex: i32 = 0): Match | null
#
zena
matchAll(input: String): Array<Match>
#
zena
replace(input: String, replacement: String): String
#
zena
replace(input: String, replacer: (m: Match) => String): String
#
zena
replaceAll(input: String, replacement: String): String
#
zena
replaceAll(input: String, replacer: (m: Match) => String): String
#
zena
split(input: String): Array<String>
#

Enums

Op

zena
enum Op
Members
zena
NoMatch
#
zena
EmptyMatch
#
zena
Literal
#
zena
CharClass
#
zena
AnyCharNotNL
#
zena
AnyChar
#
zena
BeginLine
#
zena
EndLine
#
zena
BeginText
#
zena
EndText
#
zena
WordBoundary
#
zena
NoWordBoundary
#
zena
Capture
#
zena
Star
#
zena
Plus
#
zena
Quest
#
zena
Repeat
#
zena
Concat
#
zena
Alternate
#

Flags

zena
enum Flags
Members
zena
None
#
zena
FoldCase
#
zena
DotNL
#
zena
OneLine
#
zena
NonGreedy
#
zena
WasDollar
#

Functions

parsePattern

zena
function parsePattern(pattern: String, flags: Flags): Ast

regex

zena
function regex(strings: TemplateStringsArray, values: FixedArray<String>)

Tagged template literal for creating Regex objects with raw strings. Backslashes don't need escaping: let re = regex\d+; // instead of Regex.compile("\d+") let re = regex\w+@\w+; // instead of Regex.compile("\w+@\w+")