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

example

  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;                    /* 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 && $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.         return true;
  506.     }
  507.  
  508.     /**
  509.      * Find the appropriate action for a parser given the terminal
  510.      * look-ahead token iLookAhead.
  511.      *
  512.      * If the look-ahead token is YYNOCODE, then check to see if the action is
  513.      * independent of the look-ahead.  If it is, return the action, otherwise
  514.      * return YY_NO_ACTION.
  515.      * @param int The look-ahead token
  516.      */
  517.     function yy_find_shift_action($iLookAhead)
  518.     {
  519.         $stateno $this->yystack[$this->yyidx]->stateno;
  520.      
  521.         /* if ($this->yyidx < 0) return self::YY_NO_ACTION;  */
  522.         if (!isset(self::$yy_shift_ofst[$stateno])) {
  523.             // no shift actions
  524.             return self::$yy_default[$stateno];
  525.         }
  526.         $i self::$yy_shift_ofst[$stateno];
  527.         if ($i === self::YY_SHIFT_USE_DFLT{
  528.             return self::$yy_default[$stateno];
  529.         }
  530.         if ($iLookAhead == self::YYNOCODE{
  531.             return self::YY_NO_ACTION;
  532.         }
  533.         $i += $iLookAhead;
  534.         if ($i || $i >= self::YY_SZ_ACTTAB ||
  535.               self::$yy_lookahead[$i!= $iLookAhead{
  536.             if (count(self::$yyFallback&& $iLookAhead count(self::$yyFallback)
  537.                    && ($iFallback self::$yyFallback[$iLookAhead]!= 0{
  538.                 if (self::$yyTraceFILE{
  539.                     fwrite(self::$yyTraceFILEself::$yyTracePrompt "FALLBACK " .
  540.                         self::$yyTokenName[$iLookAhead" => " .
  541.                         self::$yyTokenName[$iFallback"\n");
  542.                 }
  543.                 return $this->yy_find_shift_action($iFallback);
  544.             }
  545.             return self::$yy_default[$stateno];
  546.         else {
  547.             return self::$yy_action[$i];
  548.         }
  549.     }
  550.  
  551.     /**
  552.      * Find the appropriate action for a parser given the non-terminal
  553.      * look-ahead token $iLookAhead.
  554.      *
  555.      * If the look-ahead token is self::YYNOCODE, then check to see if the action is
  556.      * independent of the look-ahead.  If it is, return the action, otherwise
  557.      * return self::YY_NO_ACTION.
  558.      * @param int Current state number
  559.      * @param int The look-ahead token
  560.      */
  561.     function yy_find_reduce_action($stateno$iLookAhead)
  562.     {
  563.         /* $stateno = $this->yystack[$this->yyidx]->stateno; */
  564.  
  565.         if (!isset(self::$yy_reduce_ofst[$stateno])) {
  566.             return self::$yy_default[$stateno];
  567.         }
  568.         $i self::$yy_reduce_ofst[$stateno];
  569.         if ($i == self::YY_REDUCE_USE_DFLT{
  570.             return self::$yy_default[$stateno];
  571.         }
  572.         if ($iLookAhead == self::YYNOCODE{
  573.             return self::YY_NO_ACTION;
  574.         }
  575.         $i += $iLookAhead;
  576.         if ($i || $i >= self::YY_SZ_ACTTAB ||
  577.               self::$yy_lookahead[$i!= $iLookAhead{
  578.             return self::$yy_default[$stateno];
  579.         else {
  580.             return self::$yy_action[$i];
  581.         }
  582.     }
  583.  
  584.     /**
  585.      * Perform a shift action.
  586.      * @param int The new state to shift in
  587.      * @param int The major token to shift in
  588.      * @param mixed the minor token to shift in
  589.      */
  590.     function yy_shift($yyNewState$yyMajor$yypMinor)
  591.     {
  592.         $this->yyidx++;
  593.         if ($this->yyidx >= self::YYSTACKDEPTH{
  594.             $this->yyidx--;
  595.             if (self::$yyTraceFILE{
  596.                 fprintf(self::$yyTraceFILE"%sStack Overflow!\n"self::$yyTracePrompt);
  597.             }
  598.             while ($this->yyidx >= 0{
  599.                 $this->yy_pop_parser_stack();
  600.             }
  601.             /* Here code is inserted which will execute if the parser
  602.             ** stack ever overflows */
  603. %%
  604.             return;
  605.         }
  606.         $yytos new ParseyyStackEntry;
  607.         $yytos->stateno $yyNewState;
  608.         $yytos->major $yyMajor;
  609.         $yytos->minor $yypMinor;
  610.         array_push($this->yystack$yytos);
  611.         if (self::$yyTraceFILE && $this->yyidx 0{
  612.             fprintf(self::$yyTraceFILE"%sShift %d\n"self::$yyTracePrompt,
  613.                 $yyNewState);
  614.             fprintf(self::$yyTraceFILE"%sStack:"self::$yyTracePrompt);
  615.             for($i 1$i <= $this->yyidx$i++{
  616.                 fprintf(self::$yyTraceFILE" %s",
  617.                     self::$yyTokenName[$this->yystack[$i]->major]);
  618.             }
  619.             fwrite(self::$yyTraceFILE,"\n");
  620.         }
  621.     }
  622.  
  623.     /**
  624.      * The following table contains information about every rule that
  625.      * is used during the reduce.
  626.      *
  627.      * <pre>
  628.      * array(
  629.      *  array(
  630.      *   int $lhs;         Symbol on the left-hand side of the rule
  631.      *   int $nrhs;     Number of right-hand side symbols in the rule
  632.      *  ),...
  633.      * );
  634.      * </pre>
  635.      */
  636.     static public $yyRuleInfo array(
  637. %%
  638.     );
  639.  
  640.     /**
  641.      * The following table contains a mapping of reduce action to method name
  642.      * that handles the reduction.
  643.      * 
  644.      * If a rule is not set, it has no handler.
  645.      */
  646.     static public $yyReduceMap array(
  647. %%
  648.     );
  649.     /* Beginning here are the reduction cases.  A typical example
  650.     ** follows:
  651.     **  #line <lineno> <grammarfile>
  652.     **   function yy_r0($yymsp){ ... }           // User supplied code
  653.     **  #line <lineno> <thisfile>
  654.     */
  655. %%
  656.  
  657.     /**
  658.      * placeholder for the left hand side in a reduce operation.
  659.      * 
  660.      * For a parser with a rule like this:
  661.      * <pre>
  662.      * rule(A) ::= B. { A = 1; }
  663.      * </pre>
  664.      * 
  665.      * The parser will translate to something like:
  666.      * 
  667.      * <code>
  668.      * function yy_r0(){$this->_retvalue = 1;}
  669.      * </code>
  670.      */
  671.     private $_retvalue;
  672.  
  673.     /**
  674.      * Perform a reduce action and the shift that must immediately
  675.      * follow the reduce.
  676.      * 
  677.      * For a rule such as:
  678.      * 
  679.      * <pre>
  680.      * A ::= B blah C. { dosomething(); }
  681.      * </pre>
  682.      * 
  683.      * This function will first call the action, if any, ("dosomething();" in our
  684.      * example), and then it will pop three states from the stack,
  685.      * one for each entry on the right-hand side of the expression
  686.      * (B, blah, and C in our example rule), and then push the result of the action
  687.      * back on to the stack with the resulting state reduced to (as described in the .out
  688.      * file)
  689.      * @param int Number of the rule by which to reduce
  690.      */
  691.     function yy_reduce($yyruleno)
  692.     {
  693.         //int $yygoto;                     /* The next state */
  694.         //int $yyact;                      /* The next action */
  695.         //mixed $yygotominor;        /* The LHS of the rule reduced */
  696.         //ParseyyStackEntry $yymsp;            /* The top of the parser's stack */
  697.         //int $yysize;                     /* Amount to pop the stack */
  698.         $yymsp $this->yystack[$this->yyidx];
  699.         if (self::$yyTraceFILE && $yyruleno >= 
  700.               && $yyruleno count(self::$yyRuleName)) {
  701.             fprintf(self::$yyTraceFILE"%sReduce (%d) [%s].\n",
  702.                 self::$yyTracePrompt$yyruleno,
  703.                 self::$yyRuleName[$yyruleno]);
  704.         }
  705.  
  706.         $this->_retvalue $yy_lefthand_side null;
  707.         if (array_key_exists($yyrulenoself::$yyReduceMap)) {
  708.             // call the action
  709.             $this->_retvalue null;
  710.             $this->{'yy_r' self::$yyReduceMap[$yyruleno]}();
  711.             $yy_lefthand_side $this->_retvalue;
  712.         }
  713.         $yygoto self::$yyRuleInfo[$yyruleno]['lhs'];
  714.         $yysize self::$yyRuleInfo[$yyruleno]['rhs'];
  715.         $this->yyidx -= $yysize;
  716.         for($i $yysize$i$i--{
  717.             // pop all of the right-hand side parameters
  718.             array_pop($this->yystack);
  719.         }
  720.         $yyact $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno$yygoto);
  721.         if ($yyact self::YYNSTATE{
  722.             /* If we are not debugging and the reduce action popped at least
  723.             ** one element off the stack, then we can push the new element back
  724.             ** onto the stack here, and skip the stack overflow test in yy_shift().
  725.             ** That gives a significant speed improvement. */
  726.             if (!self::$yyTraceFILE && $yysize{
  727.                 $this->yyidx++;
  728.                 $x new ParseyyStackEntry;
  729.                 $x->stateno $yyact;
  730.                 $x->major $yygoto;
  731.                 $x->minor $yy_lefthand_side;
  732.                 $this->yystack[$this->yyidx$x;
  733.             else {
  734.                 $this->yy_shift($yyact$yygoto$yy_lefthand_side);
  735.             }
  736.         elseif ($yyact == self::YYNSTATE self::YYNRULE 1{
  737.             $this->yy_accept();
  738.         }
  739.     }
  740.  
  741.     /**
  742.      * The following code executes when the parse fails
  743.      * 
  744.      * Code from %parse_fail is inserted here
  745.      */
  746.     function yy_parse_failed()
  747.     {
  748.         if (self::$yyTraceFILE{
  749.             fprintf(self::$yyTraceFILE"%sFail!\n"self::$yyTracePrompt);
  750.         }
  751.         while ($this->yyidx >= 0{
  752.             $this->yy_pop_parser_stack();
  753.         }
  754.         /* Here code is inserted which will be executed whenever the
  755.         ** parser fails */
  756. %%
  757.     }
  758.  
  759.     /**
  760.      * The following code executes when a syntax error first occurs.
  761.      * 
  762.      * %syntax_error code is inserted here
  763.      * @param int The major type of the error token
  764.      * @param mixed The minor type of the error token
  765.      */
  766.     function yy_syntax_error($yymajor$TOKEN)
  767.     {
  768. %%
  769.     }
  770.  
  771.     /**
  772.      * The following is executed when the parser accepts
  773.      * 
  774.      * %parse_accept code is inserted here
  775.      */
  776.     function yy_accept()
  777.     {
  778.         if (self::$yyTraceFILE{
  779.             fprintf(self::$yyTraceFILE"%sAccept!\n"self::$yyTracePrompt);
  780.         }
  781.         while ($this->yyidx >= 0{
  782.             $stack $this->yy_pop_parser_stack();
  783.         }
  784.         /* Here code is inserted which will be executed whenever the
  785.         ** parser accepts */
  786. %%
  787.     }
  788.  
  789.     /**
  790.      * The main parser program.
  791.      * 
  792.      * The first argument is the major token number.  The second is
  793.      * the token value string as scanned from the input.
  794.      *
  795.      * @param int the token number
  796.      * @param mixed the token value
  797.      * @param mixed any extra arguments that should be passed to handlers
  798.      */
  799.     function doParse($yymajor$yytokenvalue)
  800.     {
  801. //        $yyact;            /* The parser action. */
  802. //        $yyendofinput;     /* True if we are at the end of input */
  803.         $yyerrorhit 0;   /* True if yymajor has invoked an error */
  804.         
  805.         /* (re)initialize the parser, if necessary */
  806.         if ($this->yyidx === null || $this->yyidx 0{
  807.             /* if ($yymajor == 0) return; // not sure why this was here... */
  808.             $this->yyidx 0;
  809.             $this->yyerrcnt = -1;
  810.             $x new ParseyyStackEntry;
  811.             $x->stateno 0;
  812.             $x->major 0;
  813.             $this->yystack array();
  814.             array_push($this->yystack$x);
  815.         }
  816.         $yyendofinput ($yymajor==0);
  817.         
  818.         if (self::$yyTraceFILE{
  819.             fprintf(self::$yyTraceFILE"%sInput %s\n",
  820.                 self::$yyTracePromptself::$yyTokenName[$yymajor]);
  821.         }
  822.         
  823.         do {
  824.             $yyact $this->yy_find_shift_action($yymajor);
  825.             if ($yymajor self::YYERRORSYMBOL &&
  826.                   !$this->yy_is_expected_token($yymajor)) {
  827.                 // force a syntax error
  828.                 $yyact self::YY_ERROR_ACTION;
  829.             }
  830.             if ($yyact self::YYNSTATE{
  831.                 $this->yy_shift($yyact$yymajor$yytokenvalue);
  832.                 $this->yyerrcnt--;
  833.                 if ($yyendofinput && $this->yyidx >= 0{
  834.                     $yymajor 0;
  835.                 else {
  836.                     $yymajor self::YYNOCODE;
  837.                 }
  838.             elseif ($yyact self::YYNSTATE self::YYNRULE{
  839.                 $this->yy_reduce($yyact self::YYNSTATE);
  840.             elseif ($yyact == self::YY_ERROR_ACTION{
  841.                 if (self::$yyTraceFILE{
  842.                     fprintf(self::$yyTraceFILE"%sSyntax Error!\n",
  843.                         self::$yyTracePrompt);
  844.                 }
  845.                 if (self::YYERRORSYMBOL{
  846.                     /* A syntax error has occurred.
  847.                     ** The response to an error depends upon whether or not the
  848.                     ** grammar defines an error token "ERROR".  
  849.                     **
  850.                     ** This is what we do if the grammar does define ERROR:
  851.                     **
  852.                     **  * Call the %syntax_error function.
  853.                     **
  854.                     **  * Begin popping the stack until we enter a state where
  855.                     **    it is legal to shift the error symbol, then shift
  856.                     **    the error symbol.
  857.                     **
  858.                     **  * Set the error count to three.
  859.                     **
  860.                     **  * Begin accepting and shifting new tokens.  No new error
  861.                     **    processing will occur until three tokens have been
  862.                     **    shifted successfully.
  863.                     **
  864.                     */
  865.                     if ($this->yyerrcnt 0{
  866.                         $this->yy_syntax_error($yymajor$yytokenvalue);
  867.                     }
  868.                     $yymx $this->yystack[$this->yyidx]->major;
  869.                     if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){
  870.                         if (self::$yyTraceFILE{
  871.                             fprintf(self::$yyTraceFILE"%sDiscard input token %s\n",
  872.                                 self::$yyTracePromptself::$yyTokenName[$yymajor]);
  873.                         }
  874.                         $this->yy_destructor($yymajor$yytokenvalue);
  875.                         $yymajor self::YYNOCODE;
  876.                     else {
  877.                         while ($this->yyidx >= &&
  878.                                  $yymx != self::YYERRORSYMBOL &&
  879.         ($yyact $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
  880.                               ){
  881.                             $this->yy_pop_parser_stack();
  882.                         }
  883.                         if ($this->yyidx || $yymajor==0{
  884.                             $this->yy_destructor($yymajor$yytokenvalue);
  885.                             $this->yy_parse_failed();
  886.                             $yymajor self::YYNOCODE;
  887.                         elseif ($yymx != self::YYERRORSYMBOL{
  888.                             $u2 0;
  889.                             $this->yy_shift($yyactself::YYERRORSYMBOL$u2);
  890.                         }
  891.                     }
  892.                     $this->yyerrcnt 3;
  893.                     $yyerrorhit 1;
  894.                 else {
  895.                     /* YYERRORSYMBOL is not defined */
  896.                     /* This is what we do if the grammar does not define ERROR:
  897.                     **
  898.                     **  * Report an error message, and throw away the input token.
  899.                     **
  900.                     **  * If the input token is $, then fail the parse.
  901.                     **
  902.                     ** As before, subsequent error messages are suppressed until
  903.                     ** three input tokens have been successfully shifted.
  904.                     */
  905.                     if ($this->yyerrcnt <= 0{
  906.                         $this->yy_syntax_error($yymajor$yytokenvalue);
  907.                     }
  908.                     $this->yyerrcnt 3;
  909.                     $this->yy_destructor($yymajor$yytokenvalue);
  910.                     if ($yyendofinput{
  911.                         $this->yy_parse_failed();
  912.                     }
  913.                     $yymajor self::YYNOCODE;
  914.                 }
  915.             else {
  916.                 $this->yy_accept();
  917.                 $yymajor self::YYNOCODE;
  918.             }            
  919.         while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
  920.     }
  921. }

Documentation generated on Sun, 02 Jul 2006 09:11:05 -0400 by phpDocumentor 1.3.0