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

Source for file Lempar.php

Documentation is available at Lempar.php

  1. <?php
  2. /* Driver template for the PHP_ParserGenerator 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 ParseyyToken implements ArrayAccess
  12. {
  13.     public $string '';
  14.     public $metadata = array();
  15.  
  16.     function __construct($s$m = array())
  17.     {
  18.         if ($s instanceof ParseyyToken{
  19.             $this->string $s->string;
  20.             $this->metadata $s->metadata;
  21.         else {
  22.             $this->string = (string) $s;
  23.             if ($m instanceof ParseyyToken{
  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 ParseyyToken?
  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 ParseyyToken{
  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 ParseyyStackEntry
  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. %%
  98.  
  99. // declare_class is output here
  100. %%
  101. {
  102. /* First off, code is included which follows the "include_class" declaration
  103. ** in the input file. */
  104. %%
  105.  
  106. /* Next is all token values, as class constants
  107. */
  108. /* 
  109. ** These constants (all generated automatically by the parser generator)
  110. ** specify the various kinds of tokens (terminals) that the parser
  111. ** understands. 
  112. **
  113. ** Each symbol here is a terminal symbol in the grammar.
  114. */
  115. %%
  116.  
  117. /* Next are that tables used to determine what action to take based on the
  118. ** current state and lookahead token.  These tables are used to implement
  119. ** functions that take a state number and lookahead value and return an
  120. ** action integer.  
  121. **
  122. ** Suppose the action integer is N.  Then the action is determined as
  123. ** follows
  124. **
  125. **   0 <= N < self::YYNSTATE                              Shift N.  That is,
  126. **                                                        push the lookahead
  127. **                                                        token onto the stack
  128. **                                                        and goto state N.
  129. **
  130. **   self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE   Reduce by rule N-YYNSTATE.
  131. **
  132. **   N == self::YYNSTATE+self::YYNRULE                    A syntax error has occurred.
  133. **
  134. **   N == self::YYNSTATE+self::YYNRULE+1                  The parser accepts its
  135. **                                                        input. (and concludes parsing)
  136. **
  137. **   N == self::YYNSTATE+self::YYNRULE+2                  No such action.  Denotes unused
  138. **                                                        slots in the yy_action[] table.
  139. **
  140. ** The action table is constructed as a single large static array $yy_action.
  141. ** Given state S and lookahead X, the action is computed as
  142. **
  143. **      self::$yy_action[self::$yy_shift_ofst[S] + X ]
  144. **
  145. ** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value
  146. ** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if
  147. ** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that
  148. ** the action is not in the table and that self::$yy_default[S] should be used instead.  
  149. **
  150. ** The formula above is for computing the action when the lookahead is
  151. ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
  152. ** a reduce action) then the static $yy_reduce_ofst array is used in place of
  153. ** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of
  154. ** self::YY_SHIFT_USE_DFLT.
  155. **
  156. ** The following are the tables generated in this section:
  157. **
  158. **  self::$yy_action        A single table containing all actions.
  159. **  self::$yy_lookahead     A table containing the lookahead for each entry in
  160. **                          yy_action.  Used to detect hash collisions.
  161. **  self::$yy_shift_ofst    For each state, the offset into self::$yy_action for
  162. **                          shifting terminals.
  163. **  self::$yy_reduce_ofst   For each state, the offset into self::$yy_action for
  164. **                          shifting non-terminals after a reduce.
  165. **  self::$yy_default       Default action for each state.
  166. */
  167. %%
  168. /* The next thing included is series of defines which control
  169. ** various aspects of the generated parser.
  170. **    self::YYNOCODE      is a number which corresponds
  171. **                        to no legal terminal or nonterminal number.  This
  172. **                        number is used to fill in empty slots of the hash 
  173. **                        table.
  174. **    self::YYFALLBACK    If defined, this indicates that one or more tokens
  175. **                        have fall-back values which should be used if the
  176. **                        original value of the token will not parse.
  177. **    self::YYSTACKDEPTH  is the maximum depth of the parser's stack.
  178. **    self::YYNSTATE      the combined number of states.
  179. **    self::YYNRULE       the number of rules in the grammar
  180. **    self::YYERRORSYMBOL is the code number of the error symbol.  If not
  181. **                        defined, then do no error processing.
  182. */
  183. %%
  184.     /** The next table maps tokens into fallback tokens.  If a construct
  185.      * like the following:
  186.      * 
  187.      *      %fallback ID X Y Z.
  188.      *
  189.      * appears in the grammer, then ID becomes a fallback token for X, Y,
  190.      * and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
  191.      * but it does not parse, the type of the token is changed to ID and
  192.      * the parse is retried before an error is thrown.
  193.      */
  194.     static public $yyFallback = array(
  195. %%
  196.     );
  197.     /**
  198.      * Turn parser tracing on by giving a stream to which to write the trace
  199.      * and a prompt to preface each trace message.  Tracing is turned off
  200.      * by making either argument NULL
  201.      *
  202.      * Inputs:
  203.      * 
  204.      * - A stream resource to which trace output should be written.
  205.      *   If NULL, then tracing is turned off.
  206.      * - A prefix string written at the beginning of every
  207.      *   line of trace output.  If NULL, then tracing is
  208.      *   turned off.
  209.      *
  210.      * Outputs:
  211.      * 
  212.      * - None.
  213.      * @param resource 
  214.      * @param string 
  215.      */
  216.     static function Trace($TraceFILE$zTracePrompt)
  217.     {
  218.         if (!$TraceFILE{
  219.             $zTracePrompt = 0;
  220.         elseif (!$zTracePrompt{
  221.             $TraceFILE = 0;
  222.         }
  223.         self::$yyTraceFILE $TraceFILE;
  224.         self::$yyTracePrompt $zTracePrompt;
  225.     }
  226.  
  227.     /**
  228.      * Output debug information to output (php://output stream)
  229.      */
  230.     static function PrintTrace()
  231.     {
  232.         self::$yyTraceFILE = fopen('php://output''w');
  233.         self::$yyTracePrompt '';
  234.     }
  235.  
  236.     /**
  237.      * @var resource|0
  238.      */
  239.     static public $yyTraceFILE;
  240.     /**
  241.      * String to prepend to debug output
  242.      * @var string|0
  243.      */
  244.     static public $yyTracePrompt;
  245.     /**
  246.      * @var int 
  247.      */
  248.     public $yyidx = -1;                    /* Index of top element in stack */
  249.     /**
  250.      * @var int 
  251.      */
  252.     public $yyerrcnt;                 /* Shifts left before out of the error */
  253.     /**
  254.      * @var array 
  255.      */
  256.     public $yystack = array();  /* The parser's stack */
  257.  
  258.     /**
  259.      * For tracing shifts, the names of all terminals and nonterminals
  260.      * are required.  The following table supplies these names
  261.      * @var array 
  262.      */
  263.     static public $yyTokenName = array
  264. %%
  265.     );
  266.  
  267.     /**
  268.      * For tracing reduce actions, the names of all rules are required.
  269.      * @var array 
  270.      */
  271.     static public $yyRuleName = array(
  272. %%
  273.     );
  274.  
  275.     /**
  276.      * This function returns the symbolic name associated with a token
  277.      * value.
  278.      * @param int 
  279.      * @return string 
  280.      */
  281.     function tokenName($tokenType)
  282.     {
  283.         if ($tokenType === 0{
  284.             return 'End of Input';
  285.         }
  286.         if ($tokenType > 0 && $tokenType count(self::$yyTokenName)) {
  287.             return self::$yyTokenName[$tokenType];
  288.         else {
  289.             return "Unknown";
  290.         }
  291.     }
  292.  
  293.     /**
  294.      * The following function deletes the value associated with a
  295.      * symbol.  The symbol can be either a terminal or nonterminal.
  296.      * @param int the symbol code
  297.      * @param mixed the symbol's value
  298.      */
  299.     static function yy_destructor($yymajor$yypminor)
  300.     {
  301.         switch ($yymajor{
  302.         /* Here is inserted the actions which take place when a
  303.         ** terminal or non-terminal is destroyed.  This can happen
  304.         ** when the symbol is popped from the stack during a
  305.         ** reduce or during error processing or when a parser is 
  306.         ** being destroyed before it is finished parsing.
  307.         **
  308.         ** Note: during a reduce, the only symbols destroyed are those
  309.         ** which appear on the RHS of the rule, but which are not used
  310.         ** inside the C code.
  311.         */
  312. %%
  313.             default:  break;   /* If no destructor action specified: do nothing */
  314.         }
  315.     }
  316.  
  317.     /**
  318.      * Pop the parser's stack once.
  319.      *
  320.      * If there is a destructor routine associated with the token which
  321.      * is popped from the stack, then call it.
  322.      *
  323.      * Return the major token number for the symbol popped.
  324.      * @param ParseyyParser 
  325.      * @return int 
  326.      */
  327.     function yy_pop_parser_stack()
  328.     {
  329.         if (!count($this->yystack)) {
  330.             return;
  331.         }
  332.         $yytos array_pop($this->yystack);
  333.         if (self::$yyTraceFILE && $this->yyidx >= 0{
  334.             fwrite(self::$yyTraceFILE,
  335.                 self::$yyTracePrompt 'Popping ' . self::$yyTokenName[$yytos->major.
  336.                     "\n");
  337.         }
  338.         $yymajor $yytos->major;
  339.         self::yy_destructor($yymajor$yytos->minor);
  340.         $this->yyidx--;
  341.         return $yymajor;
  342.     }
  343.  
  344.     /**
  345.      * Deallocate and destroy a parser.  Destructors are all called for
  346.      * all stack elements before shutting the parser down.
  347.      */
  348.     function __destruct()
  349.     {
  350.         while ($this->yyidx >= 0{
  351.             $this->yy_pop_parser_stack();
  352.         }
  353.         if (is_resource(self::$yyTraceFILE)) {
  354.             fclose(self::$yyTraceFILE);
  355.         }
  356.     }
  357.  
  358.     /**
  359.      * Based on the current state and parser stack, get a list of all
  360.      * possible lookahead tokens
  361.      * @param int 
  362.      * @return array 
  363.      */
  364.     function yy_get_expected_tokens($token)
  365.     {
  366.         $state $this->yystack[$this->yyidx]->stateno;
  367.         $expected = self::$yyExpectedTokens[$state];
  368.         if (in_array($tokenself::$yyExpectedTokens[$state]true)) {
  369.             return $expected;
  370.         }
  371.         $stack $this->yystack;
  372.         $yyidx $this->yyidx;
  373.         do {
  374.             $yyact $this->yy_find_shift_action($token);
  375.             if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE{
  376.                 // reduce action
  377.                 $done = 0;
  378.                 do {
  379.                     if ($done++ == 100{
  380.                         $this->yyidx = $yyidx;
  381.                         $this->yystack = $stack;
  382.                         // too much recursion prevents proper detection
  383.                         // so give up
  384.                         return array_unique($expected);
  385.                     }
  386.                     $yyruleno $yyact - self::YYNSTATE;
  387.                     $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
  388.                     $nextstate $this->yy_find_reduce_action(
  389.                         $this->yystack[$this->yyidx]->stateno,
  390.                         self::$yyRuleInfo[$yyruleno]['lhs']);
  391.                     if (isset(self::$yyExpectedTokens[$nextstate])) {
  392.                         $expected += self::$yyExpectedTokens[$nextstate];
  393.                             if (in_array($token,
  394.                                   self::$yyExpectedTokens[$nextstate]true)) {
  395.                             $this->yyidx = $yyidx;
  396.                             $this->yystack = $stack;
  397.                             return array_unique($expected);
  398.                         }
  399.                     }
  400.                     if ($nextstate < self::YYNSTATE{
  401.                         // we need to shift a non-terminal
  402.                         $this->yyidx++;
  403.                         $x = new ParseyyStackEntry;
  404.                         $x->stateno = $nextstate;
  405.                         $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
  406.                         $this->yystack[$this->yyidx$x;
  407.                         continue 2;
  408.                     elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1{
  409.                         $this->yyidx = $yyidx;
  410.                         $this->yystack = $stack;
  411.                         // the last token was just ignored, we can't accept
  412.                         // by ignoring input, this is in essence ignoring a
  413.                         // syntax error!
  414.                         return array_unique($expected);
  415.                     elseif ($nextstate === self::YY_NO_ACTION{
  416.                         $this->yyidx = $yyidx;
  417.                         $this->yystack = $stack;
  418.                         // input accepted, but not shifted (I guess)
  419.                         return $expected;
  420.                     else {
  421.                         $yyact $nextstate;
  422.                     }
  423.                 while (true);
  424.             }
  425.             break;
  426.         while (true);
  427.         return array_unique($expected);
  428.     }
  429.  
  430.     /**
  431.      * Based on the parser state and current parser stack, determine whether
  432.      * the lookahead token is possible.
  433.      * 
  434.      * The parser will convert the token value to an error token if not.  This
  435.      * catches some unusual edge cases where the parser would fail.
  436.      * @param int 
  437.      * @return bool 
  438.      */
  439.     function yy_is_expected_token($token)
  440.     {
  441.         if ($token === 0{
  442.             return true; // 0 is not part of this
  443.         }
  444.         $state $this->yystack[$this->yyidx]->stateno;
  445.         if (in_array($tokenself::$yyExpectedTokens[$state]true)) {
  446.             return true;
  447.         }
  448.         $stack $this->yystack;
  449.         $yyidx $this->yyidx;
  450.         do {
  451.             $yyact $this->yy_find_shift_action($token);
  452.             if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE{
  453.                 // reduce action
  454.                 $done = 0;
  455.                 do {
  456.                     if ($done++ == 100{
  457.                         $this->yyidx = $yyidx;
  458.                         $this->yystack = $stack;
  459.                         // too much recursion prevents proper detection
  460.                         // so give up
  461.                         return true;
  462.                     }
  463.                     $yyruleno $yyact - self::YYNSTATE;
  464.                     $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
  465.                     $nextstate $this->yy_find_reduce_action(
  466.                         $this->yystack[$this->yyidx]->stateno,
  467.                         self::$yyRuleInfo[$yyruleno]['lhs']);
  468.                     if (isset(self::$yyExpectedTokens[$nextstate]&&
  469.                           in_array($tokenself::$yyExpectedTokens[$nextstate]true)) {
  470.                         $this->yyidx = $yyidx;
  471.                         $this->yystack = $stack;
  472.                         return true;
  473.                     }
  474.                     if ($nextstate < self::YYNSTATE{
  475.                         // we need to shift a non-terminal
  476.                         $this->yyidx++;
  477.                         $x = new ParseyyStackEntry;
  478.                         $x->stateno = $nextstate;
  479.                         $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
  480.                         $this->yystack[$this->yyidx$x;
  481.                         continue 2;
  482.                     elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1{
  483.                         $this->yyidx = $yyidx;
  484.                         $this->yystack = $stack;
  485.                         if (!$token{
  486.                             // end of input: this is valid
  487.                             return true;
  488.                         }
  489.                         // the last token was just ignored, we can't accept
  490.                         // by ignoring input, this is in essence ignoring a
  491.                         // syntax error!
  492.                         return false;
  493.                     elseif ($nextstate === self::YY_NO_ACTION{
  494.                         $this->yyidx = $yyidx;
  495.                         $this->yystack = $stack;
  496.                         // input accepted, but not shifted (I guess)
  497.                         return true;
  498.                     else {
  499.                         $yyact $nextstate;
  500.                     }
  501.                 while (true);
  502.             }
  503.             break;
  504.         while (true);
  505.         $this->yyidx = $yyidx;
  506.         $this->yystack = $stack;
  507.         return true;
  508.     }
  509.  
  510.     /**
  511.      * Find the appropriate action for a parser given the terminal
  512.      * look-ahead token iLookAhead.
  513.      *
  514.      * If the look-ahead token is YYNOCODE, then check to see if the action is
  515.      * independent of the look-ahead.  If it is, return the action, otherwise
  516.      * return YY_NO_ACTION.
  517.      * @param int The look-ahead token
  518.      */
  519.     function yy_find_shift_action($iLookAhead)
  520.     {
  521.         $stateno $this->yystack[$this->yyidx]->stateno;
  522.      
  523.         /* if ($this->yyidx < 0) return self::YY_NO_ACTION;  */
  524.         if (!isset(self::$yy_shift_ofst[$stateno])) {
  525.             // no shift actions
  526.             return self::$yy_default[$stateno];
  527.         }
  528.         $i = self::$yy_shift_ofst[$stateno];
  529.         if ($i === self::YY_SHIFT_USE_DFLT{
  530.             return self::$yy_default[$stateno];
  531.         }
  532.         if ($iLookAhead == self::YYNOCODE{
  533.             return self::YY_NO_ACTION;
  534.         }
  535.         $i += $iLookAhead;
  536.         if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
  537.               self::$yy_lookahead[$i!= $iLookAhead{
  538.             if (count(self::$yyFallback&& $iLookAhead < count(self::$yyFallback)
  539.                    && ($iFallback = self::$yyFallback[$iLookAhead]!= 0{
  540.                 if (self::$yyTraceFILE{
  541.                     fwrite(self::$yyTraceFILEself::$yyTracePrompt "FALLBACK " .
  542.                         self::$yyTokenName[$iLookAhead" => " .
  543.                         self::$yyTokenName[$iFallback"\n");
  544.                 }
  545.                 return $this->yy_find_shift_action($iFallback);
  546.             }
  547.             return self::$yy_default[$stateno];
  548.         else {
  549.             return self::$yy_action[$i];
  550.         }
  551.     }
  552.  
  553.     /**
  554.      * Find the appropriate action for a parser given the non-terminal
  555.      * look-ahead token $iLookAhead.
  556.      *
  557.      * If the look-ahead token is self::YYNOCODE, then check to see if the action is
  558.      * independent of the look-ahead.  If it is, return the action, otherwise
  559.      * return self::YY_NO_ACTION.
  560.      * @param int Current state number
  561.      * @param int The look-ahead token
  562.      */
  563.     function yy_find_reduce_action($stateno$iLookAhead)
  564.     {
  565.         /* $stateno = $this->yystack[$this->yyidx]->stateno; */
  566.  
  567.         if (!isset(self::$yy_reduce_ofst[$stateno])) {
  568.             return self::$yy_default[$stateno];
  569.         }
  570.         $i = self::$yy_reduce_ofst[$stateno];
  571.         if ($i == self::YY_REDUCE_USE_DFLT{
  572.             return self::$yy_default[$stateno];
  573.         }
  574.         if ($iLookAhead == self::YYNOCODE{
  575.             return self::YY_NO_ACTION;
  576.         }
  577.         $i += $iLookAhead;
  578.         if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
  579.               self::$yy_lookahead[$i!= $iLookAhead{
  580.             return self::$yy_default[$stateno];
  581.         else {
  582.             return self::$yy_action[$i];
  583.         }
  584.     }
  585.  
  586.     /**
  587.      * Perform a shift action.
  588.      * @param int The new state to shift in
  589.      * @param int The major token to shift in
  590.      * @param mixed the minor token to shift in
  591.      */
  592.     function yy_shift($yyNewState$yyMajor$yypMinor)
  593.     {
  594.         $this->yyidx++;
  595.         if ($this->yyidx >= self::YYSTACKDEPTH{
  596.             $this->yyidx--;
  597.             if (self::$yyTraceFILE{
  598.                 fprintf(self::$yyTraceFILE"%sStack Overflow!\n"self::$yyTracePrompt);
  599.             }
  600.             while ($this->yyidx >= 0{
  601.                 $this->yy_pop_parser_stack();
  602.             }
  603.             /* Here code is inserted which will execute if the parser
  604.             ** stack ever overflows */
  605. %%
  606.             return;
  607.         }
  608.         $yytos = new ParseyyStackEntry;
  609.         $yytos->stateno = $yyNewState;
  610.         $yytos->major = $yyMajor;
  611.         $yytos->minor = $yypMinor;
  612.         array_push($this->yystack$yytos);
  613.         if (self::$yyTraceFILE && $this->yyidx > 0{
  614.             fprintf(self::$yyTraceFILE"%sShift %d\n"self::$yyTracePrompt,
  615.                 $yyNewState);
  616.             fprintf(self::$yyTraceFILE"%sStack:"self::$yyTracePrompt);
  617.             for ($i = 1; $i <= $this->yyidx; $i++{
  618.                 fprintf(self::$yyTraceFILE" %s",
  619.                     self::$yyTokenName[$this->yystack[$i]->major]);
  620.             }
  621.             fwrite(self::$yyTraceFILE,"\n");
  622.         }
  623.     }
  624.  
  625.     /**
  626.      * The following table contains information about every rule that
  627.      * is used during the reduce.
  628.      *
  629.      * <pre>
  630.      * array(
  631.      *  array(
  632.      *   int $lhs;         Symbol on the left-hand side of the rule
  633.      *   int $nrhs;     Number of right-hand side symbols in the rule
  634.      *  ),...
  635.      * );
  636.      * </pre>
  637.      */
  638.     static public $yyRuleInfo = array(
  639. %%
  640.     );
  641.  
  642.     /**
  643.      * The following table contains a mapping of reduce action to method name
  644.      * that handles the reduction.
  645.      * 
  646.      * If a rule is not set, it has no handler.
  647.      */
  648.     static public $yyReduceMap = array(
  649. %%
  650.     );
  651.     /* Beginning here are the reduction cases.  A typical example
  652.     ** follows:
  653.     **  #line <lineno> <grammarfile>
  654.     **   function yy_r0($yymsp){ ... }           // User supplied code
  655.     **  #line <lineno> <thisfile>
  656.     */
  657. %%
  658.  
  659.     /**
  660.      * placeholder for the left hand side in a reduce operation.
  661.      * 
  662.      * For a parser with a rule like this:
  663.      * <pre>
  664.      * rule(A) ::= B. { A = 1; }
  665.      * </pre>
  666.      * 
  667.      * The parser will translate to something like:
  668.      * 
  669.      * <code>
  670.      * function yy_r0(){$this->_retvalue = 1;}
  671.      * </code>
  672.      */
  673.     private $_retvalue;
  674.  
  675.     /**
  676.      * Perform a reduce action and the shift that must immediately
  677.      * follow the reduce.
  678.      * 
  679.      * For a rule such as:
  680.      * 
  681.      * <pre>
  682.      * A ::= B blah C. { dosomething(); }
  683.      * </pre>
  684.      * 
  685.      * This function will first call the action, if any, ("dosomething();" in our
  686.      * example), and then it will pop three states from the stack,
  687.      * one for each entry on the right-hand side of the expression
  688.      * (B, blah, and C in our example rule), and then push the result of the action
  689.      * back on to the stack with the resulting state reduced to (as described in the .out
  690.      * file)
  691.      * @param int Number of the rule by which to reduce
  692.      */
  693.     function yy_reduce($yyruleno)
  694.     {
  695.         //int $yygoto;                     /* The next state */
  696.         //int $yyact;                      /* The next action */
  697.         //mixed $yygotominor;        /* The LHS of the rule reduced */
  698.         //ParseyyStackEntry $yymsp;            /* The top of the parser's stack */
  699.         //int $yysize;                     /* Amount to pop the stack */
  700.         $yymsp $this->yystack[$this->yyidx];
  701.         if (self::$yyTraceFILE && $yyruleno >= 0 
  702.               && $yyruleno < count(self::$yyRuleName)) {
  703.             fprintf(self::$yyTraceFILE"%sReduce (%d) [%s].\n",
  704.                 self::$yyTracePrompt$yyruleno,
  705.                 self::$yyRuleName[$yyruleno]);
  706.         }
  707.  
  708.         $this->_retvalue = $yy_lefthand_side = null;
  709.         if (array_key_exists($yyrulenoself::$yyReduceMap)) {
  710.             // call the action
  711.             $this->_retvalue = null;
  712.             $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}();
  713.             $yy_lefthand_side $this->_retvalue;
  714.         }
  715.         $yygoto = self::$yyRuleInfo[$yyruleno]['lhs'];
  716.         $yysize = self::$yyRuleInfo[$yyruleno]['rhs'];
  717.         $this->yyidx -= $yysize;
  718.         for ($i $yysize$i$i--{
  719.             // pop all of the right-hand side parameters
  720.             array_pop($this->yystack);
  721.         }
  722.         $yyact $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno$yygoto);
  723.         if ($yyact < self::YYNSTATE{
  724.             /* If we are not debugging and the reduce action popped at least
  725.             ** one element off the stack, then we can push the new element back
  726.             ** onto the stack here, and skip the stack overflow test in yy_shift().
  727.             ** That gives a significant speed improvement. */
  728.             if (!self::$yyTraceFILE && $yysize{
  729.                 $this->yyidx++;
  730.                 $x = new ParseyyStackEntry;
  731.                 $x->stateno = $yyact;
  732.                 $x->major = $yygoto;
  733.                 $x->minor = $yy_lefthand_side;
  734.                 $this->yystack[$this->yyidx$x;
  735.             else {
  736.                 $this->yy_shift($yyact$yygoto$yy_lefthand_side);
  737.             }
  738.         elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1{
  739.             $this->yy_accept();
  740.         }
  741.     }
  742.  
  743.     /**
  744.      * The following code executes when the parse fails
  745.      * 
  746.      * Code from %parse_fail is inserted here
  747.      */
  748.     function yy_parse_failed()
  749.     {
  750.         if (self::$yyTraceFILE{
  751.             fprintf(self::$yyTraceFILE"%sFail!\n"self::$yyTracePrompt);
  752.         }
  753.         while ($this->yyidx >= 0{
  754.             $this->yy_pop_parser_stack();
  755.         }
  756.         /* Here code is inserted which will be executed whenever the
  757.         ** parser fails */
  758. %%
  759.     }
  760.  
  761.     /**
  762.      * The following code executes when a syntax error first occurs.
  763.      * 
  764.      * %syntax_error code is inserted here
  765.      * @param int The major type of the error token
  766.      * @param mixed The minor type of the error token
  767.      */
  768.     function yy_syntax_error($yymajor$TOKEN)
  769.     {
  770. %%
  771.     }
  772.  
  773.     /**
  774.      * The following is executed when the parser accepts
  775.      * 
  776.      * %parse_accept code is inserted here
  777.      */
  778.     function yy_accept()
  779.     {
  780.         if (self::$yyTraceFILE{
  781.             fprintf(self::$yyTraceFILE"%sAccept!\n"self::$yyTracePrompt);
  782.         }
  783.         while ($this->yyidx >= 0{
  784.             $stack $this->yy_pop_parser_stack();
  785.         }
  786.         /* Here code is inserted which will be executed whenever the
  787.         ** parser accepts */
  788. %%
  789.     }
  790.  
  791.     /**
  792.      * The main parser program.
  793.      * 
  794.      * The first argument is the major token number.  The second is
  795.      * the token value string as scanned from the input.
  796.      *
  797.      * @param int   $yymajor      the token number
  798.      * @param mixed $yytokenvalue the token value
  799.      * @param mixed ...           any extra arguments that should be passed to handlers
  800.      *
  801.      * @return void 
  802.      */
  803.     function doParse($yymajor$yytokenvalue)
  804.     {
  805. //        $yyact;            /* The parser action. */
  806. //        $yyendofinput;     /* True if we are at the end of input */
  807.         $yyerrorhit = 0;   /* True if yymajor has invoked an error */
  808.         
  809.         /* (re)initialize the parser, if necessary */
  810.         if ($this->yyidx === null || $this->yyidx < 0{
  811.             /* if ($yymajor == 0) return; // not sure why this was here... */
  812.             $this->yyidx = 0;
  813.             $this->yyerrcnt = -1;
  814.             $x = new ParseyyStackEntry;
  815.             $x->stateno = 0;
  816.             $x->major = 0;
  817.             $this->yystack = array();
  818.             array_push($this->yystack$x);
  819.         }
  820.         $yyendofinput ($yymajor==0);
  821.         
  822.         if (self::$yyTraceFILE{
  823.             fprintf(
  824.                 self::$yyTraceFILE,
  825.                 "%sInput %s\n",
  826.                 self::$yyTracePrompt,
  827.                 self::$yyTokenName[$yymajor]
  828.             );
  829.         }
  830.         
  831.         do {
  832.             $yyact $this->yy_find_shift_action($yymajor);
  833.             if ($yymajor < self::YYERRORSYMBOL
  834.                 && !$this->yy_is_expected_token($yymajor)
  835.             {
  836.                 // force a syntax error
  837.                 $yyact = self::YY_ERROR_ACTION;
  838.             }
  839.             if ($yyact < self::YYNSTATE{
  840.                 $this->yy_shift($yyact$yymajor$yytokenvalue);
  841.                 $this->yyerrcnt--;
  842.                 if ($yyendofinput && $this->yyidx >= 0{
  843.                     $yymajor = 0;
  844.                 else {
  845.                     $yymajor = self::YYNOCODE;
  846.                 }
  847.             elseif ($yyact < self::YYNSTATE + self::YYNRULE{
  848.                 $this->yy_reduce($yyact - self::YYNSTATE);
  849.             elseif ($yyact == self::YY_ERROR_ACTION{
  850.                 if (self::$yyTraceFILE{
  851.                     fprintf(
  852.                         self::$yyTraceFILE,
  853.                         "%sSyntax Error!\n",
  854.                         self::$yyTracePrompt
  855.                     );
  856.                 }
  857.                 if (self::YYERRORSYMBOL{
  858.                     /* A syntax error has occurred.
  859.                     ** The response to an error depends upon whether or not the
  860.                     ** grammar defines an error token "ERROR".  
  861.                     **
  862.                     ** This is what we do if the grammar does define ERROR:
  863.                     **
  864.                     **  * Call the %syntax_error function.
  865.                     **
  866.                     **  * Begin popping the stack until we enter a state where
  867.                     **    it is legal to shift the error symbol, then shift
  868.                     **    the error symbol.
  869.                     **
  870.                     **  * Set the error count to three.
  871.                     **
  872.                     **  * Begin accepting and shifting new tokens.  No new error
  873.                     **    processing will occur until three tokens have been
  874.                     **    shifted successfully.
  875.                     **
  876.                     */
  877.                     if ($this->yyerrcnt < 0{
  878.                         $this->yy_syntax_error($yymajor$yytokenvalue);
  879.                     }
  880.                     $yymx $this->yystack[$this->yyidx]->major;
  881.                     if ($yymx == self::YYERRORSYMBOL || $yyerrorhit {
  882.                         if (self::$yyTraceFILE{
  883.                             fprintf(
  884.                                 self::$yyTraceFILE,
  885.                                 "%sDiscard input token %s\n",
  886.                                 self::$yyTracePrompt,
  887.                                 self::$yyTokenName[$yymajor]
  888.                             );
  889.                         }
  890.                         $this->yy_destructor($yymajor$yytokenvalue);
  891.                         $yymajor = self::YYNOCODE;
  892.                     else {
  893.                         while ($this->yyidx >= 0
  894.                             && $yymx != self::YYERRORSYMBOL
  895.                             && ($yyact $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
  896.                         {
  897.                             $this->yy_pop_parser_stack();
  898.                         }
  899.                         if ($this->yyidx < 0 || $yymajor==0{
  900.                             $this->yy_destructor($yymajor$yytokenvalue);
  901.                             $this->yy_parse_failed();
  902.                             $yymajor = self::YYNOCODE;
  903.                         elseif ($yymx != self::YYERRORSYMBOL{
  904.                             $u2 = 0;
  905.                             $this->yy_shift($yyactself::YYERRORSYMBOL$u2);
  906.                         }
  907.                     }
  908.                     $this->yyerrcnt = 3;
  909.                     $yyerrorhit = 1;
  910.                 else {
  911.                     /* YYERRORSYMBOL is not defined */
  912.                     /* This is what we do if the grammar does not define ERROR:
  913.                     **
  914.                     **  * Report an error message, and throw away the input token.
  915.                     **
  916.                     **  * If the input token is $, then fail the parse.
  917.                     **
  918.                     ** As before, subsequent error messages are suppressed until
  919.                     ** three input tokens have been successfully shifted.
  920.                     */
  921.                     if ($this->yyerrcnt <= 0{
  922.                         $this->yy_syntax_error($yymajor$yytokenvalue);
  923.                     }
  924.                     $this->yyerrcnt = 3;
  925.                     $this->yy_destructor($yymajor$yytokenvalue);
  926.                     if ($yyendofinput{
  927.                         $this->yy_parse_failed();
  928.                     }
  929.                     $yymajor = self::YYNOCODE;
  930.                 }
  931.             else {
  932.                 $this->yy_accept();
  933.                 $yymajor = self::YYNOCODE;
  934.             }            
  935.         while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
  936.     }
  937. }

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