PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/include/Webservices/VTQL_Lexer.php

https://github.com/vtiger-jp/vtigercrm-5.1.x-ja
PHP | 324 lines | 307 code | 9 blank | 8 comment | 43 complexity | c84dc812c244ac5812f37702d805bbfa MD5 | raw file
  1. <?php
  2. /*+***********************************************************************************
  3. * The contents of this file are subject to the vtiger CRM Public License Version 1.0
  4. * ("License"); You may not use this file except in compliance with the License
  5. * The Original Code is: vtiger CRM Open Source
  6. * The Initial Developer of the Original Code is vtiger.
  7. * Portions created by vtiger are Copyright (C) vtiger.
  8. * All Rights Reserved.
  9. *************************************************************************************/
  10. global $where_col,$orderby,$in_started,$count;
  11. $where_col = false;
  12. $orderby = false;
  13. $in_started = false;
  14. $count = false;
  15. function incrementN($lexer, $count){
  16. $i = 0;
  17. for(;$i<$count;$i++){
  18. incState($lexer);
  19. }
  20. }
  21. function incState($lexer){
  22. $lexer->current_state++;
  23. if($lexer->current_state === sizeof($lexer->mandatory_states)){
  24. $lexer->mandatory = false;
  25. }
  26. }
  27. function handleselect($lexer, $val){
  28. if($lexer->mandatory){
  29. if(strcasecmp($val, $lexer->mandatory_states[$lexer->current_state])===0){
  30. incState($lexer);
  31. return VTQL_Parser::SELECT;
  32. }
  33. }
  34. }
  35. function handlecolumn_list($lexer, $val){
  36. global $count;
  37. if($lexer->mandatory){
  38. if(!(strcasecmp($val, $lexer->mandatory_states[2])===0)){
  39. if(strcmp($val, "*")===0){
  40. if(!$count){
  41. incrementN($lexer, 1);
  42. }
  43. return VTQL_Parser::ASTERISK;
  44. }else if((strcmp($val, "(")===0)){
  45. return VTQL_Parser::PARENOPEN;
  46. }else if(strcmp($val, ")")===0){
  47. return VTQL_Parser::PARENCLOSE;
  48. }else if((strcasecmp($val, "count")===0)){
  49. $count = true;
  50. return VTQL_Parser::COUNT;
  51. }else if(strcmp($val, ",")===0){
  52. return VTQL_Parser::COMMA;
  53. }else{
  54. return VTQL_Parser::COLUMNNAME;
  55. }
  56. }else{
  57. incrementN($lexer, 2);
  58. return VTQL_Parser::FRM;
  59. }
  60. }
  61. }
  62. function handlefrom($lexer, $val){
  63. if((strcasecmp($val, $lexer->mandatory_states[$lexer->current_state])===0)){
  64. incState($lexer);
  65. return VTQL_Parser::FRM;
  66. }
  67. }
  68. function handletable($lexer, $val){
  69. if($lexer->mandatory){
  70. $lexer->current_state =0;
  71. $lexer->mandatory = false;
  72. if(!(strcasecmp($val, $lexer->optional_states[$lexer->current_state])===0)){
  73. return VTQL_Parser::TABLENAME;
  74. }
  75. }
  76. }
  77. function handlewhere($lexer, $val){
  78. global $where_col,$in_started;
  79. if((strcmp($val, "=")===0)){
  80. return VTQL_Parser::EQ;
  81. }else if((strcasecmp($val, $lexer->optional_states[$lexer->current_state])===0)){
  82. return VTQL_Parser::WHERE;
  83. }else if((strcmp($val, "<")===0)){
  84. return VTQL_Parser::LT;
  85. }else if((strcmp($val, "<=")===0)){
  86. return VTQL_Parser::LTE;
  87. }else if((strcmp($val, ">=")===0)){
  88. return VTQL_Parser::GTE;
  89. }else if((strcmp($val, "!=")===0)){
  90. return VTQL_Parser::NE;
  91. }else if((strcmp($val, ">")===0)){
  92. return VTQL_Parser::GT;
  93. }else if((strcmp($val, "(")===0)){
  94. return VTQL_Parser::PARENOPEN;
  95. }else if((strcmp($val, ")")===0)){
  96. if($in_started){
  97. $in_started = false;
  98. $where_col = false;
  99. }
  100. return VTQL_Parser::PARENCLOSE;
  101. }else if((strcasecmp($val, "and")===0)){
  102. return VTQL_Parser::LOGICAL_AND;
  103. }else if((strcasecmp($val, "or")===0)){
  104. return VTQL_Parser::LOGICAL_OR;
  105. }else if(!$where_col){
  106. $where_col = true;
  107. return VTQL_Parser::COLUMNNAME;
  108. }else if((strcasecmp($val, "in")===0)){
  109. $in_started = true;
  110. return VTQL_Parser::IN;
  111. }else if(strcmp($val, ",")===0){
  112. return VTQL_Parser::COMMA;
  113. }else if(strcasecmp($val, "like")===0){
  114. return VTQL_Parser::LIKE;
  115. }else if($where_col){
  116. if(!$in_started){
  117. $where_col = false;
  118. }
  119. return VTQL_Parser::VALUE;
  120. }
  121. }
  122. function handleorderby($lexer, $val){
  123. global $orderby;
  124. if(!$orderby){
  125. $orderby = true;
  126. return VTQL_Parser::ORDERBY;
  127. }
  128. if(strcmp($val, ",")===0){
  129. return VTQL_Parser::COMMA;
  130. }else if(strcasecmp($val, "asc")===0){
  131. return VTQL_Parser::ASC;
  132. }else if(strcasecmp($val, "desc")===0){
  133. return VTQL_Parser::DESC;
  134. }else{
  135. return VTQL_Parser::COLUMNNAME;
  136. }
  137. }
  138. function handlelimit($lexer, $val){
  139. if((strcasecmp($val, "limit")===0)){
  140. return VTQL_Parser::LIMIT;
  141. }else if((strcmp($val, "(")===0)){
  142. return VTQL_Parser::PARENOPEN;
  143. }else if((strcmp($val, ")")===0)){
  144. return VTQL_Parser::PARENCLOSE;
  145. }else if(strcmp($val, ",")===0){
  146. return VTQL_Parser::COMMA;
  147. }else{
  148. return VTQL_Parser::VALUE;
  149. }
  150. }
  151. function handleend($lexer, $val){
  152. return VTQL_Parser::SEMICOLON;
  153. }
  154. class VTQL_Lexer{
  155. private $index;
  156. public $token;
  157. public $value;
  158. public $linenum;
  159. public $state = 1;
  160. private $data;
  161. public $mandatory_states = array('select','column_list','from','table');
  162. public $optional_states = array('where', 'orderby', 'limit');
  163. public $mandatory ;
  164. public $current_state ;
  165. function __construct($data)
  166. {
  167. $this->index = 0;
  168. $this->data = $data;
  169. $this->linenum = 1;
  170. $this->mandatory = true;
  171. $this->current_state = 0;
  172. }
  173. function __toString(){
  174. return $this->token."";
  175. }
  176. private $_yy_state = 1;
  177. private $_yy_stack = array();
  178. function yylex()
  179. {
  180. return $this->{'yylex' . $this->_yy_state}();
  181. }
  182. function yypushstate($state)
  183. {
  184. array_push($this->_yy_stack, $this->_yy_state);
  185. $this->_yy_state = $state;
  186. }
  187. function yypopstate()
  188. {
  189. $this->_yy_state = array_pop($this->_yy_stack);
  190. }
  191. function yybegin($state)
  192. {
  193. $this->_yy_state = $state;
  194. }
  195. function yylex1()
  196. {
  197. $tokenMap = array (
  198. 1 => 2,
  199. 4 => 0,
  200. );
  201. if ($this->index >= strlen($this->data)) {
  202. return false; // end of input
  203. }
  204. $yy_global_pattern = "/^((\\w+|'(?:[^']|'')+'|\\(|\\)|(\\+|-)?\\d+|,|\\*|=|<|>|;))|^([ \t\r\n]+)/";
  205. do {
  206. if (preg_match($yy_global_pattern, substr($this->data, $this->index), $yymatches)) {
  207. $yysubmatches = $yymatches;
  208. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  209. if (!count($yymatches)) {
  210. throw new Exception('Error: lexing failed because a rule matched' .
  211. 'an empty string. Input "' . substr($this->data,
  212. $this->index, 5) . '... state INITR');
  213. }
  214. next($yymatches); // skip global match
  215. $this->token = key($yymatches); // token number
  216. if ($tokenMap[$this->token]) {
  217. // extract sub-patterns for passing to lex function
  218. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  219. $tokenMap[$this->token]);
  220. } else {
  221. $yysubmatches = array();
  222. }
  223. $this->value = current($yymatches); // token value
  224. $r = $this->{'yy_r1_' . $this->token}($yysubmatches);
  225. if ($r === null) {
  226. $this->index += strlen($this->value);
  227. $this->linenum += substr_count("\n", $this->value);
  228. // accept this token
  229. return true;
  230. } elseif ($r === true) {
  231. // we have changed state
  232. // process this token in the new state
  233. return $this->yylex();
  234. } elseif ($r === false) {
  235. $this->index += strlen($this->value);
  236. $this->linenum += substr_count("\n", $this->value);
  237. if ($this->index >= strlen($this->data)) {
  238. return false; // end of input
  239. }
  240. // skip this token
  241. continue;
  242. } else { $yy_yymore_patterns = array(
  243. 1 => "^([ \t\r\n]+)",
  244. 4 => "",
  245. );
  246. // yymore is needed
  247. do {
  248. if (!strlen($yy_yymore_patterns[$this->token])) {
  249. throw new Exception('cannot do yymore for the last token');
  250. }
  251. if (preg_match($yy_yymore_patterns[$this->token],
  252. substr($this->data, $this->index), $yymatches)) {
  253. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  254. next($yymatches); // skip global match
  255. $this->token = key($yymatches); // token number
  256. $this->value = current($yymatches); // token value
  257. $this->linenum = substr_count("\n", $this->value);
  258. }
  259. } while ($this->{'yy_r1_' . $this->token}() !== null);
  260. // accept
  261. $this->index += strlen($this->value);
  262. $this->linenum += substr_count("\n", $this->value);
  263. return true;
  264. }
  265. } else {
  266. throw new Exception('Unexpected input at line' . $this->linenum .
  267. ': ' . $this->data[$this->index]);
  268. }
  269. break;
  270. } while (true);
  271. } // end function
  272. const INITR = 1;
  273. function yy_r1_1($yy_subpatterns)
  274. {
  275. global $orderby;
  276. //echo "<br> ql state: ",$this->current_state," ",$this->value,"<br>";
  277. if($this->mandatory){
  278. //echo "<br> ql state: ",$this->current_state," ",$this->value,"<br>";
  279. $handler = 'handle'.$this->mandatory_states[$this->current_state];
  280. $this->token = $handler($this, $this->value);
  281. }else{
  282. $str = $this->value;
  283. if(strcmp($this->value, ";")===0){
  284. $this->token = handleend($this, $this->value);
  285. return;
  286. }
  287. if(strcasecmp($this->value, "order")===0){
  288. $orderby = true;
  289. return false;
  290. }else if(strcasecmp($this->value, "by") ===0 && $orderby ===true){
  291. $orderby = false;
  292. $this->current_state = 1;
  293. }
  294. $index = array_search(strtolower($str), $this->optional_states, true);
  295. if($index !== false){
  296. $this->current_state = $index;
  297. }
  298. $handler = 'handle'.$this->optional_states[$this->current_state];
  299. $this->token = $handler($this, $this->value);
  300. }//$this->yypushstate($this->value);
  301. }
  302. function yy_r1_4($yy_subpatterns)
  303. {
  304. return false;
  305. }
  306. }
  307. ?>