|
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 |
|
20 namespace Doctrine\ORM\Query; |
|
21 |
|
22 /** |
|
23 * Scans a DQL query for tokens. |
|
24 * |
|
25 * @author Guilherme Blanco <guilhermeblanco@hotmail.com> |
|
26 * @author Janne Vanhala <jpvanhal@cc.hut.fi> |
|
27 * @author Roman Borschel <roman@code-factory.org> |
|
28 * @since 2.0 |
|
29 */ |
|
30 class Lexer extends \Doctrine\Common\Lexer |
|
31 { |
|
32 // All tokens that are not valid identifiers must be < 100 |
|
33 const T_NONE = 1; |
|
34 const T_INTEGER = 2; |
|
35 const T_STRING = 3; |
|
36 const T_INPUT_PARAMETER = 4; |
|
37 const T_FLOAT = 5; |
|
38 const T_CLOSE_PARENTHESIS = 6; |
|
39 const T_OPEN_PARENTHESIS = 7; |
|
40 const T_COMMA = 8; |
|
41 const T_DIVIDE = 9; |
|
42 const T_DOT = 10; |
|
43 const T_EQUALS = 11; |
|
44 const T_GREATER_THAN = 12; |
|
45 const T_LOWER_THAN = 13; |
|
46 const T_MINUS = 14; |
|
47 const T_MULTIPLY = 15; |
|
48 const T_NEGATE = 16; |
|
49 const T_PLUS = 17; |
|
50 const T_OPEN_CURLY_BRACE = 18; |
|
51 const T_CLOSE_CURLY_BRACE = 19; |
|
52 |
|
53 // All tokens that are also identifiers should be >= 100 |
|
54 const T_IDENTIFIER = 100; |
|
55 const T_ALL = 101; |
|
56 const T_AND = 102; |
|
57 const T_ANY = 103; |
|
58 const T_AS = 104; |
|
59 const T_ASC = 105; |
|
60 const T_AVG = 106; |
|
61 const T_BETWEEN = 107; |
|
62 const T_BOTH = 108; |
|
63 const T_BY = 109; |
|
64 const T_CASE = 110; |
|
65 const T_COALESCE = 111; |
|
66 const T_COUNT = 112; |
|
67 const T_DELETE = 113; |
|
68 const T_DESC = 114; |
|
69 const T_DISTINCT = 115; |
|
70 const T_EMPTY = 116; |
|
71 const T_ESCAPE = 117; |
|
72 const T_EXISTS = 118; |
|
73 const T_FALSE = 119; |
|
74 const T_FROM = 120; |
|
75 const T_GROUP = 121; |
|
76 const T_HAVING = 122; |
|
77 const T_IN = 123; |
|
78 const T_INDEX = 124; |
|
79 const T_INNER = 125; |
|
80 const T_INSTANCE = 126; |
|
81 const T_IS = 127; |
|
82 const T_JOIN = 128; |
|
83 const T_LEADING = 129; |
|
84 const T_LEFT = 130; |
|
85 const T_LIKE = 131; |
|
86 const T_MAX = 132; |
|
87 const T_MEMBER = 133; |
|
88 const T_MIN = 134; |
|
89 const T_NOT = 135; |
|
90 const T_NULL = 136; |
|
91 const T_NULLIF = 137; |
|
92 const T_OF = 138; |
|
93 const T_OR = 139; |
|
94 const T_ORDER = 140; |
|
95 const T_OUTER = 141; |
|
96 const T_SELECT = 142; |
|
97 const T_SET = 143; |
|
98 const T_SIZE = 144; |
|
99 const T_SOME = 145; |
|
100 const T_SUM = 146; |
|
101 const T_TRAILING = 147; |
|
102 const T_TRUE = 148; |
|
103 const T_UPDATE = 149; |
|
104 const T_WHEN = 150; |
|
105 const T_WHERE = 151; |
|
106 const T_WITH = 153; |
|
107 const T_PARTIAL = 154; |
|
108 const T_MOD = 155; |
|
109 |
|
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 /** |
|
121 * @inheritdoc |
|
122 */ |
|
123 protected function getCatchablePatterns() |
|
124 { |
|
125 return array( |
|
126 '[a-z_\\\][a-z0-9_\:\\\]*[a-z0-9_]{1}', |
|
127 '(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?', |
|
128 "'(?:[^']|'')*'", |
|
129 '\?[0-9]*|:[a-z]{1}[a-z0-9_]{0,}' |
|
130 ); |
|
131 } |
|
132 |
|
133 /** |
|
134 * @inheritdoc |
|
135 */ |
|
136 protected function getNonCatchablePatterns() |
|
137 { |
|
138 return array('\s+', '(.)'); |
|
139 } |
|
140 |
|
141 /** |
|
142 * @inheritdoc |
|
143 */ |
|
144 protected function getType(&$value) |
|
145 { |
|
146 $type = self::T_NONE; |
|
147 |
|
148 // Recognizing numeric values |
|
149 if (is_numeric($value)) { |
|
150 return (strpos($value, '.') !== false || stripos($value, 'e') !== false) |
|
151 ? self::T_FLOAT : self::T_INTEGER; |
|
152 } |
|
153 |
|
154 // Differentiate between quoted names, identifiers, input parameters and symbols |
|
155 if ($value[0] === "'") { |
|
156 $value = str_replace("''", "'", substr($value, 1, strlen($value) - 2)); |
|
157 return self::T_STRING; |
|
158 } else if (ctype_alpha($value[0]) || $value[0] === '_') { |
|
159 $name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value); |
|
160 |
|
161 if (defined($name)) { |
|
162 $type = constant($name); |
|
163 |
|
164 if ($type > 100) { |
|
165 return $type; |
|
166 } |
|
167 } |
|
168 |
|
169 return self::T_IDENTIFIER; |
|
170 } else if ($value[0] === '?' || $value[0] === ':') { |
|
171 return self::T_INPUT_PARAMETER; |
|
172 } else { |
|
173 switch ($value) { |
|
174 case '.': return self::T_DOT; |
|
175 case ',': return self::T_COMMA; |
|
176 case '(': return self::T_OPEN_PARENTHESIS; |
|
177 case ')': return self::T_CLOSE_PARENTHESIS; |
|
178 case '=': return self::T_EQUALS; |
|
179 case '>': return self::T_GREATER_THAN; |
|
180 case '<': return self::T_LOWER_THAN; |
|
181 case '+': return self::T_PLUS; |
|
182 case '-': return self::T_MINUS; |
|
183 case '*': return self::T_MULTIPLY; |
|
184 case '/': return self::T_DIVIDE; |
|
185 case '!': return self::T_NEGATE; |
|
186 case '{': return self::T_OPEN_CURLY_BRACE; |
|
187 case '}': return self::T_CLOSE_CURLY_BRACE; |
|
188 default: |
|
189 // Do nothing |
|
190 break; |
|
191 } |
|
192 } |
|
193 |
|
194 return $type; |
|
195 } |
|
196 } |