/// documentation.
#[deriving(Clone)]
#[allow(visible_private_types)]
-pub struct Regex {
- /// The representation of `Regex` is exported to support the `regex!`
- /// syntax extension. Do not rely on it.
- ///
- /// See the comments for the `program` module in `lib.rs` for a more
- /// detailed explanation for what `regex!` requires.
+pub enum Regex {
+ // The representation of `Regex` is exported to support the `regex!`
+ // syntax extension. Do not rely on it.
+ //
+ // See the comments for the `program` module in `lib.rs` for a more
+ // detailed explanation for what `regex!` requires.
#[doc(hidden)]
- pub original: String,
+ Dynamic(Dynamic),
#[doc(hidden)]
- pub names: Vec<Option<String>>,
+ Native(Native),
+}
+
+#[deriving(Clone)]
+#[doc(hidden)]
+pub struct Dynamic {
+ original: String,
+ names: Vec<Option<String>>,
#[doc(hidden)]
- pub p: MaybeNative,
+ pub prog: Program
}
-impl fmt::Show for Regex {
- /// Shows the original regular expression.
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", self.original)
- }
+#[doc(hidden)]
+pub struct Native {
+ #[doc(hidden)]
+ pub original: &'static str,
+ #[doc(hidden)]
+ pub names: &'static [Option<&'static str>],
+ #[doc(hidden)]
+ pub prog: fn(MatchKind, &str, uint, uint) -> Vec<Option<uint>>
}
-pub enum MaybeNative {
- Dynamic(Program),
- Native(fn(MatchKind, &str, uint, uint) -> Vec<Option<uint>>),
+impl Clone for Native {
+ fn clone(&self) -> Native { *self }
}
-impl Clone for MaybeNative {
- fn clone(&self) -> MaybeNative {
- match *self {
- Dynamic(ref p) => Dynamic(p.clone()),
- Native(fp) => Native(fp),
- }
+impl fmt::Show for Regex {
+ /// Shows the original regular expression.
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_str())
}
}
pub fn new(re: &str) -> Result<Regex, parse::Error> {
let ast = try!(parse::parse(re));
let (prog, names) = Program::new(ast);
- Ok(Regex {
+ Ok(Dynamic(Dynamic {
original: re.to_strbuf(),
- names: names, p: Dynamic(prog),
- })
+ names: names,
+ prog: prog,
+ }))
}
/// Returns true if and only if the regex matches the string given.
}
new.append(text.slice(last_match, text.len()))
}
+
+ /// Returns the original string of this regex.
+ pub fn as_str<'a>(&'a self) -> &'a str {
+ match *self {
+ Dynamic(Dynamic { ref original, .. }) => original.as_slice(),
+ Native(Native { ref original, .. }) => original.as_slice(),
+ }
+ }
+
+ #[doc(hidden)]
+ #[allow(visible_private_types)]
+ #[experimental]
+ pub fn names_iter<'a>(&'a self) -> NamesIter<'a> {
+ match *self {
+ Native(ref n) => NamesIterNative(n.names.iter()),
+ Dynamic(ref d) => NamesIterDynamic(d.names.iter())
+ }
+ }
+
+ fn names_len(&self) -> uint {
+ match *self {
+ Native(ref n) => n.names.len(),
+ Dynamic(ref d) => d.names.len()
+ }
+ }
+
+}
+
+enum NamesIter<'a> {
+ NamesIterNative(::std::slice::Items<'a, Option<&'static str>>),
+ NamesIterDynamic(::std::slice::Items<'a, Option<String>>)
+}
+
+impl<'a> Iterator<Option<String>> for NamesIter<'a> {
+ fn next(&mut self) -> Option<Option<String>> {
+ match *self {
+ NamesIterNative(ref mut i) => i.next().map(|x| x.map(|s| s.to_strbuf())),
+ NamesIterDynamic(ref mut i) => i.next().map(|x| x.as_ref().map(|s| s.to_strbuf())),
+ }
+ }
}
/// NoExpand indicates literal string replacement.
}
impl<'t> Captures<'t> {
+ #[allow(experimental)]
fn new(re: &Regex, search: &'t str, locs: CaptureLocs)
-> Option<Captures<'t>> {
if !has_match(&locs) {
}
let named =
- if re.names.len() == 0 {
+ if re.names_len() == 0 {
None
} else {
let mut named = HashMap::new();
- for (i, name) in re.names.iter().enumerate() {
+ for (i, name) in re.names_iter().enumerate() {
match name {
- &None => {},
- &Some(ref name) => {
- named.insert(name.to_strbuf(), i);
+ None => {},
+ Some(name) => {
+ named.insert(name, i);
}
}
}
fn exec_slice(re: &Regex, which: MatchKind,
input: &str, s: uint, e: uint) -> CaptureLocs {
- match re.p {
- Dynamic(ref prog) => vm::run(which, prog, input, s, e),
- Native(exec) => exec(which, input, s, e),
+ match *re {
+ Dynamic(Dynamic { ref prog, .. }) => vm::run(which, prog, input, s, e),
+ Native(Native { prog, .. }) => prog(which, input, s, e),
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use regex::Regex;
+static RE: Regex = regex!(r"\d+");
+
+#[test]
+fn static_splitn() {
+ let text = "cauchy123plato456tyler789binx";
+ let subs: Vec<&str> = RE.splitn(text, 2).collect();
+ assert_eq!(subs, vec!("cauchy", "plato456tyler789binx"));
+}
+
+#[test]
+fn static_split() {
+ let text = "cauchy123plato456tyler789binx";
+ let subs: Vec<&str> = RE.split(text).collect();
+ assert_eq!(subs, vec!("cauchy", "plato", "tyler", "binx"));
+}
/// It is strongly recommended to read the dynamic implementation in vm.rs
/// first before trying to understand the code generator. The implementation
/// strategy is identical and vm.rs has comments and will be easier to follow.
+#[allow(experimental)]
fn native(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree])
-> Box<MacResult> {
let regex = match parse(cx, tts) {
return DummyResult::any(sp)
}
};
- let prog = match re.p {
- Dynamic(ref prog) => prog.clone(),
+ let prog = match re {
+ Dynamic(Dynamic { ref prog, .. }) => prog.clone(),
Native(_) => unreachable!(),
};
let mut gen = NfaGen {
cx: &*cx, sp: sp, prog: prog,
- names: re.names.clone(), original: re.original.clone(),
+ names: re.names_iter().collect(), original: re.as_str().to_strbuf(),
};
MacExpr::new(gen.code())
}
|cx, name| match *name {
Some(ref name) => {
let name = name.as_slice();
- quote_expr!(cx, Some($name.to_strbuf()))
+ quote_expr!(cx, Some($name))
}
None => cx.expr_none(self.sp),
}
let regex = self.original.as_slice();
quote_expr!(self.cx, {
+static CAP_NAMES: &'static [Option<&'static str>] = &$cap_names;
fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
start: uint, end: uint) -> Vec<Option<uint>> {
#![allow(unused_imports)]
+ #![allow(unused_mut)]
use regex::native::{
MatchKind, Exists, Location, Submatches,
StepState, StepMatchEarlyReturn, StepMatch, StepContinue,
}
}
-::regex::Regex {
- original: $regex.to_strbuf(),
- names: vec!$cap_names,
- p: ::regex::native::Native(exec),
-}
+::regex::native::Native(::regex::native::Native {
+ original: $regex,
+ names: CAP_NAMES,
+ prog: exec,
+})
})
}