[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * PHP_ParserGenerator, a php 5 parser generator. 4 * 5 * This is a direct port of the Lemon parser generator, found at 6 * {@link http://www.hwaci.com/sw/lemon/} 7 * 8 * There are a few PHP-specific changes to the lemon parser generator. 9 * 10 * - %extra_argument is removed, as class constructor can be used to 11 * pass in extra information 12 * - %token_type and company are irrelevant in PHP, and so are removed 13 * - %declare_class is added to define the parser class name and any 14 * implements/extends information 15 * - %include_class is added to allow insertion of extra class information 16 * such as constants, a class constructor, etc. 17 * 18 * Other changes make the parser more robust, and also make reporting 19 * syntax errors simpler. Detection of expected tokens eliminates some 20 * problematic edge cases where an unexpected token could cause the parser 21 * to simply accept input. 22 * 23 * Otherwise, the file format is identical to the Lemon parser generator 24 * 25 * PHP version 5 26 * 27 * LICENSE: This source file is subject to version 3.01 of the PHP license 28 * that is available through the world-wide-web at the following URI: 29 * http://www.php.net/license/3_01.txt. If you did not receive a copy of 30 * the PHP License and are unable to obtain it through the web, please 31 * send a note to [email protected] so we can mail you a copy immediately. 32 * 33 * @category php 34 * @package PHP_ParserGenerator 35 * @author Gregory Beaver <[email protected]> 36 * @copyright 2006 Gregory Beaver 37 * @license http://www.php.net/license/3_01.txt PHP License 3.01 38 * @version CVS: $Id$ 39 * @since File available since Release 0.1.0 40 */ 41 /**#@+ 42 * Basic components of the parser generator 43 */ 44 require_once 'PHP/ParserGenerator/Action.php'; 45 require_once 'PHP/ParserGenerator/ActionTable.php'; 46 require_once 'PHP/ParserGenerator/Config.php'; 47 require_once 'PHP/ParserGenerator/Data.php'; 48 require_once 'PHP/ParserGenerator/Symbol.php'; 49 require_once 'PHP/ParserGenerator/Rule.php'; 50 require_once 'PHP/ParserGenerator/Parser.php'; 51 require_once 'PHP/ParserGenerator/PropagationLink.php'; 52 require_once 'PHP/ParserGenerator/State.php'; 53 /**#@-*/ 54 /** 55 * The basic home class for the parser generator 56 * 57 * @package PHP_ParserGenerator 58 * @author Gregory Beaver <[email protected]> 59 * @copyright 2006 Gregory Beaver 60 * @license http://www.php.net/license/3_01.txt PHP License 3.01 61 * @version 0.1.0 62 * @since Class available since Release 0.1.0 63 * @example Lempar.php 64 * @example examples/Parser.y Sample parser file format (PHP_LexerGenerator's parser) 65 * @example examples/Parser.php Sample parser file format PHP code (PHP_LexerGenerator's parser) 66 */ 67 class PHP_ParserGenerator 68 { 69 /** 70 * Set this to 1 to turn on debugging of Lemon's parsing of 71 * grammar files. 72 */ 73 const DEBUG = 0; 74 const MAXRHS = 1000; 75 const OPT_FLAG = 1, OPT_INT = 2, OPT_DBL = 3, OPT_STR = 4, 76 OPT_FFLAG = 5, OPT_FINT = 6, OPT_FDBL = 7, OPT_FSTR = 8; 77 public $azDefine = array(); 78 private static $options = array( 79 'b' => array( 80 'type' => self::OPT_FLAG, 81 'arg' => 'basisflag', 82 'message' => 'Print only the basis in report.' 83 ), 84 'c' => array( 85 'type' => self::OPT_FLAG, 86 'arg' => 'compress', 87 'message' => 'Don\'t compress the action table.' 88 ), 89 'D' => array( 90 'type' => self::OPT_FSTR, 91 'arg' => 'handle_D_option', 92 'message' => 'Define an %ifdef macro.' 93 ), 94 'g' => array( 95 'type' => self::OPT_FLAG, 96 'arg' => 'rpflag', 97 'message' => 'Print grammar without actions.' 98 ), 99 'm' => array( 100 'type' => self::OPT_FLAG, 101 'arg' => 'mhflag', 102 'message' => 'Output a makeheaders compatible file' 103 ), 104 'q' => array( 105 'type' => self::OPT_FLAG, 106 'arg' => 'quiet', 107 'message' => '(Quiet) Don\'t print the report file.' 108 ), 109 's' => array( 110 'type' => self::OPT_FLAG, 111 'arg' => 'statistics', 112 'message' => 'Print parser stats to standard output.' 113 ), 114 'x' => array( 115 'type' => self::OPT_FLAG, 116 'arg' => 'version', 117 'message' => 'Print the version number.' 118 ) 119 ); 120 121 private $basisflag = 0; 122 private $compress = 0; 123 private $rpflag = 0; 124 private $mhflag = 0; 125 private $quiet = 0; 126 private $statistics = 0; 127 private $version = 0; 128 private $size; 129 /** 130 * Process a flag command line argument. 131 * @param int 132 * @param array 133 * @return int 134 */ 135 function handleflags($i, $argv) 136 { 137 if (!isset($argv[1]) || !isset(self::$options[$argv[$i][1]])) { 138 throw new Exception('Command line syntax error: undefined option "' . $argv[$i] . '"'); 139 } 140 $v = self::$options[$argv[$i][1]] == '-'; 141 if (self::$options[$argv[$i][1]]['type'] == self::OPT_FLAG) { 142 $this->{self::$options[$argv[$i][1]]['arg']} = (int) $v; 143 } elseif (self::$options[$argv[$i][1]]['type'] == self::OPT_FFLAG) { 144 $this->{self::$options[$argv[$i][1]]['arg']}($v); 145 } elseif (self::$options[$argv[$i][1]]['type'] == self::OPT_FSTR) { 146 $this->{self::$options[$argv[$i][1]]['arg']}(substr($v, 2)); 147 } else { 148 throw new Exception('Command line syntax error: missing argument on switch: "' . $argv[$i] . '"'); 149 } 150 return 0; 151 } 152 153 /** 154 * Process a command line switch which has an argument. 155 * @param int 156 * @param array 157 * @param array 158 * @return int 159 */ 160 function handleswitch($i, $argv) 161 { 162 $lv = 0; 163 $dv = 0.0; 164 $sv = $end = $cp = ''; 165 $j; // int 166 $errcnt = 0; 167 $cp = strstr($argv[$i],'='); 168 if (!$cp) { 169 throw new Exception('INTERNAL ERROR: handleswitch passed bad argument, no "=" in arg'); 170 } 171 $argv[$i] = substr($argv[$i], 0, strlen($argv[$i]) - strlen($cp)); 172 if (!isset(self::$options[$argv[$i]])) { 173 throw new Exception('Command line syntax error: undefined option "' . $argv[$i] . 174 $cp . '"'); 175 } 176 $cp = substr($cp, 1); 177 switch (self::$options[$argv[$i]]['type']) { 178 case self::OPT_FLAG: 179 case self::OPT_FFLAG: 180 throw new Exception('Command line syntax error: option requires an argument "' . 181 $argv[$i] . '=' . $cp . '"'); 182 case self::OPT_DBL: 183 case self::OPT_FDBL: 184 $dv = (double) $cp; 185 break; 186 case self::OPT_INT: 187 case self::OPT_FINT: 188 $lv = (int) $cp; 189 break; 190 case self::OPT_STR: 191 case self::OPT_FSTR: 192 $sv = $cp; 193 break; 194 } 195 switch(self::$options[$argv[$i]]['type']) { 196 case self::OPT_FLAG: 197 case self::OPT_FFLAG: 198 break; 199 case self::OPT_DBL: 200 $this->$self::$options[$argv[$i]]['arg']} = $dv; 201 break; 202 case self::OPT_FDBL: 203 $this->$self::$options[$argv[$i]]['arg']}($dv); 204 break; 205 case self::OPT_INT: 206 $this->$self::$options[$argv[$i]]['arg']} = $lv; 207 break; 208 case self::OPT_FINT: 209 $this->$self::$options[$argv[$i]]['arg']}($lv); 210 break; 211 case self::OPT_STR: 212 $this->$self::$options[$argv[$i]]['arg']} = $sv; 213 break; 214 case self::OPT_FSTR: 215 $this->$self::$options[$argv[$i]]['arg']}($sv); 216 break; 217 } 218 return 0; 219 } 220 221 /** 222 * @param array arguments 223 * @param array valid options 224 * @return int 225 */ 226 function OptInit($a) 227 { 228 $errcnt = 0; 229 $argv = $a; 230 try { 231 if (is_array($argv) && count($argv) && self::$options) { 232 for($i = 1; $i < count($argv); $i++) { 233 if ($argv[$i][0] == '+' || $argv[$i][0] == '-') { 234 $errcnt += $this->handleflags($i, $argv); 235 } elseif (strstr($argv[$i],'=')) { 236 $errcnt += $this->handleswitch(i, $argv); 237 } 238 } 239 } 240 } catch (Exception $e) { 241 OptPrint(); 242 echo $e; 243 exit(1); 244 } 245 return 0; 246 } 247 248 /** 249 * Return the index of the N-th non-switch argument. Return -1 250 * if N is out of range. 251 * @param int 252 * @return int 253 */ 254 private function argindex($n, $a) 255 { 256 $dashdash = 0; 257 if (!is_array($a) || !count($a)) { 258 return -1; 259 } 260 for ($i=1; $i < count($a); $i++) { 261 if ($dashdash || !($a[$i][0] == '-' || $a[$i][0] == '+' || 262 strchr($a[$i], '='))) { 263 if ($n == 0) { 264 return $i; 265 } 266 $n--; 267 } 268 if ($_SERVER['argv'][$i] == '--') { 269 $dashdash = 1; 270 } 271 } 272 return -1; 273 } 274 275 /** 276 * Return the value of the non-option argument as indexed by $i 277 * 278 * @param int 279 * @param array the value of $argv 280 * @return 0|string 281 */ 282 private function OptArg($i, $a) 283 { 284 if (-1 == ($ind = $this->argindex($i, $a))) { 285 return 0; 286 } 287 return $a[$ind]; 288 } 289 290 /** 291 * @return int number of arguments 292 */ 293 function OptNArgs($a) 294 { 295 $cnt = $dashdash = 0; 296 if (is_array($a) && count($a)) { 297 for($i = 1; $i < count($a); $i++) { 298 if ($dashdash || !($a[$i][0] == '-' || $a[$i][0] == '+' || 299 strchr($a[$i], '='))) { 300 $cnt++; 301 } 302 if ($a[$i] == "--") { 303 $dashdash = 1; 304 } 305 } 306 } 307 return $cnt; 308 } 309 310 /** 311 * Print out command-line options 312 */ 313 function OptPrint() 314 { 315 $max = 0; 316 foreach (self::$options as $label => $info) { 317 $len = strlen($label) + 1; 318 switch ($info['type']) { 319 case self::OPT_FLAG: 320 case self::OPT_FFLAG: 321 break; 322 case self::OPT_INT: 323 case self::OPT_FINT: 324 $len += 9; /* length of "<integer>" */ 325 break; 326 case self::OPT_DBL: 327 case self::OPT_FDBL: 328 $len += 6; /* length of "<real>" */ 329 break; 330 case self::OPT_STR: 331 case self::OPT_FSTR: 332 $len += 8; /* length of "<string>" */ 333 break; 334 } 335 if ($len > $max) { 336 $max = $len; 337 } 338 } 339 foreach (self::$options as $label => $info) { 340 switch ($info['type']) { 341 case self::OPT_FLAG: 342 case self::OPT_FFLAG: 343 printf(" -%-*s %s\n", $max, $label, $info['message']); 344 break; 345 case self::OPT_INT: 346 case self::OPT_FINT: 347 printf(" %s=<integer>%*s %s\n", $label, $max - strlen($label) - 9, 348 $info['message']); 349 break; 350 case self::OPT_DBL: 351 case self::OPT_FDBL: 352 printf(" %s=<real>%*s %s\n", $label, $max - strlen($label) - 6, 353 $info['message']); 354 break; 355 case self::OPT_STR: 356 case self::OPT_FSTR: 357 printf(" %s=<string>%*s %s\n", $label, $max - strlen($label) - 8, 358 $info['message']); 359 break; 360 } 361 } 362 } 363 364 /** 365 * This routine is called with the argument to each -D command-line option. 366 * Add the macro defined to the azDefine array. 367 * @param string 368 */ 369 private function handle_D_option($z) 370 { 371 if ($a = strstr($z, '=')) { 372 $z = substr($a, 1); // strip first = 373 } 374 $this->azDefine[] = $z; 375 } 376 377 /**************** From the file "main.c" ************************************/ 378 /* 379 ** Main program file for the LEMON parser generator. 380 */ 381 382 383 /* The main program. Parse the command line and do it... */ 384 function main() 385 { 386 $lem = new PHP_ParserGenerator_Data; 387 388 $this->OptInit($_SERVER['argv']); 389 if ($this->version) { 390 echo "Lemon version 1.0/PHP_ParserGenerator port version 0.1.0\n"; 391 exit(0); 392 } 393 if ($this->OptNArgs($_SERVER['argv']) != 1) { 394 echo "Exactly one filename argument is required.\n"; 395 exit(1); 396 } 397 $lem->errorcnt = 0; 398 399 /* Initialize the machine */ 400 $lem->argv0 = $_SERVER['argv'][0]; 401 $lem->filename = $this->OptArg(0, $_SERVER['argv']); 402 $a = pathinfo($lem->filename); 403 if (isset($a['extension'])) { 404 $ext = '.' . $a['extension']; 405 $lem->filenosuffix = substr($lem->filename, 0, strlen($lem->filename) - strlen($ext)); 406 } else { 407 $lem->filenosuffix = $lem->filename; 408 } 409 $lem->basisflag = $this->basisflag; 410 $lem->has_fallback = 0; 411 $lem->nconflict = 0; 412 $lem->name = $lem->include_code = $lem->include_classcode = $lem->arg = 413 $lem->tokentype = $lem->start = 0; 414 $lem->vartype = 0; 415 $lem->stacksize = 0; 416 $lem->error = $lem->overflow = $lem->failure = $lem->accept = $lem->tokendest = 417 $lem->tokenprefix = $lem->outname = $lem->extracode = 0; 418 $lem->vardest = 0; 419 $lem->tablesize = 0; 420 PHP_ParserGenerator_Symbol::Symbol_new("$"); 421 $lem->errsym = PHP_ParserGenerator_Symbol::Symbol_new("error"); 422 423 /* Parse the input file */ 424 $parser = new PHP_ParserGenerator_Parser($this); 425 $parser->Parse($lem); 426 if ($lem->errorcnt) { 427 exit($lem->errorcnt); 428 } 429 if ($lem->rule === 0) { 430 printf("Empty grammar.\n"); 431 exit(1); 432 } 433 434 /* Count and index the symbols of the grammar */ 435 $lem->nsymbol = PHP_ParserGenerator_Symbol::Symbol_count(); 436 PHP_ParserGenerator_Symbol::Symbol_new("{default}"); 437 $lem->symbols = PHP_ParserGenerator_Symbol::Symbol_arrayof(); 438 for ($i = 0; $i <= $lem->nsymbol; $i++) { 439 $lem->symbols[$i]->index = $i; 440 } 441 usort($lem->symbols, array('PHP_ParserGenerator_Symbol', 'sortSymbols')); 442 for ($i = 0; $i <= $lem->nsymbol; $i++) { 443 $lem->symbols[$i]->index = $i; 444 } 445 // find the first lower-case symbol 446 for($i = 1; ord($lem->symbols[$i]->name[0]) < ord ('Z'); $i++); 447 $lem->nterminal = $i; 448 449 /* Generate a reprint of the grammar, if requested on the command line */ 450 if ($this->rpflag) { 451 $this->Reprint(); 452 } else { 453 /* Initialize the size for all follow and first sets */ 454 $this->SetSize($lem->nterminal); 455 456 /* Find the precedence for every production rule (that has one) */ 457 $lem->FindRulePrecedences(); 458 459 /* Compute the lambda-nonterminals and the first-sets for every 460 ** nonterminal */ 461 $lem->FindFirstSets(); 462 463 /* Compute all LR(0) states. Also record follow-set propagation 464 ** links so that the follow-set can be computed later */ 465 $lem->nstate = 0; 466 $lem->FindStates(); 467 $lem->sorted = PHP_ParserGenerator_State::State_arrayof(); 468 469 /* Tie up loose ends on the propagation links */ 470 $lem->FindLinks(); 471 472 /* Compute the follow set of every reducible configuration */ 473 $lem->FindFollowSets(); 474 475 /* Compute the action tables */ 476 $lem->FindActions(); 477 478 /* Compress the action tables */ 479 if ($this->compress===0) { 480 $lem->CompressTables(); 481 } 482 483 /* Reorder and renumber the states so that states with fewer choices 484 ** occur at the end. */ 485 $lem->ResortStates(); 486 487 /* Generate a report of the parser generated. (the "y.output" file) */ 488 if (!$this->quiet) { 489 $lem->ReportOutput(); 490 } 491 492 /* Generate the source code for the parser */ 493 $lem->ReportTable($this->mhflag); 494 495 /* Produce a header file for use by the scanner. (This step is 496 ** omitted if the "-m" option is used because makeheaders will 497 ** generate the file for us.) */ 498 // if (!$this->mhflag) { 499 // $this->ReportHeader(); 500 // } 501 } 502 if ($this->statistics) { 503 printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n", 504 $lem->nterminal, $lem->nsymbol - $lem->nterminal, $lem->nrule); 505 printf(" %d states, %d parser table entries, %d conflicts\n", 506 $lem->nstate, $lem->tablesize, $lem->nconflict); 507 } 508 if ($lem->nconflict) { 509 printf("%d parsing conflicts.\n", $lem->nconflict); 510 } 511 exit($lem->errorcnt + $lem->nconflict); 512 return ($lem->errorcnt + $lem->nconflict); 513 } 514 515 function SetSize($n) 516 { 517 $this->size = $n + 1; 518 } 519 520 /** 521 * Merge in a merge sort for a linked list 522 * Inputs: 523 * - a: A sorted, null-terminated linked list. (May be null). 524 * - b: A sorted, null-terminated linked list. (May be null). 525 * - cmp: A pointer to the comparison function. 526 * - offset: Offset in the structure to the "next" field. 527 * 528 * Return Value: 529 * A pointer to the head of a sorted list containing the elements 530 * of both a and b. 531 * 532 * Side effects: 533 * The "next" pointers for elements in the lists a and b are 534 * changed. 535 */ 536 static function merge($a, $b, $cmp, $offset) 537 { 538 if($a === 0) { 539 $head = $b; 540 } elseif ($b === 0) { 541 $head = $a; 542 } else { 543 if (call_user_func($cmp, $a, $b) < 0) { 544 $ptr = $a; 545 $a = $a->$offset; 546 } else { 547 $ptr = $b; 548 $b = $b->$offset; 549 } 550 $head = $ptr; 551 while ($a && $b) { 552 if (call_user_func($cmp, $a, $b) < 0) { 553 $ptr->$offset = $a; 554 $ptr = $a; 555 $a = $a->$offset; 556 } else { 557 $ptr->$offset = $b; 558 $ptr = $b; 559 $b = $b->$offset; 560 } 561 } 562 if ($a !== 0) { 563 $ptr->$offset = $a; 564 } else { 565 $ptr->$offset = $b; 566 } 567 } 568 return $head; 569 } 570 571 /* 572 ** Inputs: 573 ** list: Pointer to a singly-linked list of structures. 574 ** next: Pointer to pointer to the second element of the list. 575 ** cmp: A comparison function. 576 ** 577 ** Return Value: 578 ** A pointer to the head of a sorted list containing the elements 579 ** orginally in list. 580 ** 581 ** Side effects: 582 ** The "next" pointers for elements in list are changed. 583 */ 584 #define LISTSIZE 30 585 static function msort($list, $next, $cmp) 586 { 587 if ($list === 0) { 588 return $list; 589 } 590 if ($list->$next === 0) { 591 return $list; 592 } 593 $set = array_fill(0, 30, 0); 594 while ($list) { 595 $ep = $list; 596 $list = $list->$next; 597 $ep->$next = 0; 598 for ($i = 0; $i < 29 && $set[$i] !== 0; $i++) { 599 $ep = self::merge($ep, $set[$i], $cmp, $next); 600 $set[$i] = 0; 601 } 602 $set[$i] = $ep; 603 } 604 $ep = 0; 605 for ($i = 0; $i < 30; $i++) { 606 if ($set[$i] !== 0) { 607 $ep = self::merge($ep, $set[$i], $cmp, $next); 608 } 609 } 610 return $ep; 611 } 612 613 /* Find a good place to break "msg" so that its length is at least "min" 614 ** but no more than "max". Make the point as close to max as possible. 615 */ 616 static function findbreak($msg, $min, $max) 617 { 618 if ($min >= strlen($msg)) { 619 return strlen($msg); 620 } 621 for ($i = $spot = $min; $i <= $max && $i < strlen($msg); $i++) { 622 $c = $msg[$i]; 623 if ($c == '-' && $i < $max - 1) { 624 $spot = $i + 1; 625 } 626 if ($c == ' ') { 627 $spot = $i; 628 } 629 } 630 return $spot; 631 } 632 633 static function ErrorMsg($filename, $lineno, $format) 634 { 635 /* Prepare a prefix to be prepended to every output line */ 636 if ($lineno > 0) { 637 $prefix = sprintf("%20s:%d: ", $filename, $lineno); 638 } else { 639 $prefix = sprintf("%20s: ", $filename); 640 } 641 $prefixsize = strlen($prefix); 642 $availablewidth = 79 - $prefixsize; 643 644 /* Generate the error message */ 645 $ap = func_get_args(); 646 array_shift($ap); // $filename 647 array_shift($ap); // $lineno 648 array_shift($ap); // $format 649 $errmsg = vsprintf($format, $ap); 650 $linewidth = strlen($errmsg); 651 /* Remove trailing "\n"s from the error message. */ 652 while ($linewidth > 0 && in_array($errmsg[$linewidth-1], array("\n", "\r"), true)) { 653 --$linewidth; 654 $errmsg = substr($errmsg, 0, strlen($errmsg) - 1); 655 } 656 657 /* Print the error message */ 658 $base = 0; 659 $errmsg = str_replace(array("\r", "\n", "\t"), array(' ', ' ', ' '), $errmsg); 660 while (strlen($errmsg)) { 661 $end = $restart = self::findbreak($errmsg, 0, $availablewidth); 662 if (strlen($errmsg) <= 79 && $end < strlen($errmsg) && $end <= 79) { 663 $end = $restart = strlen($errmsg); 664 } 665 while (isset($errmsg[$restart]) && $errmsg[$restart] == ' ') { 666 $restart++; 667 } 668 printf("%s%.$end}s\n", $prefix, $errmsg); 669 $errmsg = substr($errmsg, $restart); 670 } 671 } 672 673 /** 674 * Duplicate the input file without comments and without actions 675 * on rules 676 */ 677 function Reprint() 678 { 679 printf("// Reprint of input file \"%s\".\n// Symbols:\n", $this->filename); 680 $maxlen = 10; 681 for ($i = 0; $i < $this->nsymbol; $i++) { 682 $sp = $this->symbols[$i]; 683 $len = strlen($sp->name); 684 if ($len > $maxlen ) { 685 $maxlen = $len; 686 } 687 } 688 $ncolumns = 76 / ($maxlen + 5); 689 if ($ncolumns < 1) { 690 $ncolumns = 1; 691 } 692 $skip = ($this->nsymbol + $ncolumns - 1) / $ncolumns; 693 for ($i = 0; $i < $skip; $i++) { 694 print "//"; 695 for ($j = $i; $j < $this->nsymbol; $j += $skip) { 696 $sp = $this->symbols[$j]; 697 //assert( sp->index==j ); 698 printf(" %3d %-$maxlen}.$maxlen}s", $j, $sp->name); 699 } 700 print "\n"; 701 } 702 for ($rp = $this->rule; $rp; $rp = $rp->next) { 703 printf("%s", $rp->lhs->name); 704 /* if ($rp->lhsalias) { 705 printf("(%s)", $rp->lhsalias); 706 }*/ 707 print " ::="; 708 for ($i = 0; $i < $rp->nrhs; $i++) { 709 $sp = $rp->rhs[$i]; 710 printf(" %s", $sp->name); 711 if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) { 712 for ($j = 1; $j < $sp->nsubsym; $j++) { 713 printf("|%s", $sp->subsym[$j]->name); 714 } 715 } 716 /* if ($rp->rhsalias[$i]) { 717 printf("(%s)", $rp->rhsalias[$i]); 718 }*/ 719 } 720 print "."; 721 if ($rp->precsym) { 722 printf(" [%s]", $rp->precsym->name); 723 } 724 /* if ($rp->code) { 725 print "\n " . $rp->code); 726 }*/ 727 print "\n"; 728 } 729 } 730 } 731 //$a = new PHP_ParserGenerator; 732 //$_SERVER['argv'] = array('lemon', '-s', '/development/lemon/PHP_Parser.y'); 733 //$_SERVER['argv'] = array('lemon', '-s', '/development/File_ChessPGN/ChessPGN/Parser.y'); 734 //$a->main();
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 |