// examples/regex_toolkit — runnable demonstration of the
// `src/regex_engine` direction on a realistic log-scrubbing task:
// extraction with named groups, redaction via replace_all, tokenizing via
// split, and a ReDoS-resistant run of a classically catastrophic pattern.
//
// Run with:
// moon run examples/regex_toolkit
///|
fn compile(pattern : String) -> @re.Pattern {
match @re.Pattern::compile(pattern) {
Ok(p) => p
Err(e) => abort("failed to compile /\{pattern}/: error at \{e.pos()}")
}
}
///|
fn slice(text : String, m : @re.Match) -> String {
let sb = StringBuilder::new()
let chars = text.to_array()
for i in m.start.. Unit {
println("=== extraction: IPv4 + status code from an access log ===")
println("input : \{log_line}")
let ip = compile(@re.demo_ipv4())
match ip.find(log_line) {
Some(m) => println("client ip : \{slice(log_line, m)}")
None => println("client ip : ")
}
let status = compile(" (?[1-5][0-9][0-9]) ")
match status.captures(log_line) {
Some(caps) =>
match caps.name("code") {
Some(m) => println("status code : \{slice(log_line, m)}")
None => println("status code : ")
}
None => println("status code : ")
}
println("")
}
///|
fn redaction_demo() -> Unit {
println("=== redaction: scrub emails and IPs before shipping logs ===")
let text = "user alice@example.com logged in from 10.0.42.7; admin bob@corp.io from 192.168.1.13"
println("input : \{text}")
let email = compile(@re.demo_email())
let ip = compile(@re.demo_ipv4())
let pass1 = email.replace_all(text, "")
let pass2 = ip.replace_all(pass1, "")
println("output: \{pass2}")
println(
"emails found: \{email.find_all(text).length()}, ips found: \{ip.find_all(text).length()}",
)
println("")
}
///|
fn split_demo() -> Unit {
println("=== split: CSV-ish tokenizing with a delimiter class ===")
let row = "dijkstra, astar;bidirectional hub-labels,cch"
let sep = compile("[,;\\s]+")
let fields = sep.split(row)
println("input : \{row}")
let sb = StringBuilder::new()
sb.write_string("[")
for i in 0.. 0 {
sb.write_string(", ")
}
sb.write_string(fields[i])
}
sb.write_string("]")
println("fields: \{sb.to_string()}")
println("")
}
///|
fn redos_demo() -> Unit {
println("=== ReDoS resistance: (a|a)*b vs 30 a's + '!' ===")
let evil = compile("(a|a)*b")
let sb = StringBuilder::new()
for _ in 0..<30 {
sb.write_char('a')
}
sb.write_char('!')
let input = sb.to_string()
let matched = evil.is_match(input)
println("pattern: (a|a)*b input: a^30 + '!'")
println(
"matched: \{matched} — completed instantly: the default engine is the linear-time Pike VM / lazy DFA, not exponential backtracking",
)
}
///|
fn main {
extraction_demo(
"203.0.113.9 - - [12/Jul/2026:14:00:07] \"GET /route HTTP/1.1\" 200 6417",
)
redaction_demo()
split_demo()
redos_demo()
}