/lib/Doctrine/ORM/Query/Lexer.php

https://github.com/adrienbrault/doctrine2 · PHP · 214 lines · 180 code · 16 blank · 18 comment · 5 complexity · a6e67ed712e45a8c51f966c3c57367e2 MD5 · raw file

  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\ORM\Query;
  4. /**
  5. * Scans a DQL query for tokens.
  6. */
  7. class Lexer extends \Doctrine\Common\Lexer
  8. {
  9. // All tokens that are not valid identifiers must be < 100
  10. public const T_NONE = 1;
  11. public const T_INTEGER = 2;
  12. public const T_STRING = 3;
  13. public const T_INPUT_PARAMETER = 4;
  14. public const T_FLOAT = 5;
  15. public const T_CLOSE_PARENTHESIS = 6;
  16. public const T_OPEN_PARENTHESIS = 7;
  17. public const T_COMMA = 8;
  18. public const T_DIVIDE = 9;
  19. public const T_DOT = 10;
  20. public const T_EQUALS = 11;
  21. public const T_GREATER_THAN = 12;
  22. public const T_LOWER_THAN = 13;
  23. public const T_MINUS = 14;
  24. public const T_MULTIPLY = 15;
  25. public const T_NEGATE = 16;
  26. public const T_PLUS = 17;
  27. public const T_OPEN_CURLY_BRACE = 18;
  28. public const T_CLOSE_CURLY_BRACE = 19;
  29. // All tokens that are identifiers or keywords that could be considered as identifiers should be >= 100
  30. public const T_ALIASED_NAME = 100;
  31. public const T_FULLY_QUALIFIED_NAME = 101;
  32. public const T_IDENTIFIER = 102;
  33. // All keyword tokens should be >= 200
  34. public const T_ALL = 200;
  35. public const T_AND = 201;
  36. public const T_ANY = 202;
  37. public const T_AS = 203;
  38. public const T_ASC = 204;
  39. public const T_AVG = 205;
  40. public const T_BETWEEN = 206;
  41. public const T_BOTH = 207;
  42. public const T_BY = 208;
  43. public const T_CASE = 209;
  44. public const T_COALESCE = 210;
  45. public const T_COUNT = 211;
  46. public const T_DELETE = 212;
  47. public const T_DESC = 213;
  48. public const T_DISTINCT = 214;
  49. public const T_ELSE = 215;
  50. public const T_EMPTY = 216;
  51. public const T_END = 217;
  52. public const T_ESCAPE = 218;
  53. public const T_EXISTS = 219;
  54. public const T_FALSE = 220;
  55. public const T_FROM = 221;
  56. public const T_GROUP = 222;
  57. public const T_HAVING = 223;
  58. public const T_HIDDEN = 224;
  59. public const T_IN = 225;
  60. public const T_INDEX = 226;
  61. public const T_INNER = 227;
  62. public const T_INSTANCE = 228;
  63. public const T_IS = 229;
  64. public const T_JOIN = 230;
  65. public const T_LEADING = 231;
  66. public const T_LEFT = 232;
  67. public const T_LIKE = 233;
  68. public const T_MAX = 234;
  69. public const T_MEMBER = 235;
  70. public const T_MIN = 236;
  71. public const T_NEW = 237;
  72. public const T_NOT = 238;
  73. public const T_NULL = 239;
  74. public const T_NULLIF = 240;
  75. public const T_OF = 241;
  76. public const T_OR = 242;
  77. public const T_ORDER = 243;
  78. public const T_OUTER = 244;
  79. public const T_PARTIAL = 245;
  80. public const T_SELECT = 246;
  81. public const T_SET = 247;
  82. public const T_SOME = 248;
  83. public const T_SUM = 249;
  84. public const T_THEN = 250;
  85. public const T_TRAILING = 251;
  86. public const T_TRUE = 252;
  87. public const T_UPDATE = 253;
  88. public const T_WHEN = 254;
  89. public const T_WHERE = 255;
  90. public const T_WITH = 256;
  91. /**
  92. * Creates a new query scanner object.
  93. *
  94. * @param string $input A query string.
  95. */
  96. public function __construct($input)
  97. {
  98. $this->setInput($input);
  99. }
  100. /**
  101. * {@inheritdoc}
  102. */
  103. protected function getCatchablePatterns()
  104. {
  105. return [
  106. '[a-z_][a-z0-9_]*\:[a-z_][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // aliased name
  107. '[a-z_\\\][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // identifier or qualified name
  108. '(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?', // numbers
  109. "'(?:[^']|'')*'", // quoted strings
  110. '\?[0-9]*|:[a-z_][a-z0-9_]*', // parameters
  111. ];
  112. }
  113. /**
  114. * {@inheritdoc}
  115. */
  116. protected function getNonCatchablePatterns()
  117. {
  118. return ['\s+', '(.)'];
  119. }
  120. /**
  121. * {@inheritdoc}
  122. */
  123. protected function getType(&$value)
  124. {
  125. $type = self::T_NONE;
  126. switch (true) {
  127. // Recognize numeric values
  128. case (is_numeric($value)):
  129. if (strpos($value, '.') !== false || stripos($value, 'e') !== false) {
  130. return self::T_FLOAT;
  131. }
  132. return self::T_INTEGER;
  133. // Recognize quoted strings
  134. case ($value[0] === "'"):
  135. $value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
  136. return self::T_STRING;
  137. // Recognize identifiers, aliased or qualified names
  138. case (ctype_alpha($value[0]) || $value[0] === '_' || $value[0] === '\\'):
  139. $name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value);
  140. if (defined($name)) {
  141. $type = constant($name);
  142. if ($type > 100) {
  143. return $type;
  144. }
  145. }
  146. if (strpos($value, ':') !== false) {
  147. return self::T_ALIASED_NAME;
  148. }
  149. if (strpos($value, '\\') !== false) {
  150. return self::T_FULLY_QUALIFIED_NAME;
  151. }
  152. return self::T_IDENTIFIER;
  153. // Recognize input parameters
  154. case ($value[0] === '?' || $value[0] === ':'):
  155. return self::T_INPUT_PARAMETER;
  156. // Recognize symbols
  157. case ($value === '.'):
  158. return self::T_DOT;
  159. case ($value === ','):
  160. return self::T_COMMA;
  161. case ($value === '('):
  162. return self::T_OPEN_PARENTHESIS;
  163. case ($value === ')'):
  164. return self::T_CLOSE_PARENTHESIS;
  165. case ($value === '='):
  166. return self::T_EQUALS;
  167. case ($value === '>'):
  168. return self::T_GREATER_THAN;
  169. case ($value === '<'):
  170. return self::T_LOWER_THAN;
  171. case ($value === '+'):
  172. return self::T_PLUS;
  173. case ($value === '-'):
  174. return self::T_MINUS;
  175. case ($value === '*'):
  176. return self::T_MULTIPLY;
  177. case ($value === '/'):
  178. return self::T_DIVIDE;
  179. case ($value === '!'):
  180. return self::T_NEGATE;
  181. case ($value === '{'):
  182. return self::T_OPEN_CURLY_BRACE;
  183. case ($value === '}'):
  184. return self::T_CLOSE_CURLY_BRACE;
  185. // Default
  186. default:
  187. // Do nothing
  188. }
  189. return $type;
  190. }
  191. }