PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Visitor/Isotropic.php

https://github.com/jeremyFreeAgent/Regex
PHP | 336 lines | 213 code | 50 blank | 73 comment | 1 complexity | 80ce2f1ad636e814544fe33e592f6448 MD5 | raw file
  1. <?php
  2. /**
  3. * Hoa
  4. *
  5. *
  6. * @license
  7. *
  8. * New BSD License
  9. *
  10. * Copyright © 2007-2013, Ivan Enderlin. All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * * Neither the name of the Hoa nor the names of its contributors may be
  20. * used to endorse or promote products derived from this software without
  21. * specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  24. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
  27. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  30. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  31. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  32. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. namespace {
  36. from('Hoa')
  37. /**
  38. * \Hoa\Regex\Visitor\Exception
  39. */
  40. -> import('Regex.Visitor.Exception')
  41. /**
  42. * \Hoa\Regex\Visitor\Visit
  43. */
  44. -> import('Regex.Visitor.Visit')
  45. /**
  46. * \Hoa\String
  47. */
  48. -> import('String.~');
  49. }
  50. namespace Hoa\Regex\Visitor {
  51. /**
  52. * Class \Hoa\Regex\Visitor\Isotropic.
  53. *
  54. * Isotropic walk on the AST to generate a data.
  55. *
  56. * @author Ivan Enderlin <ivan.enderlin@hoa-project.net>
  57. * @copyright Copyright © 2007-2013 Ivan Enderlin.
  58. * @license New BSD License
  59. */
  60. class Isotropic implements Visit {
  61. /**
  62. * Numeric-sampler.
  63. *
  64. * @var \Hoa\Math\Sampler object
  65. */
  66. protected $_sampler = null;
  67. /**
  68. * Initialize numeric-sampler.
  69. *
  70. * @access public
  71. * @param \Hoa\Math\Sampler $sampler Numeric-sampler.
  72. * @return void
  73. */
  74. public function __construct ( \Hoa\Math\Sampler $sampler ) {
  75. $this->_sampler = $sampler;
  76. return;
  77. }
  78. /**
  79. * Visit an element.
  80. *
  81. * @access public
  82. * @param \Hoa\Visitor\Element $element Element to visit.
  83. * @param mixed &$handle Handle (reference).
  84. * @param mixed $eldnah Handle (not reference).
  85. * @return mixed
  86. */
  87. public function visit ( \Hoa\Visitor\Element $element,
  88. &$handle = null, $eldnah = null ) {
  89. switch($element->getId()) {
  90. case '#expression':
  91. case '#capturing':
  92. case '#namedcapturing':
  93. return $element->getChild(0)->accept($this, $handle, $eldnah);
  94. break;
  95. case '#alternation':
  96. case '#class':
  97. return $element->getChild($this->_sampler->getInteger(
  98. 0,
  99. $element->getChildrenNumber() - 1
  100. ))->accept($this, $handle, $eldnah);
  101. break;
  102. case '#concatenation':
  103. $out = null;
  104. foreach($element->getChildren() as $child)
  105. $out .= $child->accept($this, $handle, $eldnah);
  106. return $out;
  107. break;
  108. case '#quantification':
  109. $out = null;
  110. $xy = $element->getChild(1)->getValueValue();
  111. $x = 0;
  112. $y = 0;
  113. switch($element->getChild(1)->getValueToken()) {
  114. case 'zero_or_one':
  115. $y = 1;
  116. break;
  117. case 'zero_or_more':
  118. $y = 5; // why not?
  119. break;
  120. case 'one_or_more':
  121. $x = 1;
  122. $y = 5; // why not?
  123. break;
  124. case 'exactly_n':
  125. $x = $y = (int) substr($xy, 1, -1);
  126. break;
  127. case 'n_to_m':
  128. $xy = explode(',', substr($xy, 1, -1));
  129. $x = (int) trim($xy[0]);
  130. $y = (int) trim($xy[1]);
  131. break;
  132. case 'n_or_more':
  133. $xy = explode(',', substr($xy, 1, -1));
  134. $x = (int) trim($xy[0]);
  135. $y = 5; // why not?
  136. break;
  137. }
  138. for($i = 0, $max = $this->_sampler->getInteger($x, $y);
  139. $i < $max; ++$i)
  140. $out .= $element->getChild(0)->accept(
  141. $this,
  142. $handle,
  143. $eldnah
  144. );
  145. return $out;
  146. break;
  147. case '#negativeclass':
  148. $c = array();
  149. foreach($element->getChildren() as $child)
  150. $c[\Hoa\String::toCode(
  151. $child->accept($this, $handle, $eldnah)
  152. )] = true;
  153. do {
  154. // all printable ASCII.
  155. $i = $this->_sampler->getInteger(32, 126);
  156. } while(isset($c[$i]));
  157. return \Hoa\String::fromCode($i);
  158. break;
  159. case '#range':
  160. $out = null;
  161. $left = $element->getChild(0)->accept($this, $handle, $eldnah);
  162. $right = $element->getChild(1)->accept($this, $handle, $eldnah);
  163. return \Hoa\String::fromCode($this->_sampler->getInteger(
  164. \Hoa\String::toCode($left),
  165. \Hoa\String::toCode($right)
  166. ));
  167. break;
  168. case 'token':
  169. $value = $element->getValueValue();
  170. switch($element->getValueToken()) {
  171. case 'character':
  172. $value = ltrim($value, '\\');
  173. switch($value) {
  174. case 'a':
  175. return "\a";
  176. case 'e':
  177. return "\e";
  178. case 'f':
  179. return "\f";
  180. case 'n':
  181. return "\n";
  182. case 'r':
  183. return "\r";
  184. case 't':
  185. return "\t";
  186. default:
  187. return \Hoa\String::fromCode(intval(
  188. substr($value, 1)
  189. ));
  190. }
  191. break;
  192. case 'dynamic_character':
  193. $value = ltrim($value, '\\');
  194. switch($value[0]) {
  195. case 'x':
  196. $value = trim($value, 'x{}');
  197. return \Hoa\String::fromCode(
  198. hexdec($value)
  199. );
  200. break;
  201. default:
  202. return \Hoa\String::fromCode(octdec($value));
  203. }
  204. break;
  205. case 'character_type':
  206. $value = ltrim($value, '\\');
  207. switch($value) {
  208. case 'C':
  209. return $this->_sampler->getInteger(0, 127);
  210. case 'd':
  211. return $this->_sampler->getInteger(0, 9);
  212. case 's':
  213. $value = $this->_sampler->getInteger(0, 1)
  214. ? 'h'
  215. : 'v';
  216. case 'h':
  217. $h = array(
  218. chr(0x0009),
  219. chr(0x0020),
  220. chr(0x00a0)
  221. );
  222. return $h[$this->_sampler->getInteger(
  223. 0,
  224. count($h) -1
  225. )];
  226. case 'v':
  227. $v = array(
  228. chr(0x000a),
  229. chr(0x000b),
  230. chr(0x000c),
  231. chr(0x000d)
  232. );
  233. return $v[$this->_sampler->getInteger(
  234. 0,
  235. count($v) -1
  236. )];
  237. case 'w':
  238. $w = array_merge(
  239. range(0x41, 0x5a),
  240. range(0x61, 0x7a),
  241. array(0x5f)
  242. );
  243. return chr($w[
  244. $this->_sampler->getInteger(
  245. 0,
  246. count($w) - 1
  247. )
  248. ]);
  249. default:
  250. return '?';
  251. }
  252. break;
  253. case 'literal':
  254. return str_replace('\\\\', '\\', preg_replace(
  255. '#\\\(?!\\\)#',
  256. '',
  257. $element->getValueValue()
  258. ));
  259. }
  260. break;
  261. }
  262. return;
  263. }
  264. }
  265. }