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

Documentation generated on Mon, 11 Mar 2019 15:04:57 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.