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

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