1: <?php
2: 3: 4: 5: 6: 7: 8:
9:
10: define('EASYLEX_SQL_UNKNOWN', 0);
11: define('EASYLEX_SQL_DIGIT', 1);
12: define('EASYLEX_SQL_LETTER', 2);
13: define('EASYLEX_SQL_STRING_LITERAL', 3);
14: define('EASYLEX_SQL_STRING_LITERAL_ESCAPE', 10);
15: define('EASYLEX_SQL_OPEN_PARENTHESIS', 4);
16: define('EASYLEX_SQL_CLOSE_PARENTHESIS', 5);
17: define('EASYLEX_SQL_SEPARATER', 6);
18: define('EASYLEX_SQL_SEMICOLON', 7);
19: define('EASYLEX_SQL_MARK', 8);
20: define('EASYLEX_SQL_COMMA', 9);
21:
22: class EasyLex_SQLToken
23: {
24: var $mType = EASYLEX_SQL_UNKNOWN;
25: var $mValue = "";
26:
27: function EasyLex_SQLToken($type, $value)
28: {
29: $this->mType = $type;
30: $this->mValue = $value;
31: }
32:
33: function getOutputValue()
34: {
35: if ($this->mType == EASYLEX_SQL_SEPARATER) {
36: return "";
37: }
38: else {
39: return $this->mValue;
40: }
41: }
42:
43: function getValue()
44: {
45: if ($this->mType == EASYLEX_SQL_SEPARATER) {
46: return "";
47: }
48:
49: if ($this->mType == EASYLEX_SQL_STRING_LITERAL) {
50: return substr($this->mValue, 1, strlen($this->mValue) - 2);
51: }
52:
53: return $this->mValue;
54: }
55: }
56:
57: 58: 59: 60: 61:
62: class EasyLex_SQLScanner
63: {
64: var $mTokens = array();
65: var $mStatus = EASYLEX_SQL_UNKNOWN;
66:
67: 68: 69:
70: var $mBuffer = array();
71:
72: var $mIndex = 0;
73:
74: var $mActiveToken = '';
75:
76: var $mActiveQuoteMark = null;
77:
78: function setBuffer($buffer)
79: {
80: $this->mBuffer = array();
81: for ($i = 0; $i < strlen($buffer); $i++) {
82: $this->mBuffer[$i] = $buffer{$i};
83: }
84:
85: $this->mIndex = 0;
86: }
87:
88: function parse()
89: {
90: while ($this->mIndex <= count($this->mBuffer)) {
91: if ($this->mIndex == count($this->mBuffer)) {
92: $ch = '';
93: $type = EASYLEX_SQL_UNKNOWN;
94: }
95: else {
96: $ch = $this->mBuffer[$this->mIndex];
97: $type = $this->_getChrType($ch);
98: }
99:
100: switch ($this->mStatus) {
101: case EASYLEX_SQL_UNKNOWN:
102: $this->_parseUnknown($ch, $type);
103: break;
104:
105: case EASYLEX_SQL_DIGIT:
106: $this->_parseDigit($ch, $type);
107: break;
108:
109: case EASYLEX_SQL_LETTER:
110: $this->_parseLetter($ch, $type);
111: break;
112:
113: case EASYLEX_SQL_STRING_LITERAL:
114: $this->_parseStringLiteral($ch, $type);
115: break;
116:
117: case EASYLEX_SQL_STRING_LITERAL_ESCAPE:
118: $this->_parseStringLiteralEscape($ch, $type);
119: break;
120:
121: case EASYLEX_SQL_OPEN_PARENTHESIS:
122: $this->_parseOpenParenthesis($ch, $type);
123: break;
124:
125: case EASYLEX_SQL_CLOSE_PARENTHESIS:
126: $this->_parseCloseParenthesis($ch, $type);
127: break;
128:
129: case EASYLEX_SQL_SEPARATER:
130: $this->_parseSeparater($ch, $type);
131: break;
132:
133: case EASYLEX_SQL_MARK:
134: $this->_parseMark($ch, $type);
135: break;
136:
137: case EASYLEX_SQL_SEMICOLON:
138: $this->_parseSemicolon($ch, $type);
139: break;
140:
141: case EASYLEX_SQL_COMMA:
142: $this->_parseComma($ch, $type);
143: break;
144: }
145: }
146: }
147:
148: 149: 150: 151: 152: 153: 154: 155:
156: function loadFile($path, $preprocess = true)
157: {
158: if (!file_exists($path)) {
159: return false;
160: }
161:
162: $fp = fopen($path, "rb");
163: if (!$fp) {
164: return false;
165: }
166:
167: $t_buff = "";
168: while ($str = fgets($fp)) {
169: if ($preprocess) {
170: $str = preg_replace("/^\s*\#.*/", "", $str);
171: }
172: $t_buff .= $str;
173: }
174:
175: $this->setBuffer($t_buff);
176:
177: fclose($fp);
178: return true;
179: }
180:
181: function _getChrType($ch)
182: {
183: if (preg_match("/\s/", $ch)) {
184: return EASYLEX_SQL_SEPARATER;
185: }
186:
187: if ($ch == '(') {
188: return EASYLEX_SQL_OPEN_PARENTHESIS;
189: }
190:
191: if ($ch == ')') {
192: return EASYLEX_SQL_CLOSE_PARENTHESIS;
193: }
194:
195: if ($ch == ';') {
196: return EASYLEX_SQL_SEMICOLON;
197: }
198:
199: if ($ch == ',') {
200: return EASYLEX_SQL_COMMA;
201: }
202:
203: if (preg_match("/[0-9]/", $ch)) {
204: return EASYLEX_SQL_DIGIT;
205: }
206:
207: if (preg_match("/[!=<>%\*]/", $ch)) {
208: return EASYLEX_SQL_MARK;
209: }
210:
211: return EASYLEX_SQL_LETTER;
212: }
213:
214: function _parseUnknown($ch, $type)
215: {
216: $this->mStatus = $type;
217: $this->mActiveToken .= $ch;
218: $this->mIndex++;
219:
220: if ($ch == "'" || $ch == '"' || $ch == '`') {
221: $this->mStatus = EASYLEX_SQL_STRING_LITERAL;
222: $this->mActiveQuoteMark = $ch;
223: }
224:
225: }
226:
227: function _parseDigit($ch, $type)
228: {
229: if ($type == EASYLEX_SQL_DIGIT) {
230: $this->mActiveToken .= $ch;
231: $this->mIndex++;
232: }
233: elseif ($type == EASYLEX_SQL_LETTER) {
234: $this->mStatus = EASYLEX_SQL_LETTER;
235: $this->mActiveToken .= $ch;
236: $this->mIndex++;
237: }
238: else {
239: $this->_createToken();
240: }
241: }
242:
243: function _parseLetter($ch, $type)
244: {
245: if ($type == EASYLEX_SQL_LETTER || $type == EASYLEX_SQL_DIGIT) {
246: $this->mActiveToken .= $ch;
247: $this->mIndex++;
248: }
249: else {
250: $this->_createToken();
251: }
252: }
253:
254: function _parseStringLiteral($ch, $type)
255: {
256: $this->mActiveToken .= $ch;
257: $this->mIndex++;
258:
259: if ($ch == "\\") {
260: $this->mStatus = EASYLEX_SQL_STRING_LITERAL_ESCAPE;
261: }
262: elseif ($ch == $this->mActiveQuoteMark) {
263: $this->_createToken();
264: }
265: }
266:
267: function _parseStringLiteralEscape($ch, $type)
268: {
269: $this->mStatus = EASYLEX_SQL_STRING_LITERAL;
270: }
271:
272: function _parseOpenParenthesis($ch, $type)
273: {
274: $this->_createToken();
275: }
276:
277: function _parseCloseParenthesis($ch, $type)
278: {
279: $this->_createToken();
280: }
281:
282: function _parseSeparater($ch, $type)
283: {
284: if ($type == EASYLEX_SQL_SEPARATER) {
285: $this->mActiveToken .= $ch;
286: $this->mIndex++;
287: }
288: else {
289:
290: $this->mStatus = EASYLEX_SQL_UNKNOWN;
291: $this->mActiveToken = "";
292: }
293: }
294:
295: function _parseSemicolon($ch, $type)
296: {
297: $this->_createToken();
298: }
299:
300: function _parseMark($ch, $type)
301: {
302: if ($type == EASYLEX_SQL_MARK) {
303: $this->mActiveToken .= $ch;
304: $this->mIndex++;
305: }
306: else {
307: $this->_createToken();
308: }
309: }
310:
311: function _parseComma($ch, $type)
312: {
313: $this->_createToken();
314: }
315:
316: function _createToken($type = null, $value = null)
317: {
318: if ($type === null) {
319: $type = $this->mStatus;
320: }
321:
322: if ($value === null) {
323: $value = $this->mActiveToken;
324: }
325:
326: $token =new EasyLex_SQLToken($type, $value);
327: $this->mTokens[] =& $token;
328:
329: $this->mStatus = EASYLEX_SQL_UNKNOWN;
330: $this->mActiveToken = "";
331:
332: return $token;
333: }
334:
335: 336: 337: 338: 339:
340: function &getOperations()
341: {
342: $ret = array();
343: $t_tokens = array();
344: $depth = 0;
345:
346: foreach (array_keys($this->mTokens) as $key) {
347: if ($this->mTokens[$key]->mType == EASYLEX_SQL_OPEN_PARENTHESIS) {
348: $depth++;
349: }
350: elseif ($this->mTokens[$key]->mType == EASYLEX_SQL_CLOSE_PARENTHESIS) {
351: $depth--;
352: }
353:
354: $t_tokens[] =& $this->mTokens[$key];
355:
356: if ($this->mTokens[$key]->mType == EASYLEX_SQL_SEMICOLON && $depth == 0) {
357: $ret[] =& $t_tokens;
358: unset($t_tokens);
359: $t_tokens = array();
360: }
361: }
362:
363: if (count($t_tokens) > 0) {
364: $ret[] =& $t_tokens;
365: unset($t_tokens);
366: }
367:
368: return $ret;
369: }
370:
371: function getSQL()
372: {
373: $sqls = array();
374: $lines =& $this->getOperations();
375:
376: foreach ($lines as $line) {
377: $t_arr = array();
378: foreach ($line as $token) {
379: $t_arr[] = $token->getOutputValue();
380: }
381: $sqls[] = join(" ", $t_arr);
382: }
383:
384: return $sqls;
385: }
386: }
387:
388: ?>
389: