Last active
December 16, 2015 23:59
-
-
Save Kimundi/5517223 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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