123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- <?php
- /**
- * PHP_ParserGenerator, a php 5 parser generator.
- *
- * This is a direct port of the Lemon parser generator, found at
- * {@link http://www.hwaci.com/sw/lemon/}
- *
- * PHP version 5
- *
- * LICENSE:
- *
- * Copyright (c) 2006, Gregory Beaver <cellog@php.net>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the distribution.
- * * Neither the name of the PHP_ParserGenerator nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category PHP
- * @package PHP_ParserGenerator
- * @author Gregory Beaver <cellog@php.net>
- * @copyright 2006 Gregory Beaver
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Action.php 302382 2010-08-17 06:08:09Z jespino $
- * @link http://pear.php.net/package/PHP_ParserGenerator
- * @since File available since Release 0.1.0
- */
- /**
- * Every shift or reduce operation is stored as one of the following objects.
- *
- * @category PHP
- * @package PHP_ParserGenerator
- * @author Gregory Beaver <cellog@php.net>
- * @copyright 2006 Gregory Beaver
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/PHP_ParserGenerator
- * @since Class available since Release 0.1.0
- */
- class PHP_ParserGenerator_Action
- {
- const SHIFT = 1,
- ACCEPT = 2,
- REDUCE = 3,
- ERROR = 4,
- /**
- * Was a reduce, but part of a conflict
- */
- CONFLICT = 5,
- /**
- * Was a shift. Precedence resolved conflict
- */
- SH_RESOLVED = 6,
- /**
- * Was a reduce. Precedence resolved conflict
- */
- RD_RESOLVED = 7,
- /**
- * Deleted by compression
- * @see PHP_ParserGenerator::CompressTables()
- */
- NOT_USED = 8;
- /**
- * The look-ahead symbol that triggers this action
- * @var PHP_ParserGenerator_Symbol
- */
- public $sp; /* The look-ahead symbol */
- /**
- * This defines the kind of action, and must be one
- * of the class constants.
- *
- * - {@link PHP_ParserGenerator_Action::SHIFT}
- * - {@link PHP_ParserGenerator_Action::ACCEPT}
- * - {@link PHP_ParserGenerator_Action::REDUCE}
- * - {@link PHP_ParserGenerator_Action::ERROR}
- * - {@link PHP_ParserGenerator_Action::CONFLICT}
- * - {@link PHP_ParserGenerator_Action::SH_RESOLVED}
- * - {@link PHP_ParserGenerator_Action:: RD_RESOLVED}
- * - {@link PHP_ParserGenerator_Action::NOT_USED}
- */
- public $type;
- /**
- * The new state, if this is a shift,
- * the parser rule index, if this is a reduce.
- *
- * @var PHP_ParserGenerator_State|PHP_ParserGenerator_Rule
- */
- public $x;
- /**
- * The next action for this state.
- * @var PHP_ParserGenerator_Action
- */
- public $next;
- /**
- * Compare two actions
- *
- * This is used by {@link Action_sort()} to compare actions
- */
- static function actioncmp(PHP_ParserGenerator_Action $ap1, PHP_ParserGenerator_Action $ap2)
- {
- $rc = $ap1->sp->index - $ap2->sp->index;
- if ($rc === 0) {
- $rc = $ap1->type - $ap2->type;
- }
- if ($rc === 0) {
- if ($ap1->type == self::SHIFT) {
- if ($ap1->x->statenum != $ap2->x->statenum) {
- throw new Exception('Shift conflict: ' . $ap1->sp->name .
- ' shifts both to state ' . $ap1->x->statenum . ' (rule ' .
- $ap1->x->cfp->rp->lhs->name . ' on line ' .
- $ap1->x->cfp->rp->ruleline . ') and to state ' .
- $ap2->x->statenum . ' (rule ' .
- $ap2->x->cfp->rp->lhs->name . ' on line ' .
- $ap2->x->cfp->rp->ruleline . ')');
- }
- }
- if ($ap1->type != self::REDUCE
- && $ap1->type != self::RD_RESOLVED
- && $ap1->type != self::CONFLICT
- ) {
- throw new Exception('action has not been processed: ' .
- $ap1->sp->name . ' on line ' . $ap1->x->cfp->rp->ruleline .
- ', rule ' . $ap1->x->cfp->rp->lhs->name);
- }
- if ($ap2->type != self::REDUCE
- && $ap2->type != self::RD_RESOLVED
- && $ap2->type != self::CONFLICT
- ) {
- throw new Exception('action has not been processed: ' .
- $ap2->sp->name . ' on line ' . $ap2->x->cfp->rp->ruleline .
- ', rule ' . $ap2->x->cfp->rp->lhs->name);
- }
- $rc = $ap1->x->index - $ap2->x->index;
- }
- return $rc;
- }
- function display($processed = false)
- {
- $map = array(
- self::ACCEPT => 'ACCEPT',
- self::CONFLICT => 'CONFLICT',
- self::REDUCE => 'REDUCE',
- self::SHIFT => 'SHIFT'
- );
- echo $map[$this->type] . ' for ' . $this->sp->name;
- if ($this->type == self::REDUCE) {
- echo ' - rule ' . $this->x->lhs->name . "\n";
- } elseif ($this->type == self::SHIFT) {
- echo ' - state ' . $this->x->statenum . ', basis ' . $this->x->cfp->rp->lhs->name . "\n";
- } else {
- echo "\n";
- }
- }
- /**
- * create linked list of PHP_ParserGenerator_Actions
- *
- * @param PHP_ParserGenerator_Action|null $app
- * @param int $type one of the class constants from PHP_ParserGenerator_Action
- * @param PHP_ParserGenerator_Symbol $sp
- * @param PHP_ParserGenerator_State|PHP_ParserGenerator_Rule $arg
- */
- static function Action_add(&$app, $type, PHP_ParserGenerator_Symbol $sp, $arg)
- {
- $new = new PHP_ParserGenerator_Action;
- $new->next = $app;
- $app = $new;
- $new->type = $type;
- $new->sp = $sp;
- $new->x = $arg;
- echo ' Adding ';
- $new->display();
- }
- /**
- * Sort parser actions
- *
- * @param PHP_ParserGenerator_Action $ap a parser action
- *
- * @see PHP_ParserGenerator_Data::FindActions()
- *
- * @return PHP_ParserGenerator_Action
- */
- static function Action_sort(PHP_ParserGenerator_Action $ap)
- {
- $ap = PHP_ParserGenerator::msort($ap, 'next', array('PHP_ParserGenerator_Action', 'actioncmp'));
- return $ap;
- }
- /**
- * Print an action to the given file descriptor. Return FALSE if
- * nothing was actually printed.
- *
- * @param resource $fp File descriptor to print on
- * @param integer $indent Number of indents
- *
- * @see PHP_ParserGenerator_Data::ReportOutput()
- *
- * @return int|false
- */
- function PrintAction($fp, $indent)
- {
- if (!$fp) {
- $fp = STDOUT;
- }
- $result = 1;
- switch ($this->type)
- {
- case self::SHIFT:
- fprintf($fp, "%${indent}s shift %d", $this->sp->name, $this->x->statenum);
- break;
- case self::REDUCE:
- fprintf($fp, "%${indent}s reduce %d", $this->sp->name, $this->x->index);
- break;
- case self::ACCEPT:
- fprintf($fp, "%${indent}s accept", $this->sp->name);
- break;
- case self::ERROR:
- fprintf($fp, "%${indent}s error", $this->sp->name);
- break;
- case self::CONFLICT:
- fprintf($fp, "%${indent}s reduce %-3d ** Parsing conflict **", $this->sp->name, $this->x->index);
- break;
- case self::SH_RESOLVED:
- case self::RD_RESOLVED:
- case self::NOT_USED:
- $result = 0;
- break;
- }
- return $result;
- }
- }
- ?>
|