Repository: pest-parser/pest (rust)

Issue:
Unable to get Span without consuming Pair
If getting a Span consumes a Pair, I have to choose between getting that Span and getting its inner Pairs. This is counter intuitive given that the two don't really seem related. Sometimes I want to look further into the contents of a pair and also get its position. Can we add a `span(&self)` method (or something) to get the Span of a Pair and still allow you to get its inner Pairs afterwards?

I would be happy to create a PR for this. :smile: 

Pull request:
Created as_span method
Fixes #223.

I left `into_span` so that this change is backwards compatible. `into_span` is now implemented in terms of `as_span` because they do the same thing.

Since the two methods are mostly the same, the test is also pretty much exactly the same. I added an extra part at the end to make sure that the pair is not consumed by the method.

Patch:
diff --git a/README.md b/README.md
index 219d022..94cd2ae 100644
--- a/README.md
+++ b/README.md
@@ -60,14 +60,14 @@ fn main() {
     for pair in pairs {
         // A pair is a combination of the rule which matched and a span of input
         println!("Rule:    {:?}", pair.as_rule());
-        println!("Span:    {:?}", pair.clone().into_span());
-        println!("Text:    {}", pair.clone().into_span().as_str());
+        println!("Span:    {:?}", pair.as_span());
+        println!("Text:    {}", pair.as_span().as_str());
 
         // A pair can be converted to an iterator of the tokens which make it up:
         for inner_pair in pair.into_inner() {
             match inner_pair.as_rule() {
-                Rule::alpha => println!("Letter:  {}", inner_pair.into_span().as_str()),
-                Rule::digit => println!("Digit:   {}", inner_pair.into_span().as_str()), 
+                Rule::alpha => println!("Letter:  {}", inner_pair.as_span().as_str()),
+                Rule::digit => println!("Digit:   {}", inner_pair.as_span().as_str()),
                 _ => unreachable!()
             };
         }
diff --git a/grammars/benches/json.rs b/grammars/benches/json.rs
index e044a00..087f603 100644
--- a/grammars/benches/json.rs
+++ b/grammars/benches/json.rs
@@ -46,13 +46,13 @@ fn consume(pair: Pair<Rule>) -> Json {
                 _ => unreachable!()
             },
             Rule::number => Json::Number(pair.as_str().parse().unwrap()),
-            Rule::string => Json::String(pair.into_span()),
+            Rule::string => Json::String(pair.as_span()),
             Rule::array => Json::Array(pair.into_inner().map(value).collect()),
             Rule::object => {
                 let pairs = pair.into_inner().map(|pos| {
                     let mut pair = pos.into_inner();
 
-                    let key = pair.next().unwrap().into_span();
+                    let key = pair.next().unwrap().as_span();
                     let value = value(pair.next().unwrap());
 
                     (key, value)
diff --git a/pest/src/iterators/pair.rs b/pest/src/iterators/pair.rs
index 1987cf3..bb5153e 100644
--- a/pest/src/iterators/pair.rs
+++ b/pest/src/iterators/pair.rs
@@ -102,6 +102,8 @@ impl<'i, R: RuleType> Pair<'i, R> {
 
     /// Returns the `Span` defined by the `Pair`, consuming it.
     ///
+    /// **Deprecated.** Please use `as_span` instead.
+    ///
     /// # Examples
     ///
     /// ```
@@ -122,7 +124,34 @@ impl<'i, R: RuleType> Pair<'i, R> {
     /// assert_eq!(pair.into_span().as_str(), "ab");
     /// ```
     #[inline]
+    #[deprecated(since="2.0.0", note="Please use `as_span` instead")]
     pub fn into_span(self) -> Span<'i> {
+        self.as_span()
+    }
+
+    /// Returns the `Span` defined by the `Pair`, **without** consuming it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use std::rc::Rc;
+    /// # use pest;
+    /// # #[allow(non_camel_case_types)]
+    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+    /// enum Rule {
+    ///     ab
+    /// }
+    ///
+    /// let input = "ab";
+    /// let pair = pest::state(input, |state| {
+    ///     // generating Token pair with Rule::ab ...
+    /// #     state.rule(Rule::ab, |s| s.match_string("ab"))
+    /// }).unwrap().next().unwrap();
+    ///
+    /// assert_eq!(pair.as_span().as_str(), "ab");
+    /// ```
+    #[inline]
+    pub fn as_span(&self) -> Span<'i> {
         let start = self.pos(self.start);
         let end = self.pos(self.pair());
 
@@ -207,7 +236,7 @@ impl<'i, R: RuleType> fmt::Debug for Pair<'i, R> {
             f,
             "Pair {{ rule: {:?}, span: {:?}, inner: {:?} }}",
             self.as_rule(),
-            self.clone().into_span(),
+            self.clone().as_span(),
             self.clone().into_inner()
         )
     }


Test patch:
diff --git a/pest/tests/json.rs b/pest/tests/json.rs
index 752e006..e961682 100644
--- a/pest/tests/json.rs
+++ b/pest/tests/json.rs
@@ -271,13 +271,13 @@ fn consume(pair: Pair<Rule>) -> Json {
                 _ => unreachable!()
             },
             Rule::number => Json::Number(pair.as_str().parse().unwrap()),
-            Rule::string => Json::String(pair.into_span()),
+            Rule::string => Json::String(pair.as_span()),
             Rule::array => Json::Array(pair.into_inner().map(value).collect()),
             Rule::object => {
                 let pairs = pair.into_inner().map(|pos| {
                     let mut pair = pos.into_inner();
 
-                    let key = pair.next().unwrap().into_span();
+                    let key = pair.next().unwrap().as_span();
                     let value = value(pair.next().unwrap());
 
                     (key, value)