root/trunk/Lib/Pear/PHP/LexerGenerator/Parser.php

Revision 2, 72.9 KB (checked in by tom, 5 years ago)

+ADD: Lib: Pear Basic Setup for php2lex tests.

Line 
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 */
11class 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 */
87class 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 */
149require_once 'PHP/LexerGenerator/Regex/Lexer.php';
150require_once 'PHP/LexerGenerator/Regex/Parser.php';
151require_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"
168class 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($tokenindex, true);
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(0, 0);
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;
588static 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(1, 2, ),
624        /* 1 */ array(4, 5, 8, ),
625        /* 2 */ array(4, 5, 8, ),
626        /* 3 */ array(5, 8, ),
627        /* 4 */ array(1, 2, ),
628        /* 5 */ array(5, 8, ),
629        /* 6 */ array(1, 2, ),
630        /* 7 */ array(2, ),
631        /* 8 */ array(4, ),
632        /* 9 */ array(2, ),
633        /* 10 */ array(3, 5, 8, ),
634        /* 11 */ array(3, 5, 8, ),
635        /* 12 */ array(3, 5, 8, ),
636        /* 13 */ array(3, 5, 8, ),
637        /* 14 */ array(4, 7, ),
638        /* 15 */ array(5, 8, ),
639        /* 16 */ array(5, 8, ),
640        /* 17 */ array(2, ),
641        /* 18 */ array(5, 6, 8, ),
642        /* 19 */ array(5, 6, 8, ),
643        /* 20 */ array(5, 6, ),
644        /* 21 */ array(5, 8, ),
645        /* 22 */ array(5, 8, ),
646        /* 23 */ array(5, 6, ),
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($token, self::$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($token, self::$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($token, self::$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::$yyTraceFILE, self::$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[0] . preg_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]->minor, true);
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]->minor, true);
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($yyruleno, self::$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($yymajor) as $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::$yyTracePrompt, self::$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::$yyTracePrompt, self::$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($yyact, self::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}
Note: See TracBrowser for help on using the browser.