[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/pkg/vtiger/extensions/Webservices/third-party/ -> ParserGenerator.php (source)

   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();


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1