feat: add fancy-regex
This commit is contained in:
104
__misc/fancy-regex/src/main.rs
Normal file
104
__misc/fancy-regex/src/main.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use fancy_regex::internal::{analyze, compile, run_trace, Insn, Prog};
|
||||
use fancy_regex::*;
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args().skip(1);
|
||||
if let Some(cmd) = args.next() {
|
||||
if cmd == "parse" {
|
||||
if let Some(re) = args.next() {
|
||||
let e = Expr::parse_tree(&re);
|
||||
println!("{:#?}", e);
|
||||
}
|
||||
} else if cmd == "analyze" {
|
||||
if let Some(re) = args.next() {
|
||||
let tree = Expr::parse_tree(&re).unwrap();
|
||||
let a = analyze(&tree);
|
||||
println!("{:#?}", a);
|
||||
}
|
||||
} else if cmd == "compile" {
|
||||
if let Some(re) = args.next() {
|
||||
let r = Regex::new(&re).unwrap();
|
||||
r.debug_print();
|
||||
}
|
||||
} else if cmd == "run" {
|
||||
let re = args.next().expect("expected regexp argument");
|
||||
let r = Regex::new(&re).unwrap();
|
||||
let text = args.next().expect("expected text argument");
|
||||
let mut pos = 0;
|
||||
if let Some(pos_str) = args.next() {
|
||||
pos = usize::from_str(&pos_str).unwrap();
|
||||
}
|
||||
if let Some(caps) = r.captures_from_pos(&text, pos).unwrap() {
|
||||
print!("captures:");
|
||||
for i in 0..caps.len() {
|
||||
print!(" {}:", i);
|
||||
if let Some(m) = caps.get(i) {
|
||||
print!("[{}..{}] \"{}\"", m.start(), m.end(), m.as_str());
|
||||
} else {
|
||||
print!("_");
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
for cap in caps.iter() {
|
||||
println!("iterate {:?}", cap);
|
||||
}
|
||||
} else {
|
||||
println!("no match");
|
||||
}
|
||||
} else if cmd == "trace" {
|
||||
if let Some(re) = args.next() {
|
||||
let prog = prog(&re);
|
||||
if let Some(s) = args.next() {
|
||||
run_trace(&prog, &s, 0).unwrap();
|
||||
}
|
||||
}
|
||||
} else if cmd == "trace-inner" {
|
||||
if let Some(re) = args.next() {
|
||||
let tree = Expr::parse_tree(&re).unwrap();
|
||||
let a = analyze(&tree).unwrap();
|
||||
let p = compile(&a).unwrap();
|
||||
if let Some(s) = args.next() {
|
||||
run_trace(&p, &s, 0).unwrap();
|
||||
}
|
||||
}
|
||||
} else if cmd == "graph" {
|
||||
let re = args.next().expect("expected regexp argument");
|
||||
graph(&re);
|
||||
} else {
|
||||
println!("commands: parse|analyze|compile|graph <expr>, run|trace|trace-inner <expr> <input>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn graph(re: &str) {
|
||||
let prog = prog(re);
|
||||
println!("digraph G {{");
|
||||
for (i, insn) in prog.body.iter().enumerate() {
|
||||
let label = format!("{:?}", insn)
|
||||
.replace(r#"\"#, r#"\\"#)
|
||||
.replace(r#"""#, r#"\""#);
|
||||
println!(r#"{:3} [label="{}: {}"];"#, i, i, label);
|
||||
match *insn {
|
||||
Insn::Split(a, b) => {
|
||||
println!("{:3} -> {};", i, a);
|
||||
println!("{:3} -> {};", i, b);
|
||||
}
|
||||
Insn::Jmp(target) => {
|
||||
println!("{:3} -> {};", i, target);
|
||||
}
|
||||
Insn::End => {}
|
||||
_ => {
|
||||
println!("{:3} -> {};", i, i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("}}");
|
||||
}
|
||||
|
||||
fn prog(re: &str) -> Prog {
|
||||
let tree = Expr::parse_tree(re).expect("Expected parsing regex to work");
|
||||
let result = analyze(&tree).expect("Expected analyze to succeed");
|
||||
compile(&result).expect("Expected compile to succeed")
|
||||
}
|
||||
Reference in New Issue
Block a user