PageRenderTime 38ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ChartDown/LexerNeedle.php

https://github.com/bshaffer/ChartDown
PHP | 238 lines | 177 code | 47 blank | 14 comment | 12 complexity | ee345ef9e5a03bb8a43f242e4221c57d MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of ChartDown.
  4. *
  5. * (c) 2011 Brent Shaffer
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * Easy way to navigate text
  12. *
  13. * @package chartdown
  14. * @author Brent Shaffer <bshafs@gmail.com>
  15. */
  16. class ChartDown_LexerNeedle
  17. {
  18. protected $text;
  19. protected $cursor;
  20. protected $end;
  21. protected $lineno;
  22. public function __construct($text, $cursor = 0)
  23. {
  24. $this->text = str_replace(array("\r\n", "\r"), "\n", $text);
  25. $this->end = strlen($this->text);
  26. $this->cursor = $cursor;
  27. }
  28. public function __toString()
  29. {
  30. return (string) $this->text;
  31. }
  32. public function getText()
  33. {
  34. return $this->text;
  35. }
  36. public function setText($text)
  37. {
  38. $this->text = $text;
  39. }
  40. public function getTextAtCursor()
  41. {
  42. return substr($this->text, $this->cursor);
  43. }
  44. public function getCursor()
  45. {
  46. return $this->cursor;
  47. }
  48. public function rest()
  49. {
  50. $rest = substr($this->text, $this->cursor);
  51. $this->moveToEnd();
  52. return $rest;
  53. }
  54. public function moveToEnd()
  55. {
  56. $this->cursor = $this->end;
  57. }
  58. public function match($regex, $returnSubpatterns = false)
  59. {
  60. if(preg_match($regex, $this->text, $match, null, $this->cursor))
  61. {
  62. if ($returnSubpatterns) {
  63. return $match;
  64. }
  65. return count($match) > 2 ? array_slice($match, 1) : array_pop($match);
  66. }
  67. }
  68. public function matches($regex)
  69. {
  70. return preg_match($regex, $this->text, $match, null, $this->cursor);
  71. }
  72. public function next($text)
  73. {
  74. return strpos($this->text, $text, $this->cursor);
  75. }
  76. public function hasNext($text)
  77. {
  78. return $this->next($text) !== false;
  79. }
  80. public function nextMatch($regex)
  81. {
  82. preg_match($regex, $this->text, $match, null, $this->cursor);
  83. return $match ? strpos($this->text, $match[0], $this->cursor) : false;
  84. }
  85. public function moveToFirst($searches)
  86. {
  87. $pos = $this->end;
  88. $token = null;
  89. foreach ($searches as $search) {
  90. $tmpPos = $this->isRegex($search) ? $this->nextMatch($search) : $this->next($search);
  91. if (false !== $tmpPos && $tmpPos < $pos) {
  92. $pos = $tmpPos;
  93. $token = $search;
  94. }
  95. }
  96. return $pos === $this->end ? false : array($token, $this->moveTo($token));
  97. }
  98. public function moveTo($search)
  99. {
  100. if ($this->isRegex($search)) {
  101. $match = $this->match($search, true);
  102. $pos = $this->next($match[0]) + strlen($match[0]);
  103. } elseif(is_string($search)) {
  104. $pos = $this->next($search) + strlen($search);
  105. } else {
  106. $pos = $search;
  107. }
  108. $text = substr($this->text, $this->cursor, $pos - $this->cursor);
  109. $this->moveCursor($text);
  110. return $text;
  111. }
  112. public function isRegex($text)
  113. {
  114. return strpos($text, '/') === 0 && strpos(strrev($text), '/') === 0;
  115. }
  116. public function getNext($text)
  117. {
  118. if(false !== ($pos = strpos($this->text, $text, $this->cursor)))
  119. {
  120. $prev = substr($this->text, $this->cursor, $pos - $this->cursor);
  121. $this->moveTo($text);
  122. return $prev;
  123. }
  124. return false;
  125. }
  126. public function isCurrentCharacter($string)
  127. {
  128. return false !== strpos($string, $this->text[$this->cursor]);
  129. }
  130. public function increment($step = 1)
  131. {
  132. $this->cursor += $step;
  133. }
  134. public function moveCursor($text)
  135. {
  136. $this->cursor += strlen($text);
  137. $this->lineno += substr_count($text, "\n");
  138. }
  139. public function isEOF()
  140. {
  141. return $this->cursor >= $this->end;
  142. }
  143. public function split($separator)
  144. {
  145. $needles = array();
  146. foreach (explode($separator, $this->text) as $part) {
  147. $needles[] = new self($part);
  148. }
  149. return $needles;
  150. }
  151. public function getNextLine()
  152. {
  153. return $this->isEOF() ? null : new self($this->hasNext("\n") ? $this->getNext("\n") : $this->rest());
  154. }
  155. public function getNumLines()
  156. {
  157. return substr_count(substr($this->text, $this->cursor), "\n") + 1;
  158. }
  159. public function ltrim($text)
  160. {
  161. if (0 === strpos($this->text, $text)) {
  162. $this->text = substr($this->text, strlen($text));
  163. }
  164. return $this;
  165. }
  166. public function rtrim($text)
  167. {
  168. if (strlen($this->text) -1 === ($pos = strrpos($this->text, $text))) {
  169. $this->text = substr($this->text, 0, $pos);
  170. }
  171. return $this;
  172. }
  173. public function regexTrim($regex, $sep = '')
  174. {
  175. $match = $this->match($regex);
  176. if (is_array($match)) {
  177. $match = implode($sep, $match);
  178. }
  179. if ($match) {
  180. $this->text = $match;
  181. $this->pos = 0;
  182. }
  183. }
  184. public function trim()
  185. {
  186. $text = ltrim($this->text);
  187. $this->end -= (strlen($this->text) - strlen($text));
  188. $this->text = $text;
  189. return $this;
  190. }
  191. }