3 * Smarty Internal Plugin Configfilelexer
4 * This is the lexer to break the config file source into tokens
12 * Smarty Internal Plugin Configfilelexer
14 class Smarty_Internal_Configfilelexer
25 public $yyTracePrompt;
26 public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE');
27 public $smarty_token_names = array( // Text for parser error messages
30 function __construct($data, $compiler)
32 // set instance object
33 self
::instance($this);
34 $this->data
= $data . "\n"; //now all lines are \n-terminated
36 if (preg_match('/^\xEF\xBB\xBF/', $this->data
, $match)) {
37 $this->counter +
= strlen($match[0]);
40 $this->compiler
= $compiler;
41 $this->smarty
= $compiler->smarty
;
44 public static function &instance($new_instance = null)
46 static $instance = null;
47 if (isset($new_instance) && is_object($new_instance)) {
48 $instance = $new_instance;
53 public function PrintTrace()
55 $this->yyTraceFILE
= fopen('php://output', 'w');
56 $this->yyTracePrompt
= '<br>';
59 private $_yy_state = 1;
60 private $_yy_stack = array();
62 public function yylex()
64 return $this->{'yylex' . $this->_yy_state
}();
67 public function yypushstate($state)
69 if ($this->yyTraceFILE
) {
70 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
);
72 array_push($this->_yy_stack
, $this->_yy_state
);
73 $this->_yy_state
= $state;
74 if ($this->yyTraceFILE
) {
75 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
);
79 public function yypopstate()
81 if ($this->yyTraceFILE
) {
82 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
);
84 $this->_yy_state
= array_pop($this->_yy_stack
);
85 if ($this->yyTraceFILE
) {
86 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
);
90 public function yybegin($state)
92 $this->_yy_state
= $state;
93 if ($this->yyTraceFILE
) {
94 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
);
98 public function yylex1()
110 if ($this->counter
>= strlen($this->data
)) {
111 return false; // end of input
113 $yy_global_pattern = "/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/iS";
116 if (preg_match($yy_global_pattern, $this->data
, $yymatches, null, $this->counter
)) {
117 $yysubmatches = $yymatches;
118 $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
119 if (!count($yymatches)) {
120 throw new Exception('Error: lexing failed because a rule matched' .
121 ' an empty string. Input "' . substr($this->data
,
122 $this->counter
, 5) . '... state START');
124 next($yymatches); // skip global match
125 $this->token
= key($yymatches); // token number
126 if ($tokenMap[$this->token
]) {
127 // extract sub-patterns for passing to lex function
128 $yysubmatches = array_slice($yysubmatches, $this->token +
1,
129 $tokenMap[$this->token
]);
131 $yysubmatches = array();
133 $this->value
= current($yymatches); // token value
134 $r = $this->{'yy_r1_' . $this->token
}($yysubmatches);
136 $this->counter +
= strlen($this->value
);
137 $this->line +
= substr_count($this->value
, "\n");
140 } elseif ($r === true) {
141 // we have changed state
142 // process this token in the new state
143 return $this->yylex();
144 } elseif ($r === false) {
145 $this->counter +
= strlen($this->value
);
146 $this->line +
= substr_count($this->value
, "\n");
147 if ($this->counter
>= strlen($this->data
)) {
148 return false; // end of input
154 throw new Exception('Unexpected input at line' . $this->line
.
155 ': ' . $this->data
[$this->counter
]);
163 function yy_r1_1($yy_subpatterns)
166 $this->token
= Smarty_Internal_Configfileparser
::TPC_COMMENTSTART
;
167 $this->yypushstate(self
::COMMENT
);
170 function yy_r1_2($yy_subpatterns)
173 $this->token
= Smarty_Internal_Configfileparser
::TPC_OPENB
;
174 $this->yypushstate(self
::SECTION
);
177 function yy_r1_3($yy_subpatterns)
180 $this->token
= Smarty_Internal_Configfileparser
::TPC_CLOSEB
;
183 function yy_r1_4($yy_subpatterns)
186 $this->token
= Smarty_Internal_Configfileparser
::TPC_EQUAL
;
187 $this->yypushstate(self
::VALUE
);
190 function yy_r1_5($yy_subpatterns)
196 function yy_r1_6($yy_subpatterns)
199 $this->token
= Smarty_Internal_Configfileparser
::TPC_NEWLINE
;
202 function yy_r1_7($yy_subpatterns)
205 $this->token
= Smarty_Internal_Configfileparser
::TPC_ID
;
208 function yy_r1_8($yy_subpatterns)
211 $this->token
= Smarty_Internal_Configfileparser
::TPC_OTHER
;
214 public function yylex2()
227 if ($this->counter
>= strlen($this->data
)) {
228 return false; // end of input
230 $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";
233 if (preg_match($yy_global_pattern, $this->data
, $yymatches, null, $this->counter
)) {
234 $yysubmatches = $yymatches;
235 $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
236 if (!count($yymatches)) {
237 throw new Exception('Error: lexing failed because a rule matched' .
238 ' an empty string. Input "' . substr($this->data
,
239 $this->counter
, 5) . '... state VALUE');
241 next($yymatches); // skip global match
242 $this->token
= key($yymatches); // token number
243 if ($tokenMap[$this->token
]) {
244 // extract sub-patterns for passing to lex function
245 $yysubmatches = array_slice($yysubmatches, $this->token +
1,
246 $tokenMap[$this->token
]);
248 $yysubmatches = array();
250 $this->value
= current($yymatches); // token value
251 $r = $this->{'yy_r2_' . $this->token
}($yysubmatches);
253 $this->counter +
= strlen($this->value
);
254 $this->line +
= substr_count($this->value
, "\n");
257 } elseif ($r === true) {
258 // we have changed state
259 // process this token in the new state
260 return $this->yylex();
261 } elseif ($r === false) {
262 $this->counter +
= strlen($this->value
);
263 $this->line +
= substr_count($this->value
, "\n");
264 if ($this->counter
>= strlen($this->data
)) {
265 return false; // end of input
271 throw new Exception('Unexpected input at line' . $this->line
.
272 ': ' . $this->data
[$this->counter
]);
280 function yy_r2_1($yy_subpatterns)
286 function yy_r2_2($yy_subpatterns)
289 $this->token
= Smarty_Internal_Configfileparser
::TPC_FLOAT
;
293 function yy_r2_3($yy_subpatterns)
296 $this->token
= Smarty_Internal_Configfileparser
::TPC_INT
;
300 function yy_r2_4($yy_subpatterns)
303 $this->token
= Smarty_Internal_Configfileparser
::TPC_TRIPPLE_QUOTES
;
304 $this->yypushstate(self
::TRIPPLE
);
307 function yy_r2_5($yy_subpatterns)
310 $this->token
= Smarty_Internal_Configfileparser
::TPC_SINGLE_QUOTED_STRING
;
314 function yy_r2_6($yy_subpatterns)
317 $this->token
= Smarty_Internal_Configfileparser
::TPC_DOUBLE_QUOTED_STRING
;
321 function yy_r2_7($yy_subpatterns)
324 if (!$this->smarty
->config_booleanize ||
!in_array(strtolower($this->value
), Array("true", "false", "on", "off", "yes", "no"))) {
326 $this->yypushstate(self
::NAKED_STRING_VALUE
);
327 return true; //reprocess in new state
329 $this->token
= Smarty_Internal_Configfileparser
::TPC_BOOL
;
334 function yy_r2_8($yy_subpatterns)
337 $this->token
= Smarty_Internal_Configfileparser
::TPC_NAKED_STRING
;
341 function yy_r2_9($yy_subpatterns)
344 $this->token
= Smarty_Internal_Configfileparser
::TPC_NAKED_STRING
;
349 public function yylex3()
354 if ($this->counter
>= strlen($this->data
)) {
355 return false; // end of input
357 $yy_global_pattern = "/\G([^\n]+?(?=[ \t\r]*\n))/iS";
360 if (preg_match($yy_global_pattern, $this->data
, $yymatches, null, $this->counter
)) {
361 $yysubmatches = $yymatches;
362 $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
363 if (!count($yymatches)) {
364 throw new Exception('Error: lexing failed because a rule matched' .
365 ' an empty string. Input "' . substr($this->data
,
366 $this->counter
, 5) . '... state NAKED_STRING_VALUE');
368 next($yymatches); // skip global match
369 $this->token
= key($yymatches); // token number
370 if ($tokenMap[$this->token
]) {
371 // extract sub-patterns for passing to lex function
372 $yysubmatches = array_slice($yysubmatches, $this->token +
1,
373 $tokenMap[$this->token
]);
375 $yysubmatches = array();
377 $this->value
= current($yymatches); // token value
378 $r = $this->{'yy_r3_' . $this->token
}($yysubmatches);
380 $this->counter +
= strlen($this->value
);
381 $this->line +
= substr_count($this->value
, "\n");
384 } elseif ($r === true) {
385 // we have changed state
386 // process this token in the new state
387 return $this->yylex();
388 } elseif ($r === false) {
389 $this->counter +
= strlen($this->value
);
390 $this->line +
= substr_count($this->value
, "\n");
391 if ($this->counter
>= strlen($this->data
)) {
392 return false; // end of input
398 throw new Exception('Unexpected input at line' . $this->line
.
399 ': ' . $this->data
[$this->counter
]);
405 const NAKED_STRING_VALUE
= 3;
407 function yy_r3_1($yy_subpatterns)
410 $this->token
= Smarty_Internal_Configfileparser
::TPC_NAKED_STRING
;
414 public function yylex4()
421 if ($this->counter
>= strlen($this->data
)) {
422 return false; // end of input
424 $yy_global_pattern = "/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
427 if (preg_match($yy_global_pattern, $this->data
, $yymatches, null, $this->counter
)) {
428 $yysubmatches = $yymatches;
429 $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
430 if (!count($yymatches)) {
431 throw new Exception('Error: lexing failed because a rule matched' .
432 ' an empty string. Input "' . substr($this->data
,
433 $this->counter
, 5) . '... state COMMENT');
435 next($yymatches); // skip global match
436 $this->token
= key($yymatches); // token number
437 if ($tokenMap[$this->token
]) {
438 // extract sub-patterns for passing to lex function
439 $yysubmatches = array_slice($yysubmatches, $this->token +
1,
440 $tokenMap[$this->token
]);
442 $yysubmatches = array();
444 $this->value
= current($yymatches); // token value
445 $r = $this->{'yy_r4_' . $this->token
}($yysubmatches);
447 $this->counter +
= strlen($this->value
);
448 $this->line +
= substr_count($this->value
, "\n");
451 } elseif ($r === true) {
452 // we have changed state
453 // process this token in the new state
454 return $this->yylex();
455 } elseif ($r === false) {
456 $this->counter +
= strlen($this->value
);
457 $this->line +
= substr_count($this->value
, "\n");
458 if ($this->counter
>= strlen($this->data
)) {
459 return false; // end of input
465 throw new Exception('Unexpected input at line' . $this->line
.
466 ': ' . $this->data
[$this->counter
]);
474 function yy_r4_1($yy_subpatterns)
480 function yy_r4_2($yy_subpatterns)
483 $this->token
= Smarty_Internal_Configfileparser
::TPC_NAKED_STRING
;
486 function yy_r4_3($yy_subpatterns)
489 $this->token
= Smarty_Internal_Configfileparser
::TPC_NEWLINE
;
493 public function yylex5()
499 if ($this->counter
>= strlen($this->data
)) {
500 return false; // end of input
502 $yy_global_pattern = "/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/iS";
505 if (preg_match($yy_global_pattern, $this->data
, $yymatches, null, $this->counter
)) {
506 $yysubmatches = $yymatches;
507 $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
508 if (!count($yymatches)) {
509 throw new Exception('Error: lexing failed because a rule matched' .
510 ' an empty string. Input "' . substr($this->data
,
511 $this->counter
, 5) . '... state SECTION');
513 next($yymatches); // skip global match
514 $this->token
= key($yymatches); // token number
515 if ($tokenMap[$this->token
]) {
516 // extract sub-patterns for passing to lex function
517 $yysubmatches = array_slice($yysubmatches, $this->token +
1,
518 $tokenMap[$this->token
]);
520 $yysubmatches = array();
522 $this->value
= current($yymatches); // token value
523 $r = $this->{'yy_r5_' . $this->token
}($yysubmatches);
525 $this->counter +
= strlen($this->value
);
526 $this->line +
= substr_count($this->value
, "\n");
529 } elseif ($r === true) {
530 // we have changed state
531 // process this token in the new state
532 return $this->yylex();
533 } elseif ($r === false) {
534 $this->counter +
= strlen($this->value
);
535 $this->line +
= substr_count($this->value
, "\n");
536 if ($this->counter
>= strlen($this->data
)) {
537 return false; // end of input
543 throw new Exception('Unexpected input at line' . $this->line
.
544 ': ' . $this->data
[$this->counter
]);
552 function yy_r5_1($yy_subpatterns)
555 $this->token
= Smarty_Internal_Configfileparser
::TPC_DOT
;
558 function yy_r5_2($yy_subpatterns)
561 $this->token
= Smarty_Internal_Configfileparser
::TPC_SECTION
;
565 public function yylex6()
571 if ($this->counter
>= strlen($this->data
)) {
572 return false; // end of input
574 $yy_global_pattern = "/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/iS";
577 if (preg_match($yy_global_pattern, $this->data
, $yymatches, null, $this->counter
)) {
578 $yysubmatches = $yymatches;
579 $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
580 if (!count($yymatches)) {
581 throw new Exception('Error: lexing failed because a rule matched' .
582 ' an empty string. Input "' . substr($this->data
,
583 $this->counter
, 5) . '... state TRIPPLE');
585 next($yymatches); // skip global match
586 $this->token
= key($yymatches); // token number
587 if ($tokenMap[$this->token
]) {
588 // extract sub-patterns for passing to lex function
589 $yysubmatches = array_slice($yysubmatches, $this->token +
1,
590 $tokenMap[$this->token
]);
592 $yysubmatches = array();
594 $this->value
= current($yymatches); // token value
595 $r = $this->{'yy_r6_' . $this->token
}($yysubmatches);
597 $this->counter +
= strlen($this->value
);
598 $this->line +
= substr_count($this->value
, "\n");
601 } elseif ($r === true) {
602 // we have changed state
603 // process this token in the new state
604 return $this->yylex();
605 } elseif ($r === false) {
606 $this->counter +
= strlen($this->value
);
607 $this->line +
= substr_count($this->value
, "\n");
608 if ($this->counter
>= strlen($this->data
)) {
609 return false; // end of input
615 throw new Exception('Unexpected input at line' . $this->line
.
616 ': ' . $this->data
[$this->counter
]);
624 function yy_r6_1($yy_subpatterns)
627 $this->token
= Smarty_Internal_Configfileparser
::TPC_TRIPPLE_QUOTES_END
;
629 $this->yypushstate(self
::START
);
632 function yy_r6_2($yy_subpatterns)
635 $to = strlen($this->data
);
636 preg_match("/\"\"\"[ \t\r]*[\n#;]/", $this->data
, $match, PREG_OFFSET_CAPTURE
, $this->counter
);
637 if (isset($match[0][1])) {
640 $this->compiler
->trigger_template_error("missing or misspelled literal closing tag");
642 $this->value
= substr($this->data
, $this->counter
, $to - $this->counter
);
643 $this->token
= Smarty_Internal_Configfileparser
::TPC_TRIPPLE_TEXT
;