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

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