Lexer.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. *
  15. * This software consists of voluntary contributions made by many individuals
  16. * and is licensed under the LGPL. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\ORM\Query;
  20. /**
  21. * Scans a DQL query for tokens.
  22. *
  23. * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
  24. * @author Janne Vanhala <jpvanhal@cc.hut.fi>
  25. * @author Roman Borschel <roman@code-factory.org>
  26. * @since 2.0
  27. */
  28. class Lexer extends \Doctrine\Common\Lexer
  29. {
  30. // All tokens that are not valid identifiers must be < 100
  31. const T_NONE = 1;
  32. const T_INTEGER = 2;
  33. const T_STRING = 3;
  34. const T_INPUT_PARAMETER = 4;
  35. const T_FLOAT = 5;
  36. const T_CLOSE_PARENTHESIS = 6;
  37. const T_OPEN_PARENTHESIS = 7;
  38. const T_COMMA = 8;
  39. const T_DIVIDE = 9;
  40. const T_DOT = 10;
  41. const T_EQUALS = 11;
  42. const T_GREATER_THAN = 12;
  43. const T_LOWER_THAN = 13;
  44. const T_MINUS = 14;
  45. const T_MULTIPLY = 15;
  46. const T_NEGATE = 16;
  47. const T_PLUS = 17;
  48. const T_OPEN_CURLY_BRACE = 18;
  49. const T_CLOSE_CURLY_BRACE = 19;
  50. // All tokens that are also identifiers should be >= 100
  51. const T_IDENTIFIER = 100;
  52. const T_ALL = 101;
  53. const T_AND = 102;
  54. const T_ANY = 103;
  55. const T_AS = 104;
  56. const T_ASC = 105;
  57. const T_AVG = 106;
  58. const T_BETWEEN = 107;
  59. const T_BOTH = 108;
  60. const T_BY = 109;
  61. const T_CASE = 110;
  62. const T_COALESCE = 111;
  63. const T_COUNT = 112;
  64. const T_DELETE = 113;
  65. const T_DESC = 114;
  66. const T_DISTINCT = 115;
  67. const T_ELSE = 116;
  68. const T_EMPTY = 117;
  69. const T_END = 118;
  70. const T_ESCAPE = 119;
  71. const T_EXISTS = 120;
  72. const T_FALSE = 121;
  73. const T_FROM = 122;
  74. const T_GROUP = 123;
  75. const T_HAVING = 124;
  76. const T_HIDDEN = 125;
  77. const T_IN = 126;
  78. const T_INDEX = 127;
  79. const T_INNER = 128;
  80. const T_INSTANCE = 129;
  81. const T_IS = 130;
  82. const T_JOIN = 131;
  83. const T_LEADING = 132;
  84. const T_LEFT = 133;
  85. const T_LIKE = 134;
  86. const T_MAX = 135;
  87. const T_MEMBER = 136;
  88. const T_MIN = 137;
  89. const T_NOT = 138;
  90. const T_NULL = 139;
  91. const T_NULLIF = 140;
  92. const T_OF = 141;
  93. const T_OR = 142;
  94. const T_ORDER = 143;
  95. const T_OUTER = 144;
  96. const T_SELECT = 145;
  97. const T_SET = 146;
  98. const T_SIZE = 147;
  99. const T_SOME = 148;
  100. const T_SUM = 149;
  101. const T_THEN = 150;
  102. const T_TRAILING = 151;
  103. const T_TRUE = 152;
  104. const T_UPDATE = 153;
  105. const T_WHEN = 154;
  106. const T_WHERE = 155;
  107. const T_WITH = 156;
  108. const T_PARTIAL = 157;
  109. const T_MOD = 158;
  110. /**
  111. * Creates a new query scanner object.
  112. *
  113. * @param string $input a query string
  114. */
  115. public function __construct($input)
  116. {
  117. $this->setInput($input);
  118. }
  119. /**
  120. * @inheritdoc
  121. */
  122. protected function getCatchablePatterns()
  123. {
  124. return array(
  125. '[a-z_\\\][a-z0-9_\:\\\]*[a-z0-9_]{1}',
  126. '(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
  127. "'(?:[^']|'')*'",
  128. '\?[0-9]*|:[a-z]{1}[a-z0-9_]{0,}'
  129. );
  130. }
  131. /**
  132. * @inheritdoc
  133. */
  134. protected function getNonCatchablePatterns()
  135. {
  136. return array('\s+', '(.)');
  137. }
  138. /**
  139. * @inheritdoc
  140. */
  141. protected function getType(&$value)
  142. {
  143. $type = self::T_NONE;
  144. switch (true) {
  145. // Recognize numeric values
  146. case (is_numeric($value)):
  147. if (strpos($value, '.') !== false || stripos($value, 'e') !== false) {
  148. return self::T_FLOAT;
  149. }
  150. return self::T_INTEGER;
  151. // Recognize quoted strings
  152. case ($value[0] === "'"):
  153. $value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
  154. return self::T_STRING;
  155. // Recognize identifiers
  156. case (ctype_alpha($value[0]) || $value[0] === '_'):
  157. $name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value);
  158. if (defined($name)) {
  159. $type = constant($name);
  160. if ($type > 100) {
  161. return $type;
  162. }
  163. }
  164. return self::T_IDENTIFIER;
  165. // Recognize input parameters
  166. case ($value[0] === '?' || $value[0] === ':'):
  167. return self::T_INPUT_PARAMETER;
  168. // Recognize symbols
  169. case ($value === '.'): return self::T_DOT;
  170. case ($value === ','): return self::T_COMMA;
  171. case ($value === '('): return self::T_OPEN_PARENTHESIS;
  172. case ($value === ')'): return self::T_CLOSE_PARENTHESIS;
  173. case ($value === '='): return self::T_EQUALS;
  174. case ($value === '>'): return self::T_GREATER_THAN;
  175. case ($value === '<'): return self::T_LOWER_THAN;
  176. case ($value === '+'): return self::T_PLUS;
  177. case ($value === '-'): return self::T_MINUS;
  178. case ($value === '*'): return self::T_MULTIPLY;
  179. case ($value === '/'): return self::T_DIVIDE;
  180. case ($value === '!'): return self::T_NEGATE;
  181. case ($value === '{'): return self::T_OPEN_CURLY_BRACE;
  182. case ($value === '}'): return self::T_CLOSE_CURLY_BRACE;
  183. // Default
  184. default:
  185. // Do nothing
  186. }
  187. return $type;
  188. }
  189. }