Fix #2237: Parser library failed if the same tag pair is used more than once within a template

(manually applying PR #2238 + updated unit tests)
diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php
index c1f1ad7..399131c 100644
--- a/system/libraries/Parser.php
+++ b/system/libraries/Parser.php
@@ -187,26 +187,34 @@
 	 */
 	protected function _parse_pair($variable, $data, $string)
 	{
-		if (FALSE === ($match = $this->_match_pair($string, $variable)))
+		if (FALSE === ($matches = $this->_match_pair($string, $variable)))
 		{
 			return $string;
 		}
 
 		$str = '';
-		foreach ($data as $row)
+		$search = $replace = array();
+		foreach ($matches as $match)
 		{
-			$temp = $match[1];
-			foreach ($row as $key => $val)
+			$str = '';
+			foreach ($data as $row)
 			{
-				$temp = is_array($val)
+				$temp = $match[1];
+				foreach ($row as $key => $val)
+				{
+					$temp = is_array($val)
 						? $this->_parse_pair($key, $val, $temp)
 						: $this->_parse_single($key, $val, $temp);
+				}
+
+				$str .= $temp;
 			}
 
-			$str .= $temp;
+			$search[] = $match[0];
+			$replace[] = $str;
 		}
 
-		return str_replace($match[0], $str, $string);
+		return str_replace($search, $replace, $string);
 	}
 
 	// --------------------------------------------------------------------
@@ -214,14 +222,14 @@
 	/**
 	 * Matches a variable pair
 	 *
-	 * @param	string
-	 * @param	string
+	 * @param	string	$string
+	 * @param	string	$variable
 	 * @return	mixed
 	 */
 	protected function _match_pair($string, $variable)
 	{
-		return preg_match('|'.preg_quote($this->l_delim).$variable.preg_quote($this->r_delim).'(.+?)'.preg_quote($this->l_delim).'/'.$variable.preg_quote($this->r_delim).'|s',
-					$string, $match)
+		return preg_match_all('|'.preg_quote($this->l_delim).$variable.preg_quote($this->r_delim).'(.+?)'.preg_quote($this->l_delim).'/'.$variable.preg_quote($this->r_delim).'|s',
+					$string, $match, PREG_SET_ORDER)
 			? $match : FALSE;
 	}
 
diff --git a/tests/codeigniter/libraries/Parser_test.php b/tests/codeigniter/libraries/Parser_test.php
index 394c226..6e5c192 100644
--- a/tests/codeigniter/libraries/Parser_test.php
+++ b/tests/codeigniter/libraries/Parser_test.php
@@ -76,9 +76,9 @@
 			)
 		);
 
-		$template = "{title}\n{powers}{invisibility}\n{flying}{/powers}";
+		$template = "{title}\n{powers}{invisibility}\n{flying}{/powers}\nsecond:{powers} {invisibility} {flying}{/powers}";
 
-		$this->assertEquals("Super Heroes\nyes\nno", $this->parser->parse_string($template, $data, TRUE));
+		$this->assertEquals("Super Heroes\nyes\nno\nsecond: yes no", $this->parser->parse_string($template, $data, TRUE));
 	}
 
 	// --------------------------------------------------------------------
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 7cc27eb..6d0ceb6 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -631,6 +631,7 @@
 -  Fixed a bug - Redis :doc:`Caching <libraries/caching>` driver didn't handle connection failures properly.
 -  Fixed a bug (#2756) - :doc:`Database Class <database/index>` executed the MySQL-specific `SET SESSION sql_mode` query for all drivers when the 'stricton' option is set.
 -  Fixed a bug (#2579) - :doc:`Query Builder <database/query_builder>`s "no escape" functionality didn't work properly with query cache.
+-  Fixed a bug (#2237) - :doc:`Parser Library <libraries/parser>` failed if the same tag pair is used more than once within a template.
 
 Version 2.1.4
 =============