Skip to content

Instantly share code, notes, and snippets.

@Kimundi
Last active December 16, 2015 23:59
Show Gist options
  • Select an option

  • Save Kimundi/5517223 to your computer and use it in GitHub Desktop.

Select an option

Save Kimundi/5517223 to your computer and use it in GitHub Desktop.
// So, you have this trait:
trait CompiledRegularExpression {
fn full_match(&self, input: &str) -> bool;
fn partial_match(&self, input: &str) -> bool;
fn shortest_match(&self, input: &str) -> Option<(uint, uint)>;
fn longest_match(&self, input: &str) -> Option<(uint, uint)>;
fn shortest_match_slice<'a>(&self, input: &'a str) -> Option<&'a str>;
fn longest_match_slice<'a>(&self, input: &'a str) ->Option<&'a str>;
// ...
}
// And you have a re!() syntax extension that expands to a type with a
// implementation that does 'the fastest thing possible' depending on
// its input regular expression:
assert!( re!("[1-9]").full_match("5") )
// Here re!() gets a non-static input, so it compiles to a constructor call
// for a struct that represents the regular expression as a precompiled data
// structure. It implements the CompiledRegularExpression trait with
// method implementations that use the struct to match input.
let r = re!(read());
// Here re!() gets a static input, so it compiles to a empty struct
// implementing the CompiledRegularExpression trait with hardcoded method
// implementations for this regular expression.
let r = re!("[1-9]");
// In both cases you could then do:
assert!(r.full_match(input));
assert!(r.partial_match(input));
let a: (uint, uint) = r.shortest_match(input).unwrap();
let b: (uint, uint) = r.longest_match(input).unwrap();
let c: &str = r.shortest_match_slice(input).unwrap();
let d: &str = r.longest_match_slice(input).unwrap();
// Example expansion of 'let r = re!("[1-9]")'
// (it wouldn't literally expand to this, as re!() would just generate a AST,
// but this illustrates the idea)
let r = {
fn re_match_common(
input: &str,
shortest: bool,
partial: bool
) -> Option<(uint, uint)> {
// Placeholder code for the output of whatever algoritm
// generates the code:
if input.len() == 0 {
None
} else {
if partial {
for input.each_chari |c, i| {
match c {
'1' .. '9' => return Some((i,i+1)),
_ => ()
}
}
None
} else {
match input[0] {
'1' .. '9' if input.len() == 1 => Some((0,1))
_ => None
}
}
}
}
struct Empty;
impl CompiledRegularExpression for Empty {
fn full_match(&self, input: &str) -> bool {
re_match_common(input, false, false).is_some()
}
fn partial_match(&self, input: &str) -> bool {
re_match_common(input, false, true).is_some()
}
fn shortest_match(&self, input: &str) -> Option<(uint, uint)> {
re_match_common(input, true, false)
}
fn longest_match(&self, input: &str) -> Option<(uint, uint)> {
re_match_common(input, false, false)
}
fn shortest_match_slice<'a>(&self, input: &'a str) -> Option<&'a str> {
match re_match_common(input, true, false) {
Some((start, end)) => Some(input.slice(start, end))
None => None
}
}
fn longest_match_slice<'a>(&self, input: &'a str) ->Option<&'a str> {
match re_match_common(input, false, false) {
Some((start, end)) => Some(input.slice(start, end))
None => None
}
}
}
Empty
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment