PHP_LexerGenerator
[ class tree: PHP_LexerGenerator ] [ index: PHP_LexerGenerator ] [ all elements ]

Source for file Parser.php

Documentation is available at Parser.php

  1. <?php
  2. /* Driver template for the PHP_PHP_LexerGenerator_ParserrGenerator parser generator. (PHP port of LEMON)
  3. */
  4.  
  5. /**
  6.  * This can be used to store both the string representation of
  7.  * a token, and any useful meta-data associated with the token.
  8.  *
  9.  * meta-data should be stored as an array
  10.  */
  11. class PHP_LexerGenerator_ParseryyToken implements ArrayAccess
  12. {
  13.     public $string '';
  14.     public $metadata = array();
  15.  
  16.     function __construct($s$m = array())
  17.     {
  18.         if ($s instanceof PHP_LexerGenerator_ParseryyToken{
  19.             $this->string $s->string;
  20.             $this->metadata $s->metadata;
  21.         else {
  22.             $this->string = (string) $s;
  23.             if ($m instanceof PHP_LexerGenerator_ParseryyToken{
  24.                 $this->metadata $m->metadata;
  25.             elseif (is_array($m)) {
  26.                 $this->metadata $m;
  27.             }
  28.         }
  29.     }
  30.  
  31.     function __toString()
  32.     {
  33.         return $this->_string;
  34.     }
  35.  
  36.     function offsetExists($offset)
  37.     {
  38.         return isset($this->metadata[$offset]);
  39.     }
  40.  
  41.     function offsetGet($offset)
  42.     {
  43.         return $this->metadata[$offset];
  44.     }
  45.  
  46.     function offsetSet($offset$value)
  47.     {
  48.         if ($offset === null{
  49.             if (isset($value[0])) {
  50.                 $x ($value instanceof PHP_LexerGenerator_ParseryyToken?
  51.                     $value->metadata : $value;
  52.                 $this->metadata array_merge($this->metadata$x);
  53.                 return;
  54.             }
  55.             $offset count($this->metadata);
  56.         }
  57.         if ($value === null{
  58.             return;
  59.         }
  60.         if ($value instanceof PHP_LexerGenerator_ParseryyToken{
  61.             if ($value->metadata{
  62.                 $this->metadata[$offset$value->metadata;
  63.             }
  64.         elseif ($value{
  65.             $this->metadata[$offset$value;
  66.         }
  67.     }
  68.  
  69.     function offsetUnset($offset)
  70.     {
  71.         unset($this->metadata[$offset]);
  72.     }
  73. }
  74.  
  75. /** The following structure represents a single element of the
  76.  * parser's stack.  Information stored includes:
  77.  *
  78.  *   +  The state number for the parser at this level of the stack.
  79.  *
  80.  *   +  The value of the token stored at this level of the stack.
  81.  *      (In other words, the "major" token.)
  82.  *
  83.  *   +  The semantic value stored at this level of the stack.  This is
  84.  *      the information used by the action routines in the grammar.
  85.  *      It is sometimes called the "minor" token.
  86.  */
  87. class PHP_LexerGenerator_ParseryyStackEntry
  88. {
  89.     public $stateno;       /* The state-number */
  90.     public $major;         /* The major token value.  This is the code
  91.                      ** number for the token at this stack level */
  92.     public $minor/* The user-supplied minor token value.  This
  93.                      ** is the value of the token  */
  94. };
  95.  
  96. // code external to the class is included here
  97. #line 3 "Parser.y"
  98.  
  99. /* ?><?php {//*/
  100. /**
  101.  * PHP_LexerGenerator, a php 5 lexer generator.
  102.  * 
  103.  * This lexer generator translates a file in a format similar to
  104.  * re2c ({@link http://re2c.org}) and translates it into a PHP 5-based lexer
  105.  *
  106.  * PHP version 5
  107.  *
  108.  * LICENSE:
  109.  * 
  110.  * Copyright (c) 2006, Gregory Beaver <cellog@php.net>
  111.  * All rights reserved.
  112.  *
  113.  * Redistribution and use in source and binary forms, with or without
  114.  * modification, are permitted provided that the following conditions
  115.  * are met:
  116.  *
  117.  *     * Redistributions of source code must retain the above copyright
  118.  *       notice, this list of conditions and the following disclaimer.
  119.  *     * Redistributions in binary form must reproduce the above copyright
  120.  *       notice, this list of conditions and the following disclaimer in
  121.  *       the documentation and/or other materials provided with the distribution.
  122.  *     * Neither the name of the PHP_LexerGenerator nor the names of its
  123.  *       contributors may be used to endorse or promote products derived
  124.  *       from this software without specific prior written permission.
  125.  *
  126.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  127.  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  128.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  129.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  130.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  131.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  132.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  133.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  134.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  135.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  136.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  137.  *
  138.  * @category   php
  139.  * @package    PHP_LexerGenerator
  140.  * @author     Gregory Beaver <cellog@php.net>
  141.  * @copyright  2006 Gregory Beaver
  142.  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
  143.  * @version    CVS: $Id: Parser.php,v 1.2 2006/08/30 20:10:49 cellog Exp $
  144.  * @since      File available since Release 0.1.0
  145.  */
  146. /**
  147.  * For regular expression validation
  148.  */
  149. require_once 'PHP/LexerGenerator/Regex/Lexer.php';
  150. require_once 'PHP/LexerGenerator/Regex/Parser.php';
  151. require_once 'PHP/LexerGenerator/Exception.php';
  152. /**
  153.  * Token parser for plex files.
  154.  * 
  155.  * This parser converts tokens pulled from {@link PHP_LexerGenerator_Lexer}
  156.  * into abstract patterns and rules, then creates the output file
  157.  * @package    PHP_LexerGenerator
  158.  * @author     Gregory Beaver <cellog@php.net>
  159.  * @copyright  2006 Gregory Beaver
  160.  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  161.  * @version    0.2.3
  162.  * @since      Class available since Release 0.1.0
  163.  */
  164. #line 166 "Parser.php"
  165.  
  166. // declare_class is output here
  167. #line 2 "Parser.y"
  168. class PHP_LexerGenerator_Parser#line 171 "Parser.php"
  169. {
  170. /* First off, code is included which follows the "include_class" declaration
  171. ** in the input file. */
  172. #line 82 "Parser.y"
  173.  
  174.     private $patterns;
  175.     private $out;
  176.     private $lex;
  177.     private $input;
  178.     private $counter;
  179.     private $token;
  180.     private $value;
  181.     private $line;
  182.     private $_regexLexer;
  183.     private $_regexParser;
  184.     private $_patternIndex = 0;
  185.  
  186.     public $transTable = array(
  187.         1 => self::PHPCODE,
  188.         2 => self::COMMENTSTART,
  189.         3 => self::COMMENTEND,
  190.         4 => self::QUOTE,
  191.         5 => self::PATTERN,
  192.         6 => self::CODE,
  193.         7 => self::SUBPATTERN,
  194.         8 => self::PI,
  195.     );
  196.  
  197.     function __construct($outfile$lex)
  198.     {
  199.         $this->out fopen($outfile'wb');
  200.         if (!$this->out{
  201.             throw new Exception('unable to open lexer output file "' $outfile '"');
  202.         }
  203.         $this->lex $lex;
  204.         $this->_regexLexer = new PHP_LexerGenerator_Regex_Lexer('');
  205.         $this->_regexParser = new PHP_LexerGenerator_Regex_Parser($this->_regexLexer);
  206.     }
  207.  
  208.     function outputRules($rules$statename)
  209.     {
  210.         static $ruleindex = 1;
  211.         $patterns = array();
  212.         $pattern '/';
  213.         $ruleMap = array();
  214.         $tokenindex = array();
  215.         $i = 0;
  216.         $actualindex = 1;
  217.         foreach ($rules as $rule{
  218.             $ruleMap[$i++$actualindex;
  219.             $tokenindex[$actualindex$rule['subpatterns'];
  220.             $actualindex += $rule['subpatterns'+ 1;
  221.             $patterns['^(' $rule['pattern'')';
  222.         }
  223.         $tokenindex = var_export($tokenindextrue);
  224.         $tokenindex = explode("\n"$tokenindex);
  225.         // indent for prettiness
  226.         $tokenindex = implode("\n            "$tokenindex);
  227.         $pattern .= implode('|'$patterns);
  228.         $pattern .= '/';
  229.         if (!$statename{
  230.             $statename $ruleindex;
  231.         }
  232.         fwrite($this->out'
  233.     function yylex' $ruleindex '()
  234.     {
  235.         $tokenMap = ' $tokenindex ';
  236.         if (' $this->counter . ' >= strlen(' $this->input . ')) {
  237.             return false; // end of input
  238.         }
  239.         ');
  240.         fwrite($this->out'$yy_global_pattern = "' .
  241.             $pattern '";' "\n");
  242.         fwrite($this->out'
  243.         do {
  244.             if (preg_match($yy_global_pattern, substr(' $this->input . ', ' .
  245.              $this->counter .
  246.                     '), $yymatches)) {
  247.                 $yysubmatches = $yymatches;
  248.                 $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns
  249.                 if (!count($yymatches)) {
  250.                     throw new Exception(\'Error: lexing failed because a rule matched\' .
  251.                         \'an empty string.  Input "\' . substr(' $this->input . ',
  252.                         ' $this->counter . ', 5) . \'... state ' $statename '\');
  253.                 }
  254.                 next($yymatches); // skip global match
  255.                 ' $this->token . ' = key($yymatches); // token number
  256.                 if ($tokenMap[' $this->token . ']) {
  257.                     // extract sub-patterns for passing to lex function
  258.                     $yysubmatches = array_slice($yysubmatches, ' $this->token . ' + 1,
  259.                         $tokenMap[' $this->token . ']);
  260.                 } else {
  261.                     $yysubmatches = array();
  262.                 }
  263.                 ' $this->value . ' = current($yymatches); // token value
  264.                 $r = $this->{\'yy_r' $ruleindex '_\' . ' $this->token . '}($yysubmatches);
  265.                 if ($r === null) {
  266.                     ' $this->counter . ' += strlen($this->value);
  267.                     ' $this->line . ' += substr_count("\n", ' $this->value . ');
  268.                     // accept this token
  269.                     return true;
  270.                 } elseif ($r === true) {
  271.                     // we have changed state
  272.                     // process this token in the new state
  273.                     return $this->yylex();
  274.                 } elseif ($r === false) {
  275.                     ' $this->counter . ' += strlen($this->value);
  276.                     ' $this->line . ' += substr_count("\n", ' $this->value . ');
  277.                     if (' $this->counter . ' >= strlen(' $this->input . ')) {
  278.                         return false; // end of input
  279.                     }
  280.                     // skip this token
  281.                     continue;
  282.                 } else {');
  283.         fwrite($this->out'                    $yy_yymore_patterns = array(' "\n");
  284.         for($i = 0; count($patterns)$i++{
  285.             unset($patterns[$i]);
  286.             fwrite($this->out'        ' $ruleMap[$i' => "' .
  287.                 implode('|'$patterns"\",\n");
  288.         }
  289.         fwrite($this->out'    );' "\n");
  290.         fwrite($this->out'
  291.                     // yymore is needed
  292.                     do {
  293.                         if (!strlen($yy_yymore_patterns[' $this->token . '])) {
  294.                             throw new Exception(\'cannot do yymore for the last token\');
  295.                         }
  296.                         if (preg_match($yy_yymore_patterns[' $this->token . '],
  297.                               substr(' $this->input . ', ' $this->counter . '), $yymatches)) {
  298.                             $yymatches = array_filter($yymatches, \'strlen\'); // remove empty sub-patterns
  299.                             next($yymatches); // skip global match
  300.                             ' $this->token . ' = key($yymatches); // token number
  301.                             ' $this->value . ' = current($yymatches); // token value
  302.                             ' $this->line . ' = substr_count("\n", ' $this->value . ');
  303.                         }
  304.                     } while ($this->{\'yy_r' $ruleindex '_\' . ' $this->token . '}() !== null);
  305.                     // accept
  306.                     ' $this->counter . ' += strlen($this->value);
  307.                     ' $this->line . ' += substr_count("\n", ' $this->value . ');
  308.                     return true;
  309.                 }
  310.             } else {
  311.                 throw new Exception(\'Unexpected input at line\' . ' $this->line . ' .
  312.                     \': \' . ' $this->input . '[' $this->counter . ']);
  313.             }
  314.             break;
  315.         } while (true);
  316.     } // end function
  317.  
  318. ');
  319.         if (is_string($statename)) {
  320.             fwrite($this->out'
  321.     const ' $statename ' = ' $ruleindex ';
  322. ');
  323.         }
  324.         foreach ($rules as $i => $rule{
  325.             fwrite($this->out'    function yy_r' $ruleindex '_' $ruleMap[$i'($yy_subpatterns)
  326.     {
  327. $rule['code'.
  328. '    }
  329. ');
  330.         }
  331.         $ruleindex++; // for next set of rules
  332.     }
  333.  
  334.     function error($msg)
  335.     {
  336.         echo 'Error on line ' $this->lex->line . ': ' $msg;
  337.     }
  338.  
  339.     function _validatePattern($pattern$update = false)
  340.     {
  341.         $this->_regexLexer->reset($pattern);
  342.         $this->_regexParser->reset($this->_patternIndex$update);
  343.         try {
  344.             while ($this->_regexLexer->yylex()) {
  345.                 $this->_regexParser->doParse(
  346.                     $this->_regexLexer->token$this->_regexLexer->value);
  347.             }
  348.             $this->_regexParser->doParse(00);
  349.         catch (PHP_LexerGenerator_Exception $e{
  350.             $this->error($e->getMessage());
  351.             throw new PHP_LexerGenerator_Exception('Invalid pattern "' $pattern '"');
  352.         }
  353.         return $this->_regexParser->result;
  354.     }
  355. #line 359 "Parser.php"
  356.  
  357. /* Next is all token values, as class constants
  358. */
  359. /* 
  360. ** These constants (all generated automatically by the parser generator)
  361. ** specify the various kinds of tokens (terminals) that the parser
  362. ** understands. 
  363. **
  364. ** Each symbol here is a terminal symbol in the grammar.
  365. */
  366.     const PHPCODE                        =  1;
  367.     const COMMENTSTART                   =  2;
  368.     const COMMENTEND                     =  3;
  369.     const PI                             =  4;
  370.     const SUBPATTERN                     =  5;
  371.     const CODE                           =  6;
  372.     const PATTERN                        =  7;
  373.     const QUOTE                          =  8;
  374.     const YY_NO_ACTION = 91;
  375.     const YY_ACCEPT_ACTION = 90;
  376.     const YY_ERROR_ACTION = 89;
  377.  
  378. /* Next are that tables used to determine what action to take based on the
  379. ** current state and lookahead token.  These tables are used to implement
  380. ** functions that take a state number and lookahead value and return an
  381. ** action integer.  
  382. **
  383. ** Suppose the action integer is N.  Then the action is determined as
  384. ** follows
  385. **
  386. **   0 <= N < self::YYNSTATE                              Shift N.  That is,
  387. **                                                        push the lookahead
  388. **                                                        token onto the stack
  389. **                                                        and goto state N.
  390. **
  391. **   self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE   Reduce by rule N-YYNSTATE.
  392. **
  393. **   N == self::YYNSTATE+self::YYNRULE                    A syntax error has occurred.
  394. **
  395. **   N == self::YYNSTATE+self::YYNRULE+1                  The parser accepts its
  396. **                                                        input. (and concludes parsing)
  397. **
  398. **   N == self::YYNSTATE+self::YYNRULE+2                  No such action.  Denotes unused
  399. **                                                        slots in the yy_action[] table.
  400. **
  401. ** The action table is constructed as a single large static array $yy_action.
  402. ** Given state S and lookahead X, the action is computed as
  403. **
  404. **      self::$yy_action[self::$yy_shift_ofst[S] + X ]
  405. **
  406. ** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value
  407. ** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if
  408. ** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that
  409. ** the action is not in the table and that self::$yy_default[S] should be used instead.  
  410. **
  411. ** The formula above is for computing the action when the lookahead is
  412. ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
  413. ** a reduce action) then the static $yy_reduce_ofst array is used in place of
  414. ** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of
  415. ** self::YY_SHIFT_USE_DFLT.
  416. **
  417. ** The following are the tables generated in this section:
  418. **
  419. **  self::$yy_action        A single table containing all actions.
  420. **  self::$yy_lookahead     A table containing the lookahead for each entry in
  421. **                          yy_action.  Used to detect hash collisions.
  422. **  self::$yy_shift_ofst    For each state, the offset into self::$yy_action for
  423. **                          shifting terminals.
  424. **  self::$yy_reduce_ofst   For each state, the offset into self::$yy_action for
  425. **                          shifting non-terminals after a reduce.
  426. **  self::$yy_default       Default action for each state.
  427. */
  428.     const YY_SZ_ACTTAB = 80;
  429. static public $yy_action = array(
  430.  /*     0 */    35,   24,   50,   50,   48,   51,   51,   54,   47,   43,
  431.  /*    10 */    53,   54,   45,   31,   53,   32,   30,   50,   50,    1,
  432.  /*    20 */    51,   51,   34,   50,   17,    8,   51,   90,   52,    6,
  433.  /*    30 */     3,   29,   50,   50,   25,   51,   51,   11,   38,   18,
  434.  /*    40 */     1,   41,   42,   39,   10,   36,   18,   12,   37,   18,
  435.  /*    50 */    20,    7,    2,   16,   13,   15,   18,   27,    9,    2,
  436.  /*    60 */     5,   28,   14,    1,   44,   40,   33,   49,   56,   46,
  437.  /*    70 */    26,   19,    1,   55,    2,   21,    4,   23,   22,    8,
  438.     );
  439.     static public $yy_lookahead = array(
  440.  /*     0 */     3,    3,    5,    5,    1,    8,    8,    5,    6,    2,
  441.  /*    10 */     8,    5,    6,   13,    8,    3,    3,    5,    5,   19,
  442.  /*    20 */     8,    8,    4,    5,    1,    2,    8,   10,   11,   12,
  443.  /*    30 */     5,    4,    5,    5,   13,    8,    8,   18,    5,   20,
  444.  /*    40 */    19,    8,    5,    6,   18,    5,   20,   18,    8,   20,
  445.  /*    50 */     4,    1,    2,    7,   18,    7,   20,   13,    1,    2,
  446.  /*    60 */     5,   14,   15,   19,    5,    6,   13,    1,    1,    1,
  447.  /*    70 */    16,   20,   19,    3,    2,   17,   12,    4,   17,    2,
  448. );
  449.     const YY_SHIFT_USE_DFLT = -4;
  450.     const YY_SHIFT_MAX = 35;
  451.     static public $yy_shift_ofst = array(
  452.  /*     0 */    23,   27,   18,   28,   50,   28,   57,   72,   73,   72,
  453.  /*    10 */    13,   12,   -3,   -2,   46,   40,   40,   77,    2,    6,
  454.  /*    20 */    59,   33,   33,   37,    3,    7,   48,    7,   70,   55,
  455.  /*    30 */    68,    7,   67,    7,   25,   66,
  456. );
  457.     const YY_REDUCE_USE_DFLT = -1;
  458.     const YY_REDUCE_MAX = 17;
  459.     static public $yy_reduce_ofst = array(
  460.  /*     0 */    17,   29,   19,   26,   21,   36,   53,   44,   47,    0,
  461.  /*    10 */    51,   51,   51,   51,   54,   58,   61,   64,
  462. );
  463.     static public $yyExpectedTokens = array(
  464.         /* 0 */ array(12),
  465.         /* 1 */ array(458),
  466.         /* 2 */ array(458),
  467.         /* 3 */ array(58),
  468.         /* 4 */ array(12),
  469.         /* 5 */ array(58),
  470.         /* 6 */ array(12),
  471.         /* 7 */ array(2),
  472.         /* 8 */ array(4),
  473.         /* 9 */ array(2),
  474.         /* 10 */ array(358),
  475.         /* 11 */ array(358),
  476.         /* 12 */ array(358),
  477.         /* 13 */ array(358),
  478.         /* 14 */ array(47),
  479.         /* 15 */ array(58),
  480.         /* 16 */ array(58),
  481.         /* 17 */ array(2),
  482.         /* 18 */ array(568),
  483.         /* 19 */ array(568),
  484.         /* 20 */ array(56),
  485.         /* 21 */ array(58),
  486.         /* 22 */ array(58),
  487.         /* 23 */ array(56),
  488.         /* 24 */ array(1),
  489.         /* 25 */ array(2),
  490.         /* 26 */ array(7),
  491.         /* 27 */ array(2),
  492.         /* 28 */ array(3),
  493.         /* 29 */ array(5),
  494.         /* 30 */ array(1),
  495.         /* 31 */ array(2),
  496.         /* 32 */ array(1),
  497.         /* 33 */ array(2),
  498.         /* 34 */ array(5),
  499.         /* 35 */ array(1),
  500.         /* 36 */ array(),
  501.         /* 37 */ array(),
  502.         /* 38 */ array(),
  503.         /* 39 */ array(),
  504.         /* 40 */ array(),
  505.         /* 41 */ array(),
  506.         /* 42 */ array(),
  507.         /* 43 */ array(),
  508.         /* 44 */ array(),
  509.         /* 45 */ array(),
  510.         /* 46 */ array(),
  511.         /* 47 */ array(),
  512.         /* 48 */ array(),
  513.         /* 49 */ array(),
  514.         /* 50 */ array(),
  515.         /* 51 */ array(),
  516.         /* 52 */ array(),
  517.         /* 53 */ array(),
  518.         /* 54 */ array(),
  519.         /* 55 */ array(),
  520.         /* 56 */ array(),
  521. );
  522.     static public $yy_default = array(
  523.  /*     0 */    89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
  524.  /*    10 */    89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
  525.  /*    20 */    89,   69,   68,   89,   75,   60,   63,   61,   89,   89,
  526.  /*    30 */    71,   59,   70,   58,   89,   74,   86,   85,   88,   65,
  527.  /*    40 */    67,   87,   64,   78,   66,   80,   73,   79,   77,   76,
  528.  /*    50 */    82,   81,   57,   83,   84,   62,   72,
  529. );
  530. /* The next thing included is series of defines which control
  531. ** various aspects of the generated parser.
  532. **    self::YYNOCODE      is a number which corresponds
  533. **                        to no legal terminal or nonterminal number.  This
  534. **                        number is used to fill in empty slots of the hash 
  535. **                        table.
  536. **    self::YYFALLBACK    If defined, this indicates that one or more tokens
  537. **                        have fall-back values which should be used if the
  538. **                        original value of the token will not parse.
  539. **    self::YYSTACKDEPTH  is the maximum depth of the parser's stack.
  540. **    self::YYNSTATE      the combined number of states.
  541. **    self::YYNRULE       the number of rules in the grammar
  542. **    self::YYERRORSYMBOL is the code number of the error symbol.  If not
  543. **                        defined, then do no error processing.
  544. */
  545.     const YYNOCODE = 22;
  546.     const YYSTACKDEPTH = 100;
  547.     const YYNSTATE = 57;
  548.     const YYNRULE = 32;
  549.     const YYERRORSYMBOL = 9;
  550.     const YYERRSYMDT = 'yy0';
  551.     const YYFALLBACK = 0;
  552.     /** The next table maps tokens into fallback tokens.  If a construct
  553.      * like the following:
  554.      * 
  555.      *      %fallback ID X Y Z.
  556.      *
  557.      * appears in the grammer, then ID becomes a fallback token for X, Y,
  558.      * and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
  559.      * but it does not parse, the type of the token is changed to ID and
  560.      * the parse is retried before an error is thrown.
  561.      */
  562.     static public $yyFallback = array(
  563.     );
  564.     /**
  565.      * Turn parser tracing on by giving a stream to which to write the trace
  566.      * and a prompt to preface each trace message.  Tracing is turned off
  567.      * by making either argument NULL
  568.      *
  569.      * Inputs:
  570.      * 
  571.      * - A stream resource to which trace output should be written.
  572.      *   If NULL, then tracing is turned off.
  573.      * - A prefix string written at the beginning of every
  574.      *   line of trace output.  If NULL, then tracing is
  575.      *   turned off.
  576.      *
  577.      * Outputs:
  578.      * 
  579.      * - None.
  580.      * @param resource 
  581.      * @param string 
  582.      */
  583.     static function Trace($TraceFILE$zTracePrompt)
  584.     {
  585.         if (!$TraceFILE{
  586.             $zTracePrompt = 0;
  587.         elseif (!$zTracePrompt{
  588.             $TraceFILE = 0;
  589.         }
  590.         self::$yyTraceFILE $TraceFILE;
  591.         self::$yyTracePrompt $zTracePrompt;
  592.     }
  593.  
  594.     /**
  595.      * Output debug information to output (php://output stream)
  596.      */
  597.     static function PrintTrace()
  598.     {
  599.         self::$yyTraceFILE = fopen('php://output''w');
  600.         self::$yyTracePrompt '';
  601.     }
  602.  
  603.     /**
  604.      * @var resource|0
  605.      */
  606.     static public $yyTraceFILE;
  607.     /**
  608.      * String to prepend to debug output
  609.      * @var string|0
  610.      */
  611.     static public $yyTracePrompt;
  612.     /**
  613.      * @var int 
  614.      */
  615.     public $yyidx;                    /* Index of top element in stack */
  616.     /**
  617.      * @var int 
  618.      */
  619.     public $yyerrcnt;                 /* Shifts left before out of the error */
  620.     /**
  621.      * @var array 
  622.      */
  623.     public $yystack = array();  /* The parser's stack */
  624.  
  625.     /**
  626.      * For tracing shifts, the names of all terminals and nonterminals
  627.      * are required.  The following table supplies these names
  628.      * @var array 
  629.      */
  630.     static public $yyTokenName = array
  631.   '$',             'PHPCODE',       'COMMENTSTART',  'COMMENTEND',  
  632.   'PI',            'SUBPATTERN',    'CODE',          'PATTERN',     
  633.   'QUOTE',         'error',         'start',         'lexfile',     
  634.   'declare',       'rules',         'declarations',  'processing_instructions',
  635.   'pattern_declarations',  'subpattern',    'rule',          'reset_rules'
  636.   'rule_subpattern',
  637.     );
  638.  
  639.     /**
  640.      * For tracing reduce actions, the names of all rules are required.
  641.      * @var array 
  642.      */
  643.     static public $yyRuleName = array(
  644.  /*   0 */ "start ::= lexfile",
  645.  /*   1 */ "lexfile ::= declare rules",
  646.  /*   2 */ "lexfile ::= declare PHPCODE rules",
  647.  /*   3 */ "lexfile ::= PHPCODE declare rules",
  648.  /*   4 */ "lexfile ::= PHPCODE declare PHPCODE rules",
  649.  /*   5 */ "declare ::= COMMENTSTART declarations COMMENTEND",
  650.  /*   6 */ "declarations ::= processing_instructions pattern_declarations",
  651.  /*   7 */ "processing_instructions ::= PI SUBPATTERN",
  652.  /*   8 */ "processing_instructions ::= PI CODE",
  653.  /*   9 */ "processing_instructions ::= processing_instructions PI SUBPATTERN",
  654.  /*  10 */ "processing_instructions ::= processing_instructions PI CODE",
  655.  /*  11 */ "pattern_declarations ::= PATTERN subpattern",
  656.  /*  12 */ "pattern_declarations ::= pattern_declarations PATTERN subpattern",
  657.  /*  13 */ "rules ::= COMMENTSTART rule COMMENTEND",
  658.  /*  14 */ "rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND",
  659.  /*  15 */ "rules ::= COMMENTSTART rule COMMENTEND PHPCODE",
  660.  /*  16 */ "rules ::= COMMENTSTART PI SUBPATTERN rule COMMENTEND PHPCODE",
  661.  /*  17 */ "rules ::= reset_rules rule COMMENTEND",
  662.  /*  18 */ "rules ::= reset_rules PI SUBPATTERN rule COMMENTEND",
  663.  /*  19 */ "rules ::= reset_rules rule COMMENTEND PHPCODE",
  664.  /*  20 */ "rules ::= reset_rules PI SUBPATTERN rule COMMENTEND PHPCODE",
  665.  /*  21 */ "reset_rules ::= rules COMMENTSTART",
  666.  /*  22 */ "rule ::= rule_subpattern CODE",
  667.  /*  23 */ "rule ::= rule rule_subpattern CODE",
  668.  /*  24 */ "rule_subpattern ::= QUOTE",
  669.  /*  25 */ "rule_subpattern ::= SUBPATTERN",
  670.  /*  26 */ "rule_subpattern ::= rule_subpattern QUOTE",
  671.  /*  27 */ "rule_subpattern ::= rule_subpattern SUBPATTERN",
  672.  /*  28 */ "subpattern ::= QUOTE",
  673.  /*  29 */ "subpattern ::= SUBPATTERN",
  674.  /*  30 */ "subpattern ::= subpattern QUOTE",
  675.  /*  31 */ "subpattern ::= subpattern SUBPATTERN",
  676.     );
  677.  
  678.     /**
  679.      * This function returns the symbolic name associated with a token
  680.      * value.
  681.      * @param int 
  682.      * @return string 
  683.      */
  684.     function tokenName($tokenType)
  685.     {
  686.         if ($tokenType === 0{
  687.             return 'End of Input';
  688.         }
  689.         if ($tokenType > 0 && $tokenType count(self::$yyTokenName)) {
  690.             return self::$yyTokenName[$tokenType];
  691.         else {
  692.             return "Unknown";
  693.         }
  694.     }
  695.  
  696.     /**
  697.      * The following function deletes the value associated with a
  698.      * symbol.  The symbol can be either a terminal or nonterminal.
  699.      * @param int the symbol code
  700.      * @param mixed the symbol's value
  701.      */
  702.     static function yy_destructor($yymajor$yypminor)
  703.     {
  704.         switch ($yymajor{
  705.         /* Here is inserted the actions which take place when a
  706.         ** terminal or non-terminal is destroyed.  This can happen
  707.         ** when the symbol is popped from the stack during a
  708.         ** reduce or during error processing or when a parser is 
  709.         ** being destroyed before it is finished parsing.
  710.         **
  711.         ** Note: during a reduce, the only symbols destroyed are those
  712.         ** which appear on the RHS of the rule, but which are not used
  713.         ** inside the C code.
  714.         */
  715.             default:  break;   /* If no destructor action specified: do nothing */
  716.         }
  717.     }
  718.  
  719.     /**
  720.      * Pop the parser's stack once.
  721.      *
  722.      * If there is a destructor routine associated with the token which
  723.      * is popped from the stack, then call it.
  724.      *
  725.      * Return the major token number for the symbol popped.
  726.      * @param PHP_LexerGenerator_ParseryyParser 
  727.      * @return int 
  728.      */
  729.     function yy_pop_parser_stack()
  730.     {
  731.         if (!count($this->yystack)) {
  732.             return;
  733.         }
  734.         $yytos array_pop($this->yystack);
  735.         if (self::$yyTraceFILE && $this->yyidx >= 0{
  736.             fwrite(self::$yyTraceFILE,
  737.                 self::$yyTracePrompt 'Popping ' . self::$yyTokenName[$yytos->major.
  738.                     "\n");
  739.         }
  740.         $yymajor $yytos->major;
  741.         self::yy_destructor($yymajor$yytos->minor);
  742.         $this->yyidx--;
  743.         return $yymajor;
  744.     }
  745.  
  746.     /**
  747.      * Deallocate and destroy a parser.  Destructors are all called for
  748.      * all stack elements before shutting the parser down.
  749.      */
  750.     function __destruct()
  751.     {
  752.         while ($this->yyidx >= 0{
  753.             $this->yy_pop_parser_stack();
  754.         }
  755.         if (is_resource(self::$yyTraceFILE)) {
  756.             fclose(self::$yyTraceFILE);
  757.         }
  758.     }
  759.  
  760.     /**
  761.      * Based on the current state and parser stack, get a list of all
  762.      * possible lookahead tokens
  763.      * @param int 
  764.      * @return array 
  765.      */
  766.     function yy_get_expected_tokens($token)
  767.     {
  768.         $state $this->yystack[$this->yyidx]->stateno;
  769.         $expected = self::$yyExpectedTokens[$state];
  770.         if (in_array($tokenself::$yyExpectedTokens[$state]true)) {
  771.             return $expected;
  772.         }
  773.         $stack $this->yystack;
  774.         $yyidx $this->yyidx;
  775.         do {
  776.             $yyact $this->yy_find_shift_action($token);
  777.             if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE{
  778.                 // reduce action
  779.                 $done = 0;
  780.                 do {
  781.                     if ($done++ == 100{
  782.                         $this->yyidx = $yyidx;
  783.                         $this->yystack = $stack;
  784.                         // too much recursion prevents proper detection
  785.                         // so give up
  786.                         return array_unique($expected);
  787.                     }
  788.                     $yyruleno $yyact - self::YYNSTATE;
  789.                     $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
  790.                     $nextstate $this->yy_find_reduce_action(
  791.                         $this->yystack[$this->yyidx]->stateno,
  792.                         self::$yyRuleInfo[$yyruleno]['lhs']);
  793.                     if (isset(self::$yyExpectedTokens[$nextstate])) {
  794.                         $expected += self::$yyExpectedTokens[$nextstate];
  795.                             if (in_array($token,
  796.                                   self::$yyExpectedTokens[$nextstate]true)) {
  797.                             $this->yyidx = $yyidx;
  798.                             $this->yystack = $stack;
  799.                             return array_unique($expected);
  800.                         }
  801.                     }
  802.                     if ($nextstate < self::YYNSTATE{
  803.                         // we need to shift a non-terminal
  804.                         $this->yyidx++;
  805.                         $x = new PHP_LexerGenerator_ParseryyStackEntry;
  806.                         $x->stateno = $nextstate;
  807.                         $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
  808.                         $this->yystack[$this->yyidx$x;
  809.                         continue 2;
  810.                     elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1{
  811.                         $this->yyidx = $yyidx;
  812.                         $this->yystack = $stack;
  813.                         // the last token was just ignored, we can't accept
  814.                         // by ignoring input, this is in essence ignoring a
  815.                         // syntax error!
  816.                         return array_unique($expected);
  817.                     elseif ($nextstate === self::YY_NO_ACTION{
  818.                         $this->yyidx = $yyidx;
  819.                         $this->yystack = $stack;
  820.                         // input accepted, but not shifted (I guess)
  821.                         return $expected;
  822.                     else {
  823.                         $yyact $nextstate;
  824.                     }
  825.                 while (true);
  826.             }
  827.             break;
  828.         while (true);
  829.         return array_unique($expected);
  830.     }
  831.  
  832.     /**
  833.      * Based on the parser state and current parser stack, determine whether
  834.      * the lookahead token is possible.
  835.      * 
  836.      * The parser will convert the token value to an error token if not.  This
  837.      * catches some unusual edge cases where the parser would fail.
  838.      * @param int 
  839.      * @return bool 
  840.      */
  841.     function yy_is_expected_token($token)
  842.     {
  843.         if ($token === 0{
  844.             return true; // 0 is not part of this
  845.         }
  846.         $state $this->yystack[$this->yyidx]->stateno;
  847.         if (in_array($tokenself::$yyExpectedTokens[$state]true)) {
  848.             return true;
  849.         }
  850.         $stack $this->yystack;
  851.         $yyidx $this->yyidx;
  852.         do {
  853.             $yyact $this->yy_find_shift_action($token);
  854.             if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE{
  855.                 // reduce action
  856.                 $done = 0;
  857.                 do {
  858.                     if ($done++ == 100{
  859.                         $this->yyidx = $yyidx;
  860.                         $this->yystack = $stack;
  861.                         // too much recursion prevents proper detection
  862.                         // so give up
  863.                         return true;
  864.                     }
  865.                     $yyruleno $yyact - self::YYNSTATE;
  866.                     $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
  867.                     $nextstate $this->yy_find_reduce_action(
  868.                         $this->yystack[$this->yyidx]->stateno,
  869.                         self::$yyRuleInfo[$yyruleno]['lhs']);
  870.                     if (isset(self::$yyExpectedTokens[$nextstate]&&
  871.                           in_array($tokenself::$yyExpectedTokens[$nextstate]true)) {
  872.                         $this->yyidx = $yyidx;
  873.                         $this->yystack = $stack;
  874.                         return true;
  875.                     }
  876.                     if ($nextstate < self::YYNSTATE{
  877.                         // we need to shift a non-terminal
  878.                         $this->yyidx++;
  879.                         $x = new PHP_LexerGenerator_ParseryyStackEntry;
  880.                         $x->stateno = $nextstate;
  881.                         $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
  882.                         $this->yystack[$this->yyidx$x;
  883.                         continue 2;
  884.                     elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1{
  885.                         $this->yyidx = $yyidx;
  886.                         $this->yystack = $stack;
  887.                         if (!$token{
  888.                             // end of input: this is valid
  889.                             return true;
  890.                         }
  891.                         // the last token was just ignored, we can't accept
  892.                         // by ignoring input, this is in essence ignoring a
  893.                         // syntax error!
  894.                         return false;
  895.                     elseif ($nextstate === self::YY_NO_ACTION{
  896.                         $this->yyidx = $yyidx;
  897.                         $this->yystack = $stack;
  898.                         // input accepted, but not shifted (I guess)
  899.                         return true;
  900.                     else {
  901.                         $yyact $nextstate;
  902.                     }
  903.                 while (true);
  904.             }
  905.             break;
  906.         while (true);
  907.         return true;
  908.     }
  909.  
  910.     /**
  911.      * Find the appropriate action for a parser given the terminal
  912.      * look-ahead token iLookAhead.
  913.      *
  914.      * If the look-ahead token is YYNOCODE, then check to see if the action is
  915.      * independent of the look-ahead.  If it is, return the action, otherwise
  916.      * return YY_NO_ACTION.
  917.      * @param int The look-ahead token
  918.      */
  919.     function yy_find_shift_action($iLookAhead)
  920.     {
  921.         $stateno $this->yystack[$this->yyidx]->stateno;
  922.      
  923.         /* if ($this->yyidx < 0) return self::YY_NO_ACTION;  */
  924.         if (!isset(self::$yy_shift_ofst[$stateno])) {
  925.             // no shift actions
  926.             return self::$yy_default[$stateno];
  927.         }
  928.         $i = self::$yy_shift_ofst[$stateno];
  929.         if ($i === self::YY_SHIFT_USE_DFLT{
  930.             return self::$yy_default[$stateno];
  931.         }
  932.         if ($iLookAhead == self::YYNOCODE{
  933.             return self::YY_NO_ACTION;
  934.         }
  935.         $i += $iLookAhead;
  936.         if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
  937.               self::$yy_lookahead[$i!= $iLookAhead{
  938.             if (count(self::$yyFallback&& $iLookAhead < count(self::$yyFallback)
  939.                    && ($iFallback = self::$yyFallback[$iLookAhead]!= 0{
  940.                 if (self::$yyTraceFILE{
  941.                     fwrite(self::$yyTraceFILEself::$yyTracePrompt "FALLBACK " .
  942.                         self::$yyTokenName[$iLookAhead" => " .
  943.                         self::$yyTokenName[$iFallback"\n");
  944.                 }
  945.                 return $this->yy_find_shift_action($iFallback);
  946.             }
  947.             return self::$yy_default[$stateno];
  948.         else {
  949.             return self::$yy_action[$i];
  950.         }
  951.     }
  952.  
  953.     /**
  954.      * Find the appropriate action for a parser given the non-terminal
  955.      * look-ahead token $iLookAhead.
  956.      *
  957.      * If the look-ahead token is self::YYNOCODE, then check to see if the action is
  958.      * independent of the look-ahead.  If it is, return the action, otherwise
  959.      * return self::YY_NO_ACTION.
  960.      * @param int Current state number
  961.      * @param int The look-ahead token
  962.      */
  963.     function yy_find_reduce_action($stateno$iLookAhead)
  964.     {
  965.         /* $stateno = $this->yystack[$this->yyidx]->stateno; */
  966.  
  967.         if (!isset(self::$yy_reduce_ofst[$stateno])) {
  968.             return self::$yy_default[$stateno];
  969.         }
  970.         $i = self::$yy_reduce_ofst[$stateno];
  971.         if ($i == self::YY_REDUCE_USE_DFLT{
  972.             return self::$yy_default[$stateno];
  973.         }
  974.         if ($iLookAhead == self::YYNOCODE{
  975.             return self::YY_NO_ACTION;
  976.         }
  977.         $i += $iLookAhead;
  978.         if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
  979.               self::$yy_lookahead[$i!= $iLookAhead{
  980.             return self::$yy_default[$stateno];
  981.         else {
  982.             return self::$yy_action[$i];
  983.         }
  984.     }
  985.  
  986.     /**
  987.      * Perform a shift action.
  988.      * @param int The new state to shift in
  989.      * @param int The major token to shift in
  990.      * @param mixed the minor token to shift in
  991.      */
  992.     function yy_shift($yyNewState$yyMajor$yypMinor)
  993.     {
  994.         $this->yyidx++;
  995.         if ($this->yyidx >= self::YYSTACKDEPTH{
  996.             $this->yyidx--;
  997.             if (self::$yyTraceFILE{
  998.                 fprintf(self::$yyTraceFILE"%sStack Overflow!\n"self::$yyTracePrompt);
  999.             }
  1000.             while ($this->yyidx >= 0{
  1001.                 $this->yy_pop_parser_stack();
  1002.             }
  1003.             /* Here code is inserted which will execute if the parser
  1004.             ** stack ever overflows */
  1005.             return;
  1006.         }
  1007.         $yytos = new PHP_LexerGenerator_ParseryyStackEntry;
  1008.         $yytos->stateno = $yyNewState;
  1009.         $yytos->major = $yyMajor;
  1010.         $yytos->minor = $yypMinor;
  1011.         array_push($this->yystack$yytos);
  1012.         if (self::$yyTraceFILE && $this->yyidx > 0{
  1013.             fprintf(self::$yyTraceFILE"%sShift %d\n"self::$yyTracePrompt,
  1014.                 $yyNewState);
  1015.             fprintf(self::$yyTraceFILE"%sStack:"self::$yyTracePrompt);
  1016.             for($i = 1; $i <= $this->yyidx; $i++{
  1017.                 fprintf(self::$yyTraceFILE" %s",
  1018.                     self::$yyTokenName[$this->yystack[$i]->major]);
  1019.             }
  1020.             fwrite(self::$yyTraceFILE,"\n");
  1021.         }
  1022.     }
  1023.  
  1024.     /**
  1025.      * The following table contains information about every rule that
  1026.      * is used during the reduce.
  1027.      *
  1028.      * <pre>
  1029.      * array(
  1030.      *  array(
  1031.      *   int $lhs;         Symbol on the left-hand side of the rule
  1032.      *   int $nrhs;     Number of right-hand side symbols in the rule
  1033.      *  ),...
  1034.      * );
  1035.      * </pre>
  1036.      */
  1037.     static public $yyRuleInfo = array(
  1038.   array'lhs' => 10'rhs' => 1 ),
  1039.   array'lhs' => 11'rhs' => 2 ),
  1040.   array'lhs' => 11'rhs' => 3 ),
  1041.   array'lhs' => 11'rhs' => 3 ),
  1042.   array'lhs' => 11'rhs' => 4 ),
  1043.   array'lhs' => 12'rhs' => 3 ),
  1044.   array'lhs' => 14'rhs' => 2 ),
  1045.   array'lhs' => 15'rhs' => 2 ),
  1046.   array'lhs' => 15'rhs' => 2 ),
  1047.   array'lhs' => 15'rhs' => 3 ),
  1048.   array'lhs' => 15'rhs' => 3 ),
  1049.   array'lhs' => 16'rhs' => 2 ),
  1050.   array'lhs' => 16'rhs' => 3 ),
  1051.   array'lhs' => 13'rhs' => 3 ),
  1052.   array'lhs' => 13'rhs' => 5 ),
  1053.   array'lhs' => 13'rhs' => 4 ),
  1054.   array'lhs' => 13'rhs' => 6 ),
  1055.   array'lhs' => 13'rhs' => 3 ),
  1056.   array'lhs' => 13'rhs' => 5 ),
  1057.   array'lhs' => 13'rhs' => 4 ),
  1058.   array'lhs' => 13'rhs' => 6 ),
  1059.   array'lhs' => 19'rhs' => 2 ),
  1060.   array'lhs' => 18'rhs' => 2 ),
  1061.   array'lhs' => 18'rhs' => 3 ),
  1062.   array'lhs' => 20'rhs' => 1 ),
  1063.   array'lhs' => 20'rhs' => 1 ),
  1064.   array'lhs' => 20'rhs' => 2 ),
  1065.   array'lhs' => 20'rhs' => 2 ),
  1066.   array'lhs' => 17'rhs' => 1 ),
  1067.   array'lhs' => 17'rhs' => 1 ),
  1068.   array'lhs' => 17'rhs' => 2 ),
  1069.   array'lhs' => 17'rhs' => 2 ),
  1070.     );
  1071.  
  1072.     /**
  1073.      * The following table contains a mapping of reduce action to method name
  1074.      * that handles the reduction.
  1075.      * 
  1076.      * If a rule is not set, it has no handler.
  1077.      */
  1078.     static public $yyReduceMap = array(
  1079.         1 => 1,
  1080.         2 => 2,
  1081.         3 => 3,
  1082.         4 => 4,
  1083.         5 => 5,
  1084.         6 => 6,
  1085.         7 => 7,
  1086.         8 => 7,
  1087.         9 => 9,
  1088.         10 => 9,
  1089.         11 => 11,
  1090.         12 => 12,
  1091.         13 => 13,
  1092.         14 => 14,
  1093.         15 => 15,
  1094.         16 => 16,
  1095.         17 => 17,
  1096.         18 => 18,
  1097.         19 => 19,
  1098.         20 => 20,
  1099.         21 => 21,
  1100.         22 => 22,
  1101.         23 => 23,
  1102.         24 => 24,
  1103.         25 => 25,
  1104.         26 => 26,
  1105.         27 => 27,
  1106.         28 => 28,
  1107.         29 => 29,
  1108.         30 => 30,
  1109.         31 => 31,
  1110.     );
  1111.     /* Beginning here are the reduction cases.  A typical example
  1112.     ** follows:
  1113.     **  #line <lineno> <grammarfile>
  1114.     **   function yy_r0($yymsp){ ... }           // User supplied code
  1115.     **  #line <lineno> <thisfile>
  1116.     */
  1117. #line 268 "Parser.y"
  1118.     function yy_r1(){
  1119.     fwrite($this->out'
  1120.     private $_yy_state = 1;
  1121.     private $_yy_stack = array();
  1122.  
  1123.     function yylex()
  1124.     {
  1125.         return $this->{\'yylex\' . $this->_yy_state}();
  1126.     }
  1127.  
  1128.     function yypushstate($state)
  1129.     {
  1130.         array_push($this->_yy_stack, $this->_yy_state);
  1131.         $this->_yy_state = $state;
  1132.     }
  1133.  
  1134.     function yypopstate()
  1135.     {
  1136.         $this->_yy_state = array_pop($this->_yy_stack);
  1137.     }
  1138.  
  1139.     function yybegin($state)
  1140.     {
  1141.         $this->_yy_state = $state;
  1142.     }
  1143.  
  1144. ');
  1145.     foreach ($this->yystack[$this->yyidx + 0]->minor as $rule{
  1146.         $this->outputRules($rule['rules']$rule['statename']);
  1147.         if ($rule['code']{
  1148.             fwrite($this->out$rule['code']);
  1149.         }
  1150.     }
  1151.     }
  1152. #line 1158 "Parser.php"
  1153. #line 302 "Parser.y"
  1154.     function yy_r2(){
  1155.     fwrite($this->out'
  1156.     private $_yy_state = 1;
  1157.     private $_yy_stack = array();
  1158.  
  1159.     function yylex()
  1160.     {
  1161.         return $this->{\'yylex\' . $this->_yy_state}();
  1162.     }
  1163.  
  1164.     function yypushstate($state)
  1165.     {
  1166.         array_push($this->_yy_stack, $this->_yy_state);
  1167.         $this->_yy_state = $state;
  1168.     }
  1169.  
  1170.     function yypopstate()
  1171.     {
  1172.         $this->_yy_state = array_pop($this->_yy_stack);
  1173.     }
  1174.  
  1175.     function yybegin($state)
  1176.     {
  1177.         $this->_yy_state = $state;
  1178.     }
  1179.  
  1180. ');
  1181.     if (strlen($this->yystack[$this->yyidx + -1]->minor)) {
  1182.         fwrite($this->out$this->yystack[$this->yyidx + -1]->minor);
  1183.     }
  1184.     foreach ($this->yystack[$this->yyidx + 0]->minor as $rule{
  1185.         $this->outputRules($rule['rules']$rule['statename']);
  1186.         if ($rule['code']{
  1187.             fwrite($this->out$rule['code']);
  1188.         }
  1189.     }
  1190.     }
  1191. #line 1197 "Parser.php"
  1192. #line 339 "Parser.y"
  1193.     function yy_r3(){
  1194.     if (strlen($this->yystack[$this->yyidx + -2]->minor)) {
  1195.         fwrite($this->out$this->yystack[$this->yyidx + -2]->minor);
  1196.     }
  1197.     fwrite($this->out'
  1198.     private $_yy_state = 1;
  1199.     private $_yy_stack = array();
  1200.  
  1201.     function yylex()
  1202.     {
  1203.         return $this->{\'yylex\' . $this->_yy_state}();
  1204.     }
  1205.  
  1206.     function yypushstate($state)
  1207.     {
  1208.         array_push($this->_yy_stack, $this->_yy_state);
  1209.         $this->_yy_state = $state;
  1210.     }
  1211.  
  1212.     function yypopstate()
  1213.     {
  1214.         $this->_yy_state = array_pop($this->_yy_stack);
  1215.     }
  1216.  
  1217.     function yybegin($state)
  1218.     {
  1219.         $this->_yy_state = $state;
  1220.     }
  1221.  
  1222. ');
  1223.     foreach ($this->yystack[$this->yyidx + 0]->minor as $rule{
  1224.         $this->outputRules($rule['rules']$rule['statename']);
  1225.         if ($rule['code']{
  1226.             fwrite($this->out$rule['code']);
  1227.         }
  1228.     }
  1229.     }
  1230. #line 1236 "Parser.php"
  1231. #line 376 "Parser.y"
  1232.     function yy_r4(){
  1233.     if (strlen($this->yystack[$this->yyidx + -3]->minor)) {
  1234.         fwrite($this->out$this->yystack[$this->yyidx + -3]->minor);
  1235.     }
  1236.     fwrite($this->out'
  1237.     private $_yy_state = 1;
  1238.     private $_yy_stack = array();
  1239.  
  1240.     function yylex()
  1241.     {
  1242.         return $this->{\'yylex\' . $this->_yy_state}();
  1243.     }
  1244.  
  1245.     function yypushstate($state)
  1246.     {
  1247.         array_push($this->_yy_stack, $this->_yy_state);
  1248.         $this->_yy_state = $state;
  1249.     }
  1250.  
  1251.     function yypopstate()
  1252.     {
  1253.         $this->_yy_state = array_pop($this->_yy_stack);
  1254.     }
  1255.  
  1256.     function yybegin($state)
  1257.     {
  1258.         $this->_yy_state = $state;
  1259.     }
  1260.  
  1261. ');
  1262.     if (strlen($this->yystack[$this->yyidx + -1]->minor)) {
  1263.         fwrite($this->out$this->yystack[$this->yyidx + -1]->minor);
  1264.     }
  1265.     foreach ($this->yystack[$this->yyidx + 0]->minor as $rule{
  1266.         $this->outputRules($rule['rules']$rule['statename']);
  1267.         if ($rule['code']{
  1268.             fwrite($this->out$rule['code']);
  1269.         }
  1270.     }
  1271.     }
  1272. #line 1278 "Parser.php"
  1273. #line 417 "Parser.y"
  1274.     function yy_r5(){
  1275.     $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
  1276.     $this->patterns = $this->yystack[$this->yyidx + -1]->minor['patterns'];
  1277.     $this->_patternIndex = 1;
  1278.     }
  1279. #line 1285 "Parser.php"
  1280. #line 423 "Parser.y"
  1281.     function yy_r6(){
  1282.     $expected = array(
  1283.         'counter' => true,
  1284.         'input' => true,
  1285.         'token' => true,
  1286.         'value' => true,
  1287.         'line' => true,
  1288.     );
  1289.     foreach ($this->yystack[$this->yyidx + -1]->minor as $pi{
  1290.         if (isset($expected[$pi['pi']])) {
  1291.             unset($expected[$pi['pi']]);
  1292.             continue;
  1293.         }
  1294.         if (count($expected)) {
  1295.             throw new Exception('Processing Instructions "' .
  1296.                 implode(', 'array_keys($expected)) '" must be defined');
  1297.         }
  1298.     }
  1299.     $expected = array(
  1300.         'counter' => true,
  1301.         'input' => true,
  1302.         'token' => true,
  1303.         'value' => true,
  1304.         'line' => true,
  1305.     );
  1306.     foreach ($this->yystack[$this->yyidx + -1]->minor as $pi{
  1307.         if (isset($expected[$pi['pi']])) {
  1308.             $this->{$pi['pi']$pi['definition'];
  1309.             continue;
  1310.         }
  1311.         $this->error('Unknown processing instruction %' $pi['pi'.
  1312.             ', should be one of "' implode(', 'array_keys($expected)) '"');
  1313.     }
  1314.     $this->_retvalue = array('patterns' => $this->yystack[$this->yyidx + 0]->minor'pis' => $this->yystack[$this->yyidx + -1]->minor);
  1315.     $this->_patternIndex = 1;
  1316.     }
  1317. #line 1323 "Parser.php"
  1318. #line 460 "Parser.y"
  1319.     function yy_r7(){
  1320.     $this->_retvalue = array(array('pi' => $this->yystack[$this->yyidx + -1]->minor'definition' => $this->yystack[$this->yyidx + 0]->minor));
  1321.     }
  1322. #line 1328 "Parser.php"
  1323. #line 466 "Parser.y"
  1324.     function yy_r9(){
  1325.     $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
  1326.     $this->_retvalue[= array('pi' => $this->yystack[$this->yyidx + -1]->minor'definition' => $this->yystack[$this->yyidx + 0]->minor);
  1327.     }
  1328. #line 1334 "Parser.php"
  1329. #line 475 "Parser.y"
  1330.     function yy_r11(){
  1331.     $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor => $this->yystack[$this->yyidx + 0]->minor);
  1332.     // reset internal indicator of where we are in a pattern
  1333.     $this->_patternIndex = 0;
  1334.     }
  1335. #line 1341 "Parser.php"
  1336. #line 480 "Parser.y"
  1337.     function yy_r12(){
  1338.     $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
  1339.     if (isset($this->_retvalue[$this->yystack[$this->yyidx + -1]->minor])) {
  1340.         throw new Exception('Pattern "' $this->yystack[$this->yyidx + -1]->minor . '" is already defined as "' .
  1341.             $this->_retvalue[$this->yystack[$this->yyidx + -1]->minor'", cannot redefine as "' $this->yystack[$this->yyidx + 0]->minor->string . '"');
  1342.     }
  1343.     $this->_retvalue[$this->yystack[$this->yyidx + -1]->minor$this->yystack[$this->yyidx + 0]->minor;
  1344.     // reset internal indicator of where we are in a pattern declaration
  1345.     $this->_patternIndex = 0;
  1346.     }
  1347. #line 1353 "Parser.php"
  1348. #line 491 "Parser.y"
  1349.     function yy_r13(){
  1350.     $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -1]->minor'code' => '''statename' => ''));
  1351.     }
  1352. #line 1358 "Parser.php"
  1353. #line 494 "Parser.y"
  1354.     function yy_r14(){
  1355.     if ($this->yystack[$this->yyidx + -3]->minor != 'statename'{
  1356.         throw new Exception('Error: only %statename processing instruction ' .
  1357.             'is allowed in rule sections');
  1358.     }
  1359.     $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -1]->minor'code' => '''statename' => $this->yystack[$this->yyidx + -2]->minor));
  1360.     }
  1361. #line 1367 "Parser.php"
  1362. #line 501 "Parser.y"
  1363.     function yy_r15(){
  1364.     $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -2]->minor'code' => $this->yystack[$this->yyidx + 0]->minor'statename' => ''));
  1365.     }
  1366. #line 1372 "Parser.php"
  1367. #line 504 "Parser.y"
  1368.     function yy_r16(){
  1369.     if ($this->yystack[$this->yyidx + -4]->minor != 'statename'{
  1370.         throw new Exception('Error: only %statename processing instruction ' .
  1371.             'is allowed in rule sections');
  1372.     }
  1373.     $this->_retvalue = array(array('rules' => $this->yystack[$this->yyidx + -2]->minor'code' => $this->yystack[$this->yyidx + 0]->minor'statename' => $this->yystack[$this->yyidx + -3]->minor));
  1374.     $this->_patternIndex = 1;
  1375.     }
  1376. #line 1382 "Parser.php"
  1377. #line 512 "Parser.y"
  1378.     function yy_r17(){
  1379.     $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
  1380.     $this->_retvalue[= array('rules' => $this->yystack[$this->yyidx + -1]->minor'code' => '''statename' => '');
  1381.     $this->_patternIndex = 1;
  1382.     }
  1383. #line 1389 "Parser.php"
  1384. #line 517 "Parser.y"
  1385.     function yy_r18(){
  1386.     if ($this->yystack[$this->yyidx + -3]->minor != 'statename'{
  1387.         throw new Exception('Error: only %statename processing instruction ' .
  1388.             'is allowed in rule sections');
  1389.     }
  1390.     $this->_retvalue = $this->yystack[$this->yyidx + -4]->minor;
  1391.     $this->_retvalue[= array('rules' => $this->yystack[$this->yyidx + -1]->minor'code' => '''statename' => $this->yystack[$this->yyidx + -2]->minor);
  1392.     }
  1393. #line 1399 "Parser.php"
  1394. #line 525 "Parser.y"
  1395.     function yy_r19(){
  1396.     $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor;
  1397.     $this->_retvalue[= array('rules' => $this->yystack[$this->yyidx + -2]->minor'code' => $this->yystack[$this->yyidx + 0]->minor'statename' => '');
  1398.     }
  1399. #line 1405 "Parser.php"
  1400. #line 529 "Parser.y"
  1401.     function yy_r20(){
  1402.     if ($this->yystack[$this->yyidx + -4]->minor != 'statename'{
  1403.         throw new Exception('Error: only %statename processing instruction ' .
  1404.             'is allowed in rule sections');
  1405.     }
  1406.     $this->_retvalue = $this->yystack[$this->yyidx + -5]->minor;
  1407.     $this->_retvalue[= array('rules' => $this->yystack[$this->yyidx + -2]->minor'code' => $this->yystack[$this->yyidx + 0]->minor'statename' => $this->yystack[$this->yyidx + -3]->minor);
  1408.     }
  1409. #line 1415 "Parser.php"
  1410. #line 538 "Parser.y"
  1411.     function yy_r21(){
  1412.     $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
  1413.     $this->_patternIndex = 1;
  1414.     }
  1415. #line 1421 "Parser.php"
  1416. #line 543 "Parser.y"
  1417.     function yy_r22(){
  1418.     $name $this->yystack[$this->yyidx + -1]->minor[1];
  1419.     $this->yystack[$this->yyidx + -1]->minor = $this->yystack[$this->yyidx + -1]->minor[0];
  1420.     $this->yystack[$this->yyidx + -1]->minor = $this->_validatePattern($this->yystack[$this->yyidx + -1]->minor);
  1421.     $this->_patternIndex += $this->yystack[$this->yyidx + -1]->minor['subpatterns'+ 1;
  1422.     if (@preg_match('/' str_replace('/''\\/'$this->yystack[$this->yyidx + -1]->minor['pattern']'/''')) {
  1423.         $this->error('Rule "' $name '" can match the empty string, this will break lexing');
  1424.     }
  1425.     $this->_retvalue = array(array('pattern' => str_replace('/''\\/'$this->yystack[$this->yyidx + -1]->minor->string)'code' => $this->yystack[$this->yyidx + 0]->minor'subpatterns' => $this->yystack[$this->yyidx + -1]->minor['subpatterns']));
  1426.     }
  1427. #line 1433 "Parser.php"
  1428. #line 553 "Parser.y"
  1429.     function yy_r23(){
  1430.     $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
  1431.     $name $this->yystack[$this->yyidx + -1]->minor[1];
  1432.     $this->yystack[$this->yyidx + -1]->minor = $this->yystack[$this->yyidx + -1]->minor[0];
  1433.     $this->yystack[$this->yyidx + -1]->minor = $this->_validatePattern($this->yystack[$this->yyidx + -1]->minor);
  1434.     $this->_patternIndex += $this->yystack[$this->yyidx + -1]->minor['subpatterns'+ 1;
  1435.     if (@preg_match('/' str_replace('/''\\/'$this->yystack[$this->yyidx + -1]->minor['pattern']'/''')) {
  1436.         $this->error('Rule "' $name '" can match the empty string, this will break lexing');
  1437.     }
  1438.     $this->_retvalue[= array('pattern' => str_replace('/''\\/'$this->yystack[$this->yyidx + -1]->minor->string)'code' => $this->yystack[$this->yyidx + 0]->minor'subpatterns' => $this->yystack[$this->yyidx + -1]->minor['subpatterns']);
  1439.     }
  1440. #line 1446 "Parser.php"
  1441. #line 565 "Parser.y"
  1442.     function yy_r24(){
  1443.     $this->_retvalue = array(preg_quote($this->yystack[$this->yyidx + 0]->minor'/')$this->yystack[$this->yyidx + 0]->minor);
  1444.     }
  1445. #line 1451 "Parser.php"
  1446. #line 568 "Parser.y"
  1447.     function yy_r25(){
  1448.     if (!isset($this->patterns[$this->yystack[$this->yyidx + 0]->minor])) {
  1449.         $this->error('Undefined pattern "' $this->yystack[$this->yyidx + 0]->minor . '" used in rules');
  1450.         throw new Exception('Undefined pattern "' $this->yystack[$this->yyidx + 0]->minor . '" used in rules');
  1451.     }
  1452.     $this->_retvalue = array($this->patterns[$this->yystack[$this->yyidx + 0]->minor]$this->yystack[$this->yyidx + 0]->minor);
  1453.     }
  1454. #line 1460 "Parser.php"
  1455. #line 575 "Parser.y"
  1456.     function yy_r26(){
  1457.     $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor[0preg_quote($this->yystack[$this->yyidx + 0]->minor'/')$this->yystack[$this->yyidx + -1]->minor[1' ' $this->yystack[$this->yyidx + 0]->minor);
  1458.     }
  1459. #line 1465 "Parser.php"
  1460. #line 578 "Parser.y"
  1461.     function yy_r27(){
  1462.     if (!isset($this->patterns[$this->yystack[$this->yyidx + 0]->minor])) {
  1463.         $this->error('Undefined pattern "' $this->yystack[$this->yyidx + 0]->minor . '" used in rules');
  1464.         throw new Exception('Undefined pattern "' $this->yystack[$this->yyidx + 0]->minor . '" used in rules');
  1465.     }
  1466.     $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor[0$this->patterns[$this->yystack[$this->yyidx + 0]->minor]$this->yystack[$this->yyidx + -1]->minor[1' ' $this->yystack[$this->yyidx + 0]->minor);
  1467.     }
  1468. #line 1474 "Parser.php"
  1469. #line 586 "Parser.y"
  1470.     function yy_r28(){
  1471.     $this->_retvalue = preg_quote($this->yystack[$this->yyidx + 0]->minor'/');
  1472.     }
  1473. #line 1479 "Parser.php"
  1474. #line 589 "Parser.y"
  1475.     function yy_r29(){
  1476.     // increment internal sub-pattern counter
  1477.     // adjust back-references in pattern based on previous pattern
  1478.     $test $this->_validatePattern($this->yystack[$this->yyidx + 0]->minortrue);
  1479.     $this->_patternIndex += $test['subpatterns'];
  1480.     $this->_retvalue = $test['pattern'];
  1481.     }
  1482. #line 1488 "Parser.php"
  1483. #line 596 "Parser.y"
  1484.     function yy_r30(){
  1485.     $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . preg_quote($this->yystack[$this->yyidx + 0]->minor'/');
  1486.     }
  1487. #line 1493 "Parser.php"
  1488. #line 599 "Parser.y"
  1489.     function yy_r31(){
  1490.     // increment internal sub-pattern counter
  1491.     // adjust back-references in pattern based on previous pattern
  1492.     $test $this->_validatePattern($this->yystack[$this->yyidx + 0]->minortrue);
  1493.     $this->_patternIndex += $test['subpatterns'];
  1494.     $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . $test['pattern'];
  1495.     }
  1496. #line 1502 "Parser.php"
  1497.  
  1498.     /**
  1499.      * placeholder for the left hand side in a reduce operation.
  1500.      * 
  1501.      * For a parser with a rule like this:
  1502.      * <pre>
  1503.      * rule(A) ::= B. { A = 1; }
  1504.      * </pre>
  1505.      * 
  1506.      * The parser will translate to something like:
  1507.      * 
  1508.      * <code>
  1509.      * function yy_r0(){$this->_retvalue = 1;}
  1510.      * </code>
  1511.      */
  1512.     private $_retvalue;
  1513.  
  1514.     /**
  1515.      * Perform a reduce action and the shift that must immediately
  1516.      * follow the reduce.
  1517.      * 
  1518.      * For a rule such as:
  1519.      * 
  1520.      * <pre>
  1521.      * A ::= B blah C. { dosomething(); }
  1522.      * </pre>
  1523.      * 
  1524.      * This function will first call the action, if any, ("dosomething();" in our
  1525.      * example), and then it will pop three states from the stack,
  1526.      * one for each entry on the right-hand side of the expression
  1527.      * (B, blah, and C in our example rule), and then push the result of the action
  1528.      * back on to the stack with the resulting state reduced to (as described in the .out
  1529.      * file)
  1530.      * @param int Number of the rule by which to reduce
  1531.      */
  1532.     function yy_reduce($yyruleno)
  1533.     {
  1534.         //int $yygoto;                     /* The next state */
  1535.         //int $yyact;                      /* The next action */
  1536.         //mixed $yygotominor;        /* The LHS of the rule reduced */
  1537.         //PHP_LexerGenerator_ParseryyStackEntry $yymsp;            /* The top of the parser's stack */
  1538.         //int $yysize;                     /* Amount to pop the stack */
  1539.         $yymsp $this->yystack[$this->yyidx];
  1540.         if (self::$yyTraceFILE && $yyruleno >= 0 
  1541.               && $yyruleno < count(self::$yyRuleName)) {
  1542.             fprintf(self::$yyTraceFILE"%sReduce (%d) [%s].\n",
  1543.                 self::$yyTracePrompt$yyruleno,
  1544.                 self::$yyRuleName[$yyruleno]);
  1545.         }
  1546.  
  1547.         $this->_retvalue = $yy_lefthand_side = null;
  1548.         if (array_key_exists($yyrulenoself::$yyReduceMap)) {
  1549.             // call the action
  1550.             $this->_retvalue = null;
  1551.             $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}();
  1552.             $yy_lefthand_side $this->_retvalue;
  1553.         }
  1554.         $yygoto = self::$yyRuleInfo[$yyruleno]['lhs'];
  1555.         $yysize = self::$yyRuleInfo[$yyruleno]['rhs'];
  1556.         $this->yyidx -= $yysize;
  1557.         for($i $yysize$i$i--{
  1558.             // pop all of the right-hand side parameters
  1559.             array_pop($this->yystack);
  1560.         }
  1561.         $yyact $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno$yygoto);
  1562.         if ($yyact < self::YYNSTATE{
  1563.             /* If we are not debugging and the reduce action popped at least
  1564.             ** one element off the stack, then we can push the new element back
  1565.             ** onto the stack here, and skip the stack overflow test in yy_shift().
  1566.             ** That gives a significant speed improvement. */
  1567.             if (!self::$yyTraceFILE && $yysize{
  1568.                 $this->yyidx++;
  1569.                 $x = new PHP_LexerGenerator_ParseryyStackEntry;
  1570.                 $x->stateno = $yyact;
  1571.                 $x->major = $yygoto;
  1572.                 $x->minor = $yy_lefthand_side;
  1573.                 $this->yystack[$this->yyidx$x;
  1574.             else {
  1575.                 $this->yy_shift($yyact$yygoto$yy_lefthand_side);
  1576.             }
  1577.         elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1{
  1578.             $this->yy_accept();
  1579.         }
  1580.     }
  1581.  
  1582.     /**
  1583.      * The following code executes when the parse fails
  1584.      * 
  1585.      * Code from %parse_fail is inserted here
  1586.      */
  1587.     function yy_parse_failed()
  1588.     {
  1589.         if (self::$yyTraceFILE{
  1590.             fprintf(self::$yyTraceFILE"%sFail!\n"self::$yyTracePrompt);
  1591.         }
  1592.         while ($this->yyidx >= 0{
  1593.             $this->yy_pop_parser_stack();
  1594.         }
  1595.         /* Here code is inserted which will be executed whenever the
  1596.         ** parser fails */
  1597.     }
  1598.  
  1599.     /**
  1600.      * The following code executes when a syntax error first occurs.
  1601.      * 
  1602.      * %syntax_error code is inserted here
  1603.      * @param int The major type of the error token
  1604.      * @param mixed The minor type of the error token
  1605.      */
  1606.     function yy_syntax_error($yymajor$TOKEN)
  1607.     {
  1608. #line 70 "Parser.y"
  1609.  
  1610.     echo "Syntax Error on line " $this->lex->line . ": token '" 
  1611.         $this->lex->value . "' while parsing rule:";
  1612.     foreach ($this->yystack as $entry{
  1613.         echo $this->tokenName($entry->major' ';
  1614.     }
  1615.     foreach ($this->yy_get_expected_tokens($yymajoras $token{
  1616.         $expect[= self::$yyTokenName[$token];
  1617.     }
  1618.     throw new Exception('Unexpected ' $this->tokenName($yymajor'(' $TOKEN
  1619.         . '), expected one of: ' implode(','$expect));
  1620. #line 1627 "Parser.php"
  1621.     }
  1622.  
  1623.     /**
  1624.      * The following is executed when the parser accepts
  1625.      * 
  1626.      * %parse_accept code is inserted here
  1627.      */
  1628.     function yy_accept()
  1629.     {
  1630.         if (self::$yyTraceFILE{
  1631.             fprintf(self::$yyTraceFILE"%sAccept!\n"self::$yyTracePrompt);
  1632.         }
  1633.         while ($this->yyidx >= 0{
  1634.             $stack $this->yy_pop_parser_stack();
  1635.         }
  1636.         /* Here code is inserted which will be executed whenever the
  1637.         ** parser accepts */
  1638.     }
  1639.  
  1640.     /**
  1641.      * The main parser program.
  1642.      * 
  1643.      * The first argument is the major token number.  The second is
  1644.      * the token value string as scanned from the input.
  1645.      *
  1646.      * @param int the token number
  1647.      * @param mixed the token value
  1648.      * @param mixed any extra arguments that should be passed to handlers
  1649.      */
  1650.     function doParse($yymajor$yytokenvalue)
  1651.     {
  1652. //        $yyact;            /* The parser action. */
  1653. //        $yyendofinput;     /* True if we are at the end of input */
  1654.         $yyerrorhit = 0;   /* True if yymajor has invoked an error */
  1655.         
  1656.         /* (re)initialize the parser, if necessary */
  1657.         if ($this->yyidx === null || $this->yyidx < 0{
  1658.             /* if ($yymajor == 0) return; // not sure why this was here... */
  1659.             $this->yyidx = 0;
  1660.             $this->yyerrcnt = -1;
  1661.             $x = new PHP_LexerGenerator_ParseryyStackEntry;
  1662.             $x->stateno = 0;
  1663.             $x->major = 0;
  1664.             $this->yystack = array();
  1665.             array_push($this->yystack$x);
  1666.         }
  1667.         $yyendofinput ($yymajor==0);
  1668.         
  1669.         if (self::$yyTraceFILE{
  1670.             fprintf(self::$yyTraceFILE"%sInput %s\n",
  1671.                 self::$yyTracePromptself::$yyTokenName[$yymajor]);
  1672.         }
  1673.         
  1674.         do {
  1675.             $yyact $this->yy_find_shift_action($yymajor);
  1676.             if ($yymajor < self::YYERRORSYMBOL &&
  1677.                   !$this->yy_is_expected_token($yymajor)) {
  1678.                 // force a syntax error
  1679.                 $yyact = self::YY_ERROR_ACTION;
  1680.             }
  1681.             if ($yyact < self::YYNSTATE{
  1682.                 $this->yy_shift($yyact$yymajor$yytokenvalue);
  1683.                 $this->yyerrcnt--;
  1684.                 if ($yyendofinput && $this->yyidx >= 0{
  1685.                     $yymajor = 0;
  1686.                 else {
  1687.                     $yymajor = self::YYNOCODE;
  1688.                 }
  1689.             elseif ($yyact < self::YYNSTATE + self::YYNRULE{
  1690.                 $this->yy_reduce($yyact - self::YYNSTATE);
  1691.             elseif ($yyact == self::YY_ERROR_ACTION{
  1692.                 if (self::$yyTraceFILE{
  1693.                     fprintf(self::$yyTraceFILE"%sSyntax Error!\n",
  1694.                         self::$yyTracePrompt);
  1695.                 }
  1696.                 if (self::YYERRORSYMBOL{
  1697.                     /* A syntax error has occurred.
  1698.                     ** The response to an error depends upon whether or not the
  1699.                     ** grammar defines an error token "ERROR".  
  1700.                     **
  1701.                     ** This is what we do if the grammar does define ERROR:
  1702.                     **
  1703.                     **  * Call the %syntax_error function.
  1704.                     **
  1705.                     **  * Begin popping the stack until we enter a state where
  1706.                     **    it is legal to shift the error symbol, then shift
  1707.                     **    the error symbol.
  1708.                     **
  1709.                     **  * Set the error count to three.
  1710.                     **
  1711.                     **  * Begin accepting and shifting new tokens.  No new error
  1712.                     **    processing will occur until three tokens have been
  1713.                     **    shifted successfully.
  1714.                     **
  1715.                     */
  1716.                     if ($this->yyerrcnt < 0{
  1717.                         $this->yy_syntax_error($yymajor$yytokenvalue);
  1718.                     }
  1719.                     $yymx $this->yystack[$this->yyidx]->major;
  1720.                     if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){
  1721.                         if (self::$yyTraceFILE{
  1722.                             fprintf(self::$yyTraceFILE"%sDiscard input token %s\n",
  1723.                                 self::$yyTracePromptself::$yyTokenName[$yymajor]);
  1724.                         }
  1725.                         $this->yy_destructor($yymajor$yytokenvalue);
  1726.                         $yymajor = self::YYNOCODE;
  1727.                     else {
  1728.                         while ($this->yyidx >= 0 &&
  1729.                                  $yymx != self::YYERRORSYMBOL &&
  1730.         ($yyact $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
  1731.                               ){
  1732.                             $this->yy_pop_parser_stack();
  1733.                         }
  1734.                         if ($this->yyidx < 0 || $yymajor==0{
  1735.                             $this->yy_destructor($yymajor$yytokenvalue);
  1736.                             $this->yy_parse_failed();
  1737.                             $yymajor = self::YYNOCODE;
  1738.                         elseif ($yymx != self::YYERRORSYMBOL{
  1739.                             $u2 = 0;
  1740.                             $this->yy_shift($yyactself::YYERRORSYMBOL$u2);
  1741.                         }
  1742.                     }
  1743.                     $this->yyerrcnt = 3;
  1744.                     $yyerrorhit = 1;
  1745.                 else {
  1746.                     /* YYERRORSYMBOL is not defined */
  1747.                     /* This is what we do if the grammar does not define ERROR:
  1748.                     **
  1749.                     **  * Report an error message, and throw away the input token.
  1750.                     **
  1751.                     **  * If the input token is $, then fail the parse.
  1752.                     **
  1753.                     ** As before, subsequent error messages are suppressed until
  1754.                     ** three input tokens have been successfully shifted.
  1755.                     */
  1756.                     if ($this->yyerrcnt <= 0{
  1757.                         $this->yy_syntax_error($yymajor$yytokenvalue);
  1758.                     }
  1759.                     $this->yyerrcnt = 3;
  1760.                     $this->yy_destructor($yymajor$yytokenvalue);
  1761.                     if ($yyendofinput{
  1762.                         $this->yy_parse_failed();
  1763.                     }
  1764.                     $yymajor = self::YYNOCODE;
  1765.                 }
  1766.             else {
  1767.                 $this->yy_accept();
  1768.                 $yymajor = self::YYNOCODE;
  1769.             }            
  1770.         while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
  1771.     }
  1772. }

Documentation generated on Mon, 11 Mar 2019 14:46:16 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.