smarty_internal_configfilelexer.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. <?php
  2. /**
  3. * Smarty Internal Plugin Configfilelexer
  4. * This is the lexer to break the config file source into tokens
  5. *
  6. * @package Smarty
  7. * @subpackage Config
  8. * @author Uwe Tews
  9. */
  10. /**
  11. * Smarty Internal Plugin Configfilelexer
  12. */
  13. class Smarty_Internal_Configfilelexer
  14. {
  15. public $data;
  16. public $counter;
  17. public $token;
  18. public $value;
  19. public $node;
  20. public $line;
  21. private $state = 1;
  22. public $yyTraceFILE;
  23. public $yyTracePrompt;
  24. public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE');
  25. public $smarty_token_names = array( // Text for parser error messages
  26. );
  27. function __construct($data, $compiler)
  28. {
  29. // set instance object
  30. self::instance($this);
  31. $this->data = $data . "\n"; //now all lines are \n-terminated
  32. $this->counter = 0;
  33. if (preg_match('/^\xEF\xBB\xBF/', $this->data, $match)) {
  34. $this->counter += strlen($match[0]);
  35. }
  36. $this->line = 1;
  37. $this->compiler = $compiler;
  38. $this->smarty = $compiler->smarty;
  39. }
  40. public static function &instance($new_instance = null)
  41. {
  42. static $instance = null;
  43. if (isset($new_instance) && is_object($new_instance)) {
  44. $instance = $new_instance;
  45. }
  46. return $instance;
  47. }
  48. public function PrintTrace()
  49. {
  50. $this->yyTraceFILE = fopen('php://output', 'w');
  51. $this->yyTracePrompt = '<br>';
  52. }
  53. private $_yy_state = 1;
  54. private $_yy_stack = array();
  55. public function yylex()
  56. {
  57. return $this->{'yylex' . $this->_yy_state}();
  58. }
  59. public function yypushstate($state)
  60. {
  61. if ($this->yyTraceFILE) {
  62. fprintf($this->yyTraceFILE, "%sState push %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
  63. }
  64. array_push($this->_yy_stack, $this->_yy_state);
  65. $this->_yy_state = $state;
  66. if ($this->yyTraceFILE) {
  67. fprintf($this->yyTraceFILE, "%snew State %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
  68. }
  69. }
  70. public function yypopstate()
  71. {
  72. if ($this->yyTraceFILE) {
  73. fprintf($this->yyTraceFILE, "%sState pop %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
  74. }
  75. $this->_yy_state = array_pop($this->_yy_stack);
  76. if ($this->yyTraceFILE) {
  77. fprintf($this->yyTraceFILE, "%snew State %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
  78. }
  79. }
  80. public function yybegin($state)
  81. {
  82. $this->_yy_state = $state;
  83. if ($this->yyTraceFILE) {
  84. fprintf($this->yyTraceFILE, "%sState set %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
  85. }
  86. }
  87. public function yylex1()
  88. {
  89. $tokenMap = array(
  90. 1 => 0,
  91. 2 => 0,
  92. 3 => 0,
  93. 4 => 0,
  94. 5 => 0,
  95. 6 => 0,
  96. 7 => 0,
  97. 8 => 0,
  98. );
  99. if ($this->counter >= strlen($this->data)) {
  100. return false; // end of input
  101. }
  102. $yy_global_pattern = "/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/iS";
  103. do {
  104. if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
  105. $yysubmatches = $yymatches;
  106. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  107. if (!count($yymatches)) {
  108. throw new Exception('Error: lexing failed because a rule matched' .
  109. ' an empty string. Input "' . substr($this->data,
  110. $this->counter, 5) . '... state START');
  111. }
  112. next($yymatches); // skip global match
  113. $this->token = key($yymatches); // token number
  114. if ($tokenMap[$this->token]) {
  115. // extract sub-patterns for passing to lex function
  116. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  117. $tokenMap[$this->token]);
  118. } else {
  119. $yysubmatches = array();
  120. }
  121. $this->value = current($yymatches); // token value
  122. $r = $this->{'yy_r1_' . $this->token}($yysubmatches);
  123. if ($r === null) {
  124. $this->counter += strlen($this->value);
  125. $this->line += substr_count($this->value, "\n");
  126. // accept this token
  127. return true;
  128. } elseif ($r === true) {
  129. // we have changed state
  130. // process this token in the new state
  131. return $this->yylex();
  132. } elseif ($r === false) {
  133. $this->counter += strlen($this->value);
  134. $this->line += substr_count($this->value, "\n");
  135. if ($this->counter >= strlen($this->data)) {
  136. return false; // end of input
  137. }
  138. // skip this token
  139. continue;
  140. }
  141. } else {
  142. throw new Exception('Unexpected input at line' . $this->line .
  143. ': ' . $this->data[$this->counter]);
  144. }
  145. break;
  146. } while (true);
  147. } // end function
  148. const START = 1;
  149. function yy_r1_1($yy_subpatterns)
  150. {
  151. $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART;
  152. $this->yypushstate(self::COMMENT);
  153. }
  154. function yy_r1_2($yy_subpatterns)
  155. {
  156. $this->token = Smarty_Internal_Configfileparser::TPC_OPENB;
  157. $this->yypushstate(self::SECTION);
  158. }
  159. function yy_r1_3($yy_subpatterns)
  160. {
  161. $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB;
  162. }
  163. function yy_r1_4($yy_subpatterns)
  164. {
  165. $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL;
  166. $this->yypushstate(self::VALUE);
  167. }
  168. function yy_r1_5($yy_subpatterns)
  169. {
  170. return false;
  171. }
  172. function yy_r1_6($yy_subpatterns)
  173. {
  174. $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
  175. }
  176. function yy_r1_7($yy_subpatterns)
  177. {
  178. $this->token = Smarty_Internal_Configfileparser::TPC_ID;
  179. }
  180. function yy_r1_8($yy_subpatterns)
  181. {
  182. $this->token = Smarty_Internal_Configfileparser::TPC_OTHER;
  183. }
  184. public function yylex2()
  185. {
  186. $tokenMap = array(
  187. 1 => 0,
  188. 2 => 0,
  189. 3 => 0,
  190. 4 => 0,
  191. 5 => 0,
  192. 6 => 0,
  193. 7 => 0,
  194. 8 => 0,
  195. 9 => 0,
  196. );
  197. if ($this->counter >= strlen($this->data)) {
  198. return false; // end of input
  199. }
  200. $yy_global_pattern = "/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
  201. do {
  202. if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
  203. $yysubmatches = $yymatches;
  204. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  205. if (!count($yymatches)) {
  206. throw new Exception('Error: lexing failed because a rule matched' .
  207. ' an empty string. Input "' . substr($this->data,
  208. $this->counter, 5) . '... state VALUE');
  209. }
  210. next($yymatches); // skip global match
  211. $this->token = key($yymatches); // token number
  212. if ($tokenMap[$this->token]) {
  213. // extract sub-patterns for passing to lex function
  214. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  215. $tokenMap[$this->token]);
  216. } else {
  217. $yysubmatches = array();
  218. }
  219. $this->value = current($yymatches); // token value
  220. $r = $this->{'yy_r2_' . $this->token}($yysubmatches);
  221. if ($r === null) {
  222. $this->counter += strlen($this->value);
  223. $this->line += substr_count($this->value, "\n");
  224. // accept this token
  225. return true;
  226. } elseif ($r === true) {
  227. // we have changed state
  228. // process this token in the new state
  229. return $this->yylex();
  230. } elseif ($r === false) {
  231. $this->counter += strlen($this->value);
  232. $this->line += substr_count($this->value, "\n");
  233. if ($this->counter >= strlen($this->data)) {
  234. return false; // end of input
  235. }
  236. // skip this token
  237. continue;
  238. }
  239. } else {
  240. throw new Exception('Unexpected input at line' . $this->line .
  241. ': ' . $this->data[$this->counter]);
  242. }
  243. break;
  244. } while (true);
  245. } // end function
  246. const VALUE = 2;
  247. function yy_r2_1($yy_subpatterns)
  248. {
  249. return false;
  250. }
  251. function yy_r2_2($yy_subpatterns)
  252. {
  253. $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT;
  254. $this->yypopstate();
  255. }
  256. function yy_r2_3($yy_subpatterns)
  257. {
  258. $this->token = Smarty_Internal_Configfileparser::TPC_INT;
  259. $this->yypopstate();
  260. }
  261. function yy_r2_4($yy_subpatterns)
  262. {
  263. $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES;
  264. $this->yypushstate(self::TRIPPLE);
  265. }
  266. function yy_r2_5($yy_subpatterns)
  267. {
  268. $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING;
  269. $this->yypopstate();
  270. }
  271. function yy_r2_6($yy_subpatterns)
  272. {
  273. $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING;
  274. $this->yypopstate();
  275. }
  276. function yy_r2_7($yy_subpatterns)
  277. {
  278. if (!$this->smarty->config_booleanize || !in_array(strtolower($this->value), Array("true", "false", "on", "off", "yes", "no"))) {
  279. $this->yypopstate();
  280. $this->yypushstate(self::NAKED_STRING_VALUE);
  281. return true; //reprocess in new state
  282. } else {
  283. $this->token = Smarty_Internal_Configfileparser::TPC_BOOL;
  284. $this->yypopstate();
  285. }
  286. }
  287. function yy_r2_8($yy_subpatterns)
  288. {
  289. $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
  290. $this->yypopstate();
  291. }
  292. function yy_r2_9($yy_subpatterns)
  293. {
  294. $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
  295. $this->value = "";
  296. $this->yypopstate();
  297. }
  298. public function yylex3()
  299. {
  300. $tokenMap = array(
  301. 1 => 0,
  302. );
  303. if ($this->counter >= strlen($this->data)) {
  304. return false; // end of input
  305. }
  306. $yy_global_pattern = "/\G([^\n]+?(?=[ \t\r]*\n))/iS";
  307. do {
  308. if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
  309. $yysubmatches = $yymatches;
  310. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  311. if (!count($yymatches)) {
  312. throw new Exception('Error: lexing failed because a rule matched' .
  313. ' an empty string. Input "' . substr($this->data,
  314. $this->counter, 5) . '... state NAKED_STRING_VALUE');
  315. }
  316. next($yymatches); // skip global match
  317. $this->token = key($yymatches); // token number
  318. if ($tokenMap[$this->token]) {
  319. // extract sub-patterns for passing to lex function
  320. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  321. $tokenMap[$this->token]);
  322. } else {
  323. $yysubmatches = array();
  324. }
  325. $this->value = current($yymatches); // token value
  326. $r = $this->{'yy_r3_' . $this->token}($yysubmatches);
  327. if ($r === null) {
  328. $this->counter += strlen($this->value);
  329. $this->line += substr_count($this->value, "\n");
  330. // accept this token
  331. return true;
  332. } elseif ($r === true) {
  333. // we have changed state
  334. // process this token in the new state
  335. return $this->yylex();
  336. } elseif ($r === false) {
  337. $this->counter += strlen($this->value);
  338. $this->line += substr_count($this->value, "\n");
  339. if ($this->counter >= strlen($this->data)) {
  340. return false; // end of input
  341. }
  342. // skip this token
  343. continue;
  344. }
  345. } else {
  346. throw new Exception('Unexpected input at line' . $this->line .
  347. ': ' . $this->data[$this->counter]);
  348. }
  349. break;
  350. } while (true);
  351. } // end function
  352. const NAKED_STRING_VALUE = 3;
  353. function yy_r3_1($yy_subpatterns)
  354. {
  355. $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
  356. $this->yypopstate();
  357. }
  358. public function yylex4()
  359. {
  360. $tokenMap = array(
  361. 1 => 0,
  362. 2 => 0,
  363. 3 => 0,
  364. );
  365. if ($this->counter >= strlen($this->data)) {
  366. return false; // end of input
  367. }
  368. $yy_global_pattern = "/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
  369. do {
  370. if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
  371. $yysubmatches = $yymatches;
  372. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  373. if (!count($yymatches)) {
  374. throw new Exception('Error: lexing failed because a rule matched' .
  375. ' an empty string. Input "' . substr($this->data,
  376. $this->counter, 5) . '... state COMMENT');
  377. }
  378. next($yymatches); // skip global match
  379. $this->token = key($yymatches); // token number
  380. if ($tokenMap[$this->token]) {
  381. // extract sub-patterns for passing to lex function
  382. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  383. $tokenMap[$this->token]);
  384. } else {
  385. $yysubmatches = array();
  386. }
  387. $this->value = current($yymatches); // token value
  388. $r = $this->{'yy_r4_' . $this->token}($yysubmatches);
  389. if ($r === null) {
  390. $this->counter += strlen($this->value);
  391. $this->line += substr_count($this->value, "\n");
  392. // accept this token
  393. return true;
  394. } elseif ($r === true) {
  395. // we have changed state
  396. // process this token in the new state
  397. return $this->yylex();
  398. } elseif ($r === false) {
  399. $this->counter += strlen($this->value);
  400. $this->line += substr_count($this->value, "\n");
  401. if ($this->counter >= strlen($this->data)) {
  402. return false; // end of input
  403. }
  404. // skip this token
  405. continue;
  406. }
  407. } else {
  408. throw new Exception('Unexpected input at line' . $this->line .
  409. ': ' . $this->data[$this->counter]);
  410. }
  411. break;
  412. } while (true);
  413. } // end function
  414. const COMMENT = 4;
  415. function yy_r4_1($yy_subpatterns)
  416. {
  417. return false;
  418. }
  419. function yy_r4_2($yy_subpatterns)
  420. {
  421. $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
  422. }
  423. function yy_r4_3($yy_subpatterns)
  424. {
  425. $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
  426. $this->yypopstate();
  427. }
  428. public function yylex5()
  429. {
  430. $tokenMap = array(
  431. 1 => 0,
  432. 2 => 0,
  433. );
  434. if ($this->counter >= strlen($this->data)) {
  435. return false; // end of input
  436. }
  437. $yy_global_pattern = "/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/iS";
  438. do {
  439. if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
  440. $yysubmatches = $yymatches;
  441. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  442. if (!count($yymatches)) {
  443. throw new Exception('Error: lexing failed because a rule matched' .
  444. ' an empty string. Input "' . substr($this->data,
  445. $this->counter, 5) . '... state SECTION');
  446. }
  447. next($yymatches); // skip global match
  448. $this->token = key($yymatches); // token number
  449. if ($tokenMap[$this->token]) {
  450. // extract sub-patterns for passing to lex function
  451. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  452. $tokenMap[$this->token]);
  453. } else {
  454. $yysubmatches = array();
  455. }
  456. $this->value = current($yymatches); // token value
  457. $r = $this->{'yy_r5_' . $this->token}($yysubmatches);
  458. if ($r === null) {
  459. $this->counter += strlen($this->value);
  460. $this->line += substr_count($this->value, "\n");
  461. // accept this token
  462. return true;
  463. } elseif ($r === true) {
  464. // we have changed state
  465. // process this token in the new state
  466. return $this->yylex();
  467. } elseif ($r === false) {
  468. $this->counter += strlen($this->value);
  469. $this->line += substr_count($this->value, "\n");
  470. if ($this->counter >= strlen($this->data)) {
  471. return false; // end of input
  472. }
  473. // skip this token
  474. continue;
  475. }
  476. } else {
  477. throw new Exception('Unexpected input at line' . $this->line .
  478. ': ' . $this->data[$this->counter]);
  479. }
  480. break;
  481. } while (true);
  482. } // end function
  483. const SECTION = 5;
  484. function yy_r5_1($yy_subpatterns)
  485. {
  486. $this->token = Smarty_Internal_Configfileparser::TPC_DOT;
  487. }
  488. function yy_r5_2($yy_subpatterns)
  489. {
  490. $this->token = Smarty_Internal_Configfileparser::TPC_SECTION;
  491. $this->yypopstate();
  492. }
  493. public function yylex6()
  494. {
  495. $tokenMap = array(
  496. 1 => 0,
  497. 2 => 0,
  498. );
  499. if ($this->counter >= strlen($this->data)) {
  500. return false; // end of input
  501. }
  502. $yy_global_pattern = "/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/iS";
  503. do {
  504. if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
  505. $yysubmatches = $yymatches;
  506. $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
  507. if (!count($yymatches)) {
  508. throw new Exception('Error: lexing failed because a rule matched' .
  509. ' an empty string. Input "' . substr($this->data,
  510. $this->counter, 5) . '... state TRIPPLE');
  511. }
  512. next($yymatches); // skip global match
  513. $this->token = key($yymatches); // token number
  514. if ($tokenMap[$this->token]) {
  515. // extract sub-patterns for passing to lex function
  516. $yysubmatches = array_slice($yysubmatches, $this->token + 1,
  517. $tokenMap[$this->token]);
  518. } else {
  519. $yysubmatches = array();
  520. }
  521. $this->value = current($yymatches); // token value
  522. $r = $this->{'yy_r6_' . $this->token}($yysubmatches);
  523. if ($r === null) {
  524. $this->counter += strlen($this->value);
  525. $this->line += substr_count($this->value, "\n");
  526. // accept this token
  527. return true;
  528. } elseif ($r === true) {
  529. // we have changed state
  530. // process this token in the new state
  531. return $this->yylex();
  532. } elseif ($r === false) {
  533. $this->counter += strlen($this->value);
  534. $this->line += substr_count($this->value, "\n");
  535. if ($this->counter >= strlen($this->data)) {
  536. return false; // end of input
  537. }
  538. // skip this token
  539. continue;
  540. }
  541. } else {
  542. throw new Exception('Unexpected input at line' . $this->line .
  543. ': ' . $this->data[$this->counter]);
  544. }
  545. break;
  546. } while (true);
  547. } // end function
  548. const TRIPPLE = 6;
  549. function yy_r6_1($yy_subpatterns)
  550. {
  551. $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END;
  552. $this->yypopstate();
  553. $this->yypushstate(self::START);
  554. }
  555. function yy_r6_2($yy_subpatterns)
  556. {
  557. $to = strlen($this->data);
  558. preg_match("/\"\"\"[ \t\r]*[\n#;]/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
  559. if (isset($match[0][1])) {
  560. $to = $match[0][1];
  561. } else {
  562. $this->compiler->trigger_template_error("missing or misspelled literal closing tag");
  563. }
  564. $this->value = substr($this->data, $this->counter, $to - $this->counter);
  565. $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT;
  566. }
  567. }