[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 %name PHP_LexerGenerator_Parser 2 %declare_class {class PHP_LexerGenerator_Parser} 3 %include { 4 /* ?><?php {//*/ 5 /** 6 * PHP_LexerGenerator, a php 5 lexer generator. 7 * 8 * This lexer generator translates a file in a format similar to 9 * re2c ({@link http://re2c.org}) and translates it into a PHP 5-based lexer 10 * 11 * PHP version 5 12 * 13 * LICENSE: 14 * 15 * Copyright (c) 2006, Gregory Beaver <[email protected]> 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 22 * * Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * * Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in 26 * the documentation and/or other materials provided with the distribution. 27 * * Neither the name of the PHP_LexerGenerator nor the names of its 28 * contributors may be used to endorse or promote products derived 29 * from this software without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 32 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 33 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 36 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 37 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 38 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 39 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 * 43 * @category php 44 * @package PHP_LexerGenerator 45 * @author Gregory Beaver <[email protected]> 46 * @copyright 2006 Gregory Beaver 47 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License 48 * @version CVS: $Id$ 49 * @since File available since Release 0.1.0 50 */ 51 /** 52 * For regular expression validation 53 */ 54 require_once 'PHP/LexerGenerator/Regex/Lexer.php'; 55 require_once 'PHP/LexerGenerator/Regex/Parser.php'; 56 require_once 'PHP/LexerGenerator/Exception.php'; 57 /** 58 * Token parser for plex files. 59 * 60 * This parser converts tokens pulled from {@link PHP_LexerGenerator_Lexer} 61 * into abstract patterns and rules, then creates the output file 62 * @package PHP_LexerGenerator 63 * @author Gregory Beaver <[email protected]> 64 * @copyright 2006 Gregory Beaver 65 * @license http://www.php.net/license/3_01.txt PHP License 3.01 66 * @version 0.2.0 67 * @since Class available since Release 0.1.0 68 */ 69 } 70 %syntax_error { 71 echo "Syntax Error on line " . $this->lex->line . ": token '" . 72 $this->lex->value . "' while parsing rule:"; 73 foreach ($this->yystack as $entry) { 74 echo $this->tokenName($entry->major) . ' '; 75 } 76 foreach ($this->yy_get_expected_tokens($yymajor) as $token) { 77 $expect[] = self::$yyTokenName[$token]; 78 } 79 throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN 80 . '), expected one of: ' . implode(',', $expect)); 81 } 82 %include_class { 83 private $patterns; 84 private $out; 85 private $lex; 86 private $input; 87 private $counter; 88 private $token; 89 private $value; 90 private $line; 91 private $_regexLexer; 92 private $_regexParser; 93 94 public $transTable = array( 95 1 => self::PHPCODE, 96 2 => self::COMMENTSTART, 97 3 => self::COMMENTEND, 98 4 => self::QUOTE, 99 5 => self::PATTERN, 100 6 => self::CODE, 101 7 => self::SUBPATTERN, 102 8 => self::PI, 103 ); 104 105 function __construct($outfile, $lex) 106 { 107 $this->out = fopen($outfile, 'wb'); 108 if (!$this->out) { 109 throw new Exception('unable to open lexer output file "' . $outfile . '"'); 110 } 111 $this->lex = $lex; 112 $this->_regexLexer = new PHP_LexerGenerator_Regex_Lexer(''); 113 $this->_regexParser = new PHP_LexerGenerator_Regex_Parser($this->_regexLexer); 114 } 115 116 function outputRules($rules, $statename) 117 { 118 static $ruleindex = 1; 119 $patterns = array(); 120 $pattern = '/'; 121 $ruleMap = array(); 122 $tokenindex = array(); 123 $i = 0; 124 $actualindex = 1; 125 foreach ($rules as $rule) { 126 $ruleMap[$i++] = $actualindex; 127 $tokenindex[$actualindex] = $rule['subpatterns']; 128 $actualindex += $rule['subpatterns'] + 1; 129 $patterns[] = '^(' . $rule['pattern'] . ')'; 130 } 131 $tokenindex = var_export($tokenindex, true); 132 $tokenindex = explode("\n", $tokenindex); 133 // indent for prettiness 134 $tokenindex = implode("\n ", $tokenindex); 135 $pattern .= implode('|', $patterns); 136 $pattern .= '/'; 137 if (!$statename) { 138 $statename = $ruleindex; 139 } 140 fwrite($this->out, ' 141 function yylex' . $ruleindex . '() 142 { 143 $tokenMap = ' . $tokenindex . '; 144 if (' . $this->counter . ' >= strlen(' . $this->input . ')) { 145 return false; // end of input 146 } 147 '); 148 fwrite($this->out, '$yy_global_pattern = "' . 149 $pattern . '";' . "\n"); 150 fwrite($this->out, ' 151 do { 152 if (preg_match($yy_global_pattern, substr(' . $this->input . ', ' . 153 $this->counter . 154 '), $yymatches)) { 155 $yysubmatches = $yymatches; 156 $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns 157 if (!count($yymatches)) { 158 throw new Exception(\'Error: lexing failed because a rule matched\' . 159 \'an empty string. Input "\' . substr(' . $this->input . ', 160 ' . $this->counter . ', 5) . \'... state ' . $statename . '\'); 161 } 162 next($yymatches); // skip global match 163 ' . $this->token . ' = key($yymatches); // token number 164 if ($tokenMap[' . $this->token . ']) { 165 // extract sub-patterns for passing to lex function 166 $yysubmatches = array_slice($yysubmatches, ' . $this->token . ' + 1, 167 $tokenMap[' . $this->token . ']); 168 } else { 169 $yysubmatches = array(); 170 } 171 ' . $this->value . ' = current($yymatches); // token value 172 $r = $this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}($yysubmatches); 173 if ($r === null) { 174 ' . $this->counter . ' += strlen($this->value); 175 ' . $this->line . ' += substr_count("\n", ' . $this->value . '); 176 // accept this token 177 return true; 178 } elseif ($r === true) { 179 // we have changed state 180 // process this token in the new state 181 return $this->yylex(); 182 } elseif ($r === false) { 183 ' . $this->counter . ' += strlen($this->value); 184 ' . $this->line . ' += substr_count("\n", ' . $this->value . '); 185 if (' . $this->counter . ' >= strlen(' . $this->input . ')) { 186 return false; // end of input 187 } 188 // skip this token 189 continue; 190 } else {'); 191 fwrite($this->out, ' $yy_yymore_patterns = array(' . "\n"); 192 for($i = 0; count($patterns); $i++) { 193 unset($patterns[$i]); 194 fwrite($this->out, ' ' . $ruleMap[$i] . ' => "' . 195 implode('|', $patterns) . "\",\n"); 196 } 197 fwrite($this->out, ' );' . "\n"); 198 fwrite($this->out, ' 199 // yymore is needed 200 do { 201 if (!strlen($yy_yymore_patterns[' . $this->token . '])) { 202 throw new Exception(\'cannot do yymore for the last token\'); 203 } 204 if (preg_match($yy_yymore_patterns[' . $this->token . '], 205 substr(' . $this->input . ', ' . $this->counter . '), $yymatches)) { 206 $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns 207 next($yymatches); // skip global match 208 ' . $this->token . ' = key($yymatches); // token number 209 ' . $this->value . ' = current($yymatches); // token value 210 ' . $this->line . ' = substr_count("\n", ' . $this->value . '); 211 } 212 } while ($this->{\'yy_r' . $ruleindex . '_\' . ' . $this->token . '}() !== null); 213 // accept 214 ' . $this->counter . ' += strlen($this->value); 215 ' . $this->line . ' += substr_count("\n", ' . $this->value . '); 216 return true; 217 } 218 } else { 219 throw new Exception(\'Unexpected input at line\' . ' . $this->line . ' . 220 \': \' . ' . $this->input . '[' . $this->counter . ']); 221 } 222 break; 223 } while (true); 224 } // end function 225 226 '); 227 if ($statename) { 228 fwrite($this->out, ' 229 const ' . $statename . ' = ' . $ruleindex . '; 230 '); 231 } 232 foreach ($rules as $i => $rule) { 233 fwrite($this->out, ' function yy_r' . $ruleindex . '_' . $ruleMap[$i] . '($yy_subpatterns) 234 { 235 ' . $rule['code'] . 236 ' } 237 '); 238 } 239 $ruleindex++; // for next set of rules 240 } 241 242 function error($msg) 243 { 244 echo 'Error on line ' . $this->lex->line . ': ' , $msg; 245 } 246 247 function _validatePattern($pattern) 248 { 249 $this->_regexLexer->reset($pattern); 250 try { 251 while ($this->_regexLexer->yylex()) { 252 $this->_regexParser->doParse( 253 $this->_regexLexer->token, $this->_regexLexer->value); 254 } 255 $this->_regexParser->doParse(0, 0); 256 } catch (PHP_LexerGenerator_Exception $e) { 257 $this->error($e->getMessage()); 258 throw new PHP_LexerGenerator_Exception('Invalid pattern "' . $pattern . '"'); 259 } 260 return $this->_regexParser->result; 261 } 262 } 263 264 start ::= lexfile. 265 266 lexfile ::= declare rules(B). { 267 fwrite($this->out, ' 268 private $_yy_state = 1; 269 private $_yy_stack = array(); 270 271 function yylex() 272 { 273 return $this->{\'yylex\' . $this->_yy_state}(); 274 } 275 276 function yypushstate($state) 277 { 278 array_push($this->_yy_stack, $this->_yy_state); 279 $this->_yy_state = $state; 280 } 281 282 function yypopstate() 283 { 284 $this->_yy_state = array_pop($this->_yy_stack); 285 } 286 287 function yybegin($state) 288 { 289 $this->_yy_state = $state; 290 } 291 292 '); 293 foreach (B as $rule) { 294 $this->outputRules($rule['rules'], $rule['statename']); 295 if ($rule['code']) { 296 fwrite($this->out, $rule['code']); 297 } 298 } 299 } 300 lexfile ::= declare(D) PHPCODE(B) rules(C). { 301 fwrite($this->out, ' 302 private $_yy_state = 1; 303 private $_yy_stack = array(); 304 305 function yylex() 306 { 307 return $this->{\'yylex\' . $this->_yy_state}(); 308 } 309 310 function yypushstate($state) 311 { 312 array_push($this->_yy_stack, $this->_yy_state); 313 $this->_yy_state = $state; 314 } 315 316 function yypopstate() 317 { 318 $this->_yy_state = array_pop($this->_yy_stack); 319 } 320 321 function yybegin($state) 322 { 323 $this->_yy_state = $state; 324 } 325 326 '); 327 if (strlen(B)) { 328 fwrite($this->out, B); 329 } 330 foreach (C as $rule) { 331 $this->outputRules($rule['rules'], $rule['statename']); 332 if ($rule['code']) { 333 fwrite($this->out, $rule['code']); 334 } 335 } 336 } 337 lexfile ::= PHPCODE(B) declare(D) rules(C). { 338 if (strlen(B)) { 339 fwrite($this->out, B); 340 } 341 fwrite($this->out, ' 342 private $_yy_state = 1; 343 private $_yy_stack = array(); 344 345 function yylex() 346 { 347 return $this->{\'yylex\' . $this->_yy_state}(); 348 } 349 350 function yypushstate($state) 351 { 352 array_push($this->_yy_stack, $this->_yy_state); 353 $this->_yy_state = $state; 354 } 355 356 function yypopstate() 357 { 358 $this->_yy_state = array_pop($this->_yy_stack); 359 } 360 361 function yybegin($state) 362 { 363 $this->_yy_state = $state; 364 } 365 366 '); 367 foreach (C as $rule) { 368 $this->outputRules($rule['rules'], $rule['statename']); 369 if ($rule['code']) { 370 fwrite($this->out, $rule['code']); 371 } 372 } 373 } 374 lexfile ::= PHPCODE(A) declare(D) PHPCODE(B) rules(C). { 375 if (strlen(A)) { 376 fwrite($this->out, A); 377 } 378 fwrite($this->out, ' 379 private $_yy_state = 1; 380 private $_yy_stack = array(); 381 382 function yylex() 383 { 384 return $this->{\'yylex\' . $this->_yy_state}(); 385 } 386 387 function yypushstate($state) 388 { 389 array_push($this->_yy_stack, $this->_yy_state); 390 $this->_yy_state = $state; 391 } 392 393 function yypopstate() 394 { 395 $this->_yy_state = array_pop($this->_yy_stack); 396 } 397 398 function yybegin($state) 399 { 400 $this->_yy_state = $state; 401 } 402 403 '); 404 if (strlen(B)) { 405 fwrite($this->out, B); 406 } 407 foreach (C as $rule) { 408 $this->outputRules($rule['rules'], $rule['statename']); 409 if ($rule['code']) { 410 fwrite($this->out, $rule['code']); 411 } 412 } 413 } 414 415 declare(A) ::= COMMENTSTART declarations(B) COMMENTEND. { 416 A = B; 417 $this->patterns = B['patterns']; 418 } 419 420 declarations(A) ::= processing_instructions(B) pattern_declarations(C). { 421 $expected = array( 422 'counter' => true, 423 'input' => true, 424 'token' => true, 425 'value' => true, 426 'line' => true, 427 ); 428 foreach (B as $pi) { 429 if (isset($expected[$pi['pi']])) { 430 unset($expected[$pi['pi']]); 431 continue; 432 } 433 if (count($expected)) { 434 throw new Exception('Processing Instructions "' . 435 implode(', ', array_keys($expected)) . '" must be defined'); 436 } 437 } 438 $expected = array( 439 'counter' => true, 440 'input' => true, 441 'token' => true, 442 'value' => true, 443 'line' => true, 444 ); 445 foreach (B as $pi) { 446 if (isset($expected[$pi['pi']])) { 447 $this->{$pi['pi']} = $pi['definition']; 448 continue; 449 } 450 $this->error('Unknown processing instruction %' . $pi['pi'] . 451 ', should be one of "' . implode(', ', array_keys($expected)) . '"'); 452 } 453 A = array('patterns' => C, 'pis' => B); 454 } 455 456 processing_instructions(A) ::= PI(B) SUBPATTERN(C). { 457 A = array(array('pi' => B, 'definition' => C)); 458 } 459 processing_instructions(A) ::= PI(B) CODE(C). { 460 A = array(array('pi' => B, 'definition' => C)); 461 } 462 processing_instructions(A) ::= processing_instructions(P) PI(B) SUBPATTERN(C). { 463 A = P; 464 A[] = array('pi' => B, 'definition' => C); 465 } 466 processing_instructions(A) ::= processing_instructions(P) PI(B) CODE(C). { 467 A = P; 468 A[] = array('pi' => B, 'definition' => C); 469 } 470 471 pattern_declarations(A) ::= PATTERN(B) subpattern(C). { 472 A = array(B => C); 473 } 474 pattern_declarations(A) ::= pattern_declarations(B) PATTERN(C) subpattern(D). { 475 A = B; 476 if (isset(A[C])) { 477 throw new Exception('Pattern "' . C . '" is already defined as "' . 478 A[C] . '", cannot redefine as "' . D->string . '"'); 479 } 480 A[C] = D; 481 } 482 483 rules(A) ::= COMMENTSTART rule(B) COMMENTEND. { 484 A = array(array('rules' => B, 'code' => '', 'statename' => '')); 485 } 486 rules(A) ::= COMMENTSTART PI(P) SUBPATTERN(S) rule(B) COMMENTEND. { 487 if (P != 'statename') { 488 throw new Exception('Error: only %statename processing instruction ' . 489 'is allowed in rule sections'); 490 } 491 A = array(array('rules' => B, 'code' => '', 'statename' => S)); 492 } 493 rules(A) ::= COMMENTSTART rule(B) COMMENTEND PHPCODE(C). { 494 A = array(array('rules' => B, 'code' => C, 'statename' => '')); 495 } 496 rules(A) ::= COMMENTSTART PI(P) SUBPATTERN(S) rule(B) COMMENTEND PHPCODE(C). { 497 if (P != 'statename') { 498 throw new Exception('Error: only %statename processing instruction ' . 499 'is allowed in rule sections'); 500 } 501 A = array(array('rules' => B, 'code' => C, 'statename' => S)); 502 } 503 rules(A) ::= rules(R) COMMENTSTART rule(B) COMMENTEND. { 504 A = R; 505 A[] = array('rules' => B, 'code' => '', 'statename' => ''); 506 } 507 rules(A) ::= rules(R) PI(P) SUBPATTERN(S) COMMENTSTART rule(B) COMMENTEND. { 508 if (P != 'statename') { 509 throw new Exception('Error: only %statename processing instruction ' . 510 'is allowed in rule sections'); 511 } 512 A = R; 513 A[] = array('rules' => B, 'code' => '', 'statename' => S); 514 } 515 rules(A) ::= rules(R) COMMENTSTART rule(B) COMMENTEND PHPCODE(C). { 516 A = R; 517 A[] = array('rules' => B, 'code' => C, 'statename' => ''); 518 } 519 rules(A) ::= rules(R) COMMENTSTART PI(P) SUBPATTERN(S) rule(B) COMMENTEND PHPCODE(C). { 520 if (P != 'statename') { 521 throw new Exception('Error: only %statename processing instruction ' . 522 'is allowed in rule sections'); 523 } 524 A = R; 525 A[] = array('rules' => B, 'code' => C, 'statename' => S); 526 } 527 528 rule(A) ::= rule_subpattern(B) CODE(C). { 529 if (@preg_match('/' . B[0] . '/', '')) { 530 $this->error('Rule "' . B[2] . '" can match the empty string, this will break lexing'); 531 } 532 A = array(array('pattern' => B[1], 'code' => C, 'subpatterns' => B[3])); 533 } 534 rule(A) ::= rule(R) rule_subpattern(B) CODE(C).{ 535 A = R; 536 if (@preg_match('/' . B[0] . '/', '')) { 537 $this->error('Rule "' . B[2] . '" can match the empty string, this will break lexing'); 538 } 539 A[] = array('pattern' => B[1], 'code' => C, 'subpatterns' => B[3]); 540 } 541 542 rule_subpattern(A) ::= QUOTE(B). { 543 A = array( 544 preg_quote(B, '/'), 545 str_replace(array('\\', '"'), array('\\\\', '\\"'), preg_quote(B, '/')), 546 '"' . str_replace('"', '\"', B) . '"', 0); 547 } 548 rule_subpattern(A) ::= SUBPATTERN(B). { 549 if (!isset($this->patterns[B])) { 550 $this->error('Undefined pattern "' . B . '" used in rules'); 551 throw new Exception('Undefined pattern "' . B . '" used in rules'); 552 } 553 A = array($this->patterns[B]['pattern'], $this->patterns[B]->string, B, $this->patterns[B]['subpatterns']); 554 } 555 rule_subpattern(A) ::= rule_subpattern(B) QUOTE(C). { 556 A = array( 557 B[0] . preg_quote(C, '/'), 558 B[1] . str_replace(array('\\', '"'), array('\\\\', '\\"'), preg_quote(C, '/')), 559 B[2] . ' "' . str_replace('"', '\"', C) . '"', B[3]); 560 } 561 rule_subpattern(A) ::= rule_subpattern(B) SUBPATTERN(C). { 562 if (!isset($this->patterns[C])) { 563 $this->error('Undefined pattern "' . C . '" used in rules'); 564 throw new Exception('Undefined pattern "' . C . '" used in rules'); 565 } 566 A = array(B[0] . $this->patterns[C]['pattern'], B[1] . $this->patterns[C]->string, 567 B[2] . ' ' . C, B[3] + $this->patterns[C]['subpatterns']); 568 } 569 570 subpattern(A) ::= QUOTE(B). { 571 A = new PHP_LexerGenerator_ParseryyToken(str_replace(array('\\', '"'), array('\\\\', '\\"'), preg_quote(B, '/')), array( 572 'pattern' => preg_quote(B, '/'), 'subpatterns' => 0)); 573 } 574 subpattern(A) ::= SUBPATTERN(B). { 575 A = $this->_validatePattern(B); 576 } 577 subpattern(A) ::= subpattern(B) QUOTE(C). { 578 A = new PHP_LexerGenerator_ParseryyToken(B->string . str_replace(array('\\', '"'), array('\\\\', '\\"'), preg_quote(C, '/')), array( 579 'pattern' => B['pattern'] . preg_quote(C, '/'), 'subpatterns' => B['subpatterns'])); 580 } 581 subpattern(A) ::= subpattern(B) SUBPATTERN(C). { 582 $x = $this->_validatePattern(C); 583 A = new PHP_LexerGenerator_ParseryyToken(B->string . $x->string, array( 584 'pattern' => B['pattern'] . $x['pattern'], 585 'subpatterns' => $x['subpatterns'] + B['subpatterns'])); 586 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |