GitHub PullRequestReviewCommentEvent at 2014-04-23 17:35:57
Repository: rust
Actor: alexcrichton
Payload: {"comment":{"url":"https://api.github.com/repos/mozilla/rust/pulls/comments/11912695","id":11912695,"diff_hunk":"@@ -0,0 +1,783 @@\n+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT\n+// file at the top-level directory of this distribution and at\n+// http://rust-lang.org/COPYRIGHT.\n+//\n+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\n+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\n+// option. This file may not be copied, modified, or distributed\n+// except according to those terms.\n+\n+use collections::HashMap;\n+use std::cast;\n+use std::fmt;\n+use std::from_str::from_str;\n+use std::str::{MaybeOwned, Owned, Slice};\n+use std::str::raw;\n+\n+use std::mem;\n+use std::ptr;\n+use std::rt::global_heap::malloc_raw;\n+use RawVec = std::raw::Vec;\n+\n+use compile::Program;\n+use parse;\n+use vm;\n+use vm::{CaptureLocs, MatchKind, Exists, Location, Submatches};\n+\n+/// Escapes all regular expression meta characters in `text` so that it may be\n+/// safely used in a regular expression as a literal string.\n+pub fn quote(text: &str) -> ~str {\n+    let mut quoted = StrBuf::with_capacity(text.len());\n+    for c in text.chars() {\n+        if parse::is_punct(c) {\n+            quoted.push_char('\\\\')\n+        }\n+        quoted.push_char(c);\n+    }\n+    quoted.into_owned()\n+}\n+\n+/// Tests if the given regular expression matches somewhere in the text given.\n+///\n+/// If there was a problem compiling the regular expression, an error is\n+/// returned.\n+///\n+/// To find submatches, split or replace text, you'll need to compile an\n+/// expression first.\n+///\n+/// Note that you should prefer the `regexp!` macro when possible. For example,\n+/// `regexp!(\"...\").is_match(\"...\")`.\n+pub fn is_match(regex: &str, text: &str) -> Result<bool, parse::Error> {\n+    Regexp::new(regex).map(|r| r.is_match(text))\n+}\n+\n+/// Regexp is a compiled regular expression, represented as either a sequence\n+/// of bytecode instructions (dynamic) or as a specialized Rust function\n+/// (native). It can be used to search, split\n+/// or replace text. All searching is done with an implicit `.*?` at the\n+/// beginning and end of an expression. To force an expression to match the\n+/// whole string (or a prefix or a suffix), you must use an anchor like `^` or\n+/// `$` (or `\\A` and `\\z`).\n+///\n+/// While this crate will handle Unicode strings (whether in the regular\n+/// expression or in the search text), all positions returned are **byte\n+/// indices**. Every byte index is guaranteed to be at a UTF8 codepoint\n+/// boundary.\n+///\n+/// The lifetimes `'r` and `'t` in this crate correspond to the lifetime of a\n+/// compiled regular expression and text to search, respectively.\n+///\n+/// The only methods that allocate new strings are the string replacement\n+/// methods. All other methods (searching and splitting) return borrowed\n+/// pointers into the string given.\n+///\n+/// # Examples\n+///\n+/// Find the location of a US phone number:\n+///\n+/// ```rust\n+/// # use regexp::Regexp;\n+/// let re = match Regexp::new(\"[0-9]{3}-[0-9]{3}-[0-9]{4}\") {\n+///     Ok(re) => re,\n+///     Err(err) => fail!(\"{}\", err),\n+/// };\n+/// assert_eq!(re.find(\"phone: 111-222-3333\"), Some((7, 19)));\n+/// ```\n+///\n+/// You can also use the `regexp!` macro to compile a regular expression when\n+/// you compile your program:\n+///\n+/// ```rust\n+/// #![feature(phase)]\n+/// extern crate regexp;\n+/// #[phase(syntax)] extern crate regexp_macros;\n+///\n+/// fn main() {\n+///     let re = regexp!(r\"\\d+\");\n+///     assert_eq!(re.find(\"123 abc\"), Some((0, 3)));\n+/// }\n+/// ```\n+///\n+/// Given an incorrect regular expression, `regexp!` will cause the Rust\n+/// compiler to produce a compile time error.\n+/// Note that `regexp!` will compile the expression to native Rust code, which\n+/// makes it much faster when searching text.\n+/// More details about the `regexp!` macro can be found in the `regexp` crate\n+/// documentation.\n+#[deriving(Clone)]\n+#[allow(visible_private_types)]\n+pub struct Regexp {\n+    /// The representation of `Regexp` is exported to support the `regexp!`\n+    /// syntax extension. Do not rely on it.\n+    ///\n+    /// See the comments for the `program` module in `lib.rs` for a more\n+    /// detailed explanation for what `regexp!` requires.\n+    #[doc(hidden)]\n+    pub original: ~str,\n+    #[doc(hidden)]\n+    pub names: ~[Option<~str>],\n+    #[doc(hidden)]\n+    pub p: MaybeNative,\n+}\n+\n+impl fmt::Show for Regexp {\n+    /// Shows the original regular expression.\n+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n+        write!(f.buf, \"{}\", self.original)\n+    }\n+}\n+\n+pub enum MaybeNative {\n+    Dynamic(Program),\n+    Native(fn(MatchKind, &str, uint, uint) -> Vec<Option<uint>>),\n+}\n+\n+impl Clone for MaybeNative {\n+    fn clone(&self) -> MaybeNative {\n+        match *self {\n+            Dynamic(ref p) => Dynamic(p.clone()),\n+            Native(fp) => Native(fp),\n+        }\n+    }\n+}\n+\n+impl Regexp {\n+    /// Compiles a dynamic regular expression. Once compiled, it can be\n+    /// used repeatedly to search, split or replace text in a string.\n+    ///\n+    /// When possible, you should prefer the `regexp!` macro since it is\n+    /// safer and always faster.\n+    ///\n+    /// If an invalid expression is given, then an error is returned.\n+    pub fn new(re: &str) -> Result<Regexp, parse::Error> {\n+        let ast = try!(parse::parse(re));\n+        let (prog, names) = Program::new(ast);\n+        Ok(Regexp { original: re.to_owned(), names: names, p: Dynamic(prog) })\n+    }\n+}\n+\n+impl Regexp {\n+    /// Returns true if and only if the regexp matches the string given.\n+    pub fn is_match(&self, text: &str) -> bool {\n+        has_match(&exec(self, Exists, text))\n+    }\n+\n+    /// Returns the start and end byte range of the leftmost-first match in\n+    /// `text`. If no match exists, then `None` is returned.\n+    ///\n+    /// Note that this should only be used if you want to discover the position\n+    /// of the match. Testing the existence of a match is faster if you use\n+    /// `is_match`.\n+    pub fn find(&self, text: &str) -> Option<(uint, uint)> {\n+        let caps = exec(self, Location, text);\n+        if has_match(&caps) {\n+            Some((caps.get(0).unwrap(), caps.get(1).unwrap()))\n+        } else {\n+            None\n+        }\n+    }\n+\n+    /// Returns an iterator for each successive non-overlapping match in\n+    /// `text`, returning the start and end byte indices with respect to\n+    /// `text`.\n+    pub fn find_iter<'r, 't>(&'r self, text: &'t str) -> FindMatches<'r, 't> {\n+        FindMatches {\n+            re: self,\n+            search: text,\n+            last_end: 0,\n+            last_match: None,\n+        }\n+    }\n+\n+    /// Returns the capture groups corresponding to the leftmost-first\n+    /// match in `text`. Capture group `0` always corresponds to the entire\n+    /// match. If no match is found, then `None` is returned.\n+    ///\n+    /// You should only use `captures` if you need access to submatches.\n+    /// Otherwise, `find` is faster for discovering the location of the overall\n+    /// match.\n+    pub fn captures<'t>(&self, text: &'t str) -> Option<Captures<'t>> {\n+        let caps = exec(self, Submatches, text);\n+        Captures::new(self, text, caps)\n+    }\n+\n+    /// Returns an iterator over all the non-overlapping capture groups matched\n+    /// in `text`. This is operationally the same as `find_iter` (except it\n+    /// yields information about submatches).\n+    pub fn captures_iter<'r, 't>(&'r self, text: &'t str)","path":"src/libregexp/re.rs","position":206,"original_position":208,"commit_id":"095a9d4393715d944e7cf721fe17c9be8fc2d6c2","original_commit_id":"7451150bfdef2c908f833686168e5b65c0497da2","user":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars.githubusercontent.com/u/64996?","gravatar_id":"477e2098d9864b482d28e5ef8e657f43","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"body":"If you have type (certainly not a blocker), could you add a small example to this and the above few methods? I think I understand how to use them, but examples are always super helpful!\r\n\r\n(again, not a blocker, just a cherry on top)","created_at":"2014-04-23T17:35:57Z","updated_at":"2014-04-23T17:35:57Z","html_url":"https://github.com/mozilla/rust/pull/13700#discussion_r11912695","pull_request_url":"https://api.github.com/repos/mozilla/rust/pulls/13700","_links":{"self":{"href":"https://api.github.com/repos/mozilla/rust/pulls/comments/11912695"},"html":{"href":"https://github.com/mozilla/rust/pull/13700#discussion_r11912695"},"pull_request":{"href":"https://api.github.com/repos/mozilla/rust/pulls/13700"}}}}