init
This commit is contained in:
commit
72a26edcff
22092 changed files with 2101903 additions and 0 deletions
243
vendor/smarty/smarty-lexer/ParserGenerator/Action.php
vendored
Normal file
243
vendor/smarty/smarty-lexer/ParserGenerator/Action.php
vendored
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
<?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,v 1.2 2007/03/04 17:52:05 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
* Every shift or reduce operation is stored as one of the following objects.
|
||||
*
|
||||
* @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 0.1.5
|
||||
* @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
|
||||
*/
|
||||
public 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;
|
||||
}
|
||||
|
||||
public function display($processed = false)
|
||||
{
|
||||
$map = array(
|
||||
self::ACCEPT => 'ACCEPT',
|
||||
self::CONFLICT => 'CONFLICT',
|
||||
self::REDUCE => 'REDUCE',
|
||||
self::SHIFT => 'SHIFT'
|
||||
);
|
||||
$sep = isset($_SERVER['_']) ? "\n" : "<br>";
|
||||
echo $map[$this->type] . ' for ' . $this->sp->name;
|
||||
if ($this->type == self::REDUCE) {
|
||||
echo ' - rule ' . $this->x->lhs->name . $sep;
|
||||
} elseif ($this->type == self::SHIFT) {
|
||||
echo ' - state ' . $this->x->statenum . ', basis ' . $this->x->cfp->rp->lhs->name . $sep;
|
||||
} else {
|
||||
echo $sep;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create linked list of PHP_ParserGenerator_Actions
|
||||
*
|
||||
* @param PHP_ParserGenerator_Action|null
|
||||
* @param int one of the class constants from PHP_ParserGenerator_Action
|
||||
* @param PHP_ParserGenerator_Symbol
|
||||
* @param PHP_ParserGenerator_State|PHP_ParserGenerator_Rule
|
||||
*/
|
||||
public 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
|
||||
* @see PHP_ParserGenerator_Data::FindActions()
|
||||
*/
|
||||
public 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.
|
||||
* @see PHP_ParserGenerator_Data::ReportOutput()
|
||||
*/
|
||||
public 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;
|
||||
}
|
||||
}
|
||||
293
vendor/smarty/smarty-lexer/ParserGenerator/ActionTable.php
vendored
Normal file
293
vendor/smarty/smarty-lexer/ParserGenerator/ActionTable.php
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
<?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: ActionTable.php,v 1.1 2006/07/18 00:53:10 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
* The state of the yy_action table under construction is an instance of
|
||||
* the following structure
|
||||
* @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 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_ActionTable
|
||||
{
|
||||
/**
|
||||
* Number of used slots in {@link $aAction}
|
||||
* @var int
|
||||
*/
|
||||
public $nAction = 0;
|
||||
/**
|
||||
* The $yy_action table under construction.
|
||||
*
|
||||
* Each entry is of format:
|
||||
* <code>
|
||||
* array(
|
||||
* 'lookahead' => -1, // Value of the lookahead token (symbol index)
|
||||
* 'action' => -1 // Action to take on the given lookahead (action index)
|
||||
* );
|
||||
* </code>
|
||||
* @see PHP_ParserGenerator_Data::compute_action()
|
||||
* @var array
|
||||
*/
|
||||
public $aAction =
|
||||
array(array(
|
||||
'lookahead' => -1,
|
||||
'action' => -1
|
||||
));
|
||||
/**
|
||||
* A single new transaction set.
|
||||
*
|
||||
* @see $aAction format of the internal array is described here
|
||||
* @var array
|
||||
*/
|
||||
public $aLookahead =
|
||||
array(array(
|
||||
'lookahead' => 0,
|
||||
'action' => 0
|
||||
));
|
||||
/**
|
||||
* The smallest (minimum) value of any lookahead token in {@link $aLookahead}
|
||||
*
|
||||
* The lowest non-terminal is always introduced earlier in the parser file,
|
||||
* and is therefore a more significant token.
|
||||
* @var int
|
||||
*/
|
||||
public $mnLookahead = 0;
|
||||
/**
|
||||
* The action associated with the smallest lookahead token.
|
||||
* @see $mnLookahead
|
||||
* @var int
|
||||
*/
|
||||
public $mnAction = 0;
|
||||
/**
|
||||
* The largest (maximum) value of any lookahead token in {@link $aLookahead}
|
||||
* @var int
|
||||
*/
|
||||
public $mxLookahead = 0;
|
||||
/**
|
||||
* The number of slots used in {@link $aLookahead}.
|
||||
*
|
||||
* This is the same as count($aLookahead), but there was no pressing reason
|
||||
* to change this when porting from C.
|
||||
* @see $mnLookahead
|
||||
* @var int
|
||||
*/
|
||||
public $nLookahead = 0;
|
||||
|
||||
/**
|
||||
* Add a new action to the current transaction set
|
||||
* @param int
|
||||
* @param int
|
||||
*/
|
||||
public function acttab_action($lookahead, $action)
|
||||
{
|
||||
if ($this->nLookahead === 0) {
|
||||
$this->aLookahead = array();
|
||||
$this->mxLookahead = $lookahead;
|
||||
$this->mnLookahead = $lookahead;
|
||||
$this->mnAction = $action;
|
||||
} else {
|
||||
if ($this->mxLookahead < $lookahead) {
|
||||
$this->mxLookahead = $lookahead;
|
||||
}
|
||||
if ($this->mnLookahead > $lookahead) {
|
||||
$this->mnLookahead = $lookahead;
|
||||
$this->mnAction = $action;
|
||||
}
|
||||
}
|
||||
$this->aLookahead[$this->nLookahead] = array(
|
||||
'lookahead' => $lookahead,
|
||||
'action' => $action);
|
||||
$this->nLookahead++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the transaction set built up with prior calls to acttab_action()
|
||||
* into the current action table. Then reset the transaction set back
|
||||
* to an empty set in preparation for a new round of acttab_action() calls.
|
||||
*
|
||||
* Return the offset into the action table of the new transaction.
|
||||
* @return int Return the offset that should be added to the lookahead in
|
||||
* order to get the index into $yy_action of the action. This will be used
|
||||
* in generation of $yy_ofst tables (reduce and shift)
|
||||
* @throws Exception
|
||||
*/
|
||||
public function acttab_insert()
|
||||
{
|
||||
if ($this->nLookahead <= 0) {
|
||||
throw new Exception('nLookahead is not set up?');
|
||||
}
|
||||
|
||||
/* Scan the existing action table looking for an offset where we can
|
||||
** insert the current transaction set. Fall out of the loop when that
|
||||
** offset is found. In the worst case, we fall out of the loop when
|
||||
** i reaches $this->nAction, which means we append the new transaction set.
|
||||
**
|
||||
** i is the index in $this->aAction[] where $this->mnLookahead is inserted.
|
||||
*/
|
||||
for ($i = 0; $i < $this->nAction + $this->mnLookahead; $i++) {
|
||||
if (!isset($this->aAction[$i])) {
|
||||
$this->aAction[$i] = array(
|
||||
'lookahead' => -1,
|
||||
'action' => -1,
|
||||
);
|
||||
}
|
||||
if ($this->aAction[$i]['lookahead'] < 0) {
|
||||
for ($j = 0; $j < $this->nLookahead; $j++) {
|
||||
if (!isset($this->aLookahead[$j])) {
|
||||
$this->aLookahead[$j] = array(
|
||||
'lookahead' => 0,
|
||||
'action' => 0,
|
||||
);
|
||||
}
|
||||
$k = $this->aLookahead[$j]['lookahead'] -
|
||||
$this->mnLookahead + $i;
|
||||
if ($k < 0) {
|
||||
break;
|
||||
}
|
||||
if (!isset($this->aAction[$k])) {
|
||||
$this->aAction[$k] = array(
|
||||
'lookahead' => -1,
|
||||
'action' => -1,
|
||||
);
|
||||
}
|
||||
if ($this->aAction[$k]['lookahead'] >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($j < $this->nLookahead) {
|
||||
continue;
|
||||
}
|
||||
for ($j = 0; $j < $this->nAction; $j++) {
|
||||
if (!isset($this->aAction[$j])) {
|
||||
$this->aAction[$j] = array(
|
||||
'lookahead' => -1,
|
||||
'action' => -1,
|
||||
);
|
||||
}
|
||||
if ($this->aAction[$j]['lookahead'] == $j +
|
||||
$this->mnLookahead - $i) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($j == $this->nAction) {
|
||||
break; /* Fits in empty slots */
|
||||
}
|
||||
} elseif ($this->aAction[$i]['lookahead'] == $this->mnLookahead) {
|
||||
if ($this->aAction[$i]['action'] != $this->mnAction) {
|
||||
continue;
|
||||
}
|
||||
for ($j = 0; $j < $this->nLookahead; $j++) {
|
||||
$k = $this->aLookahead[$j]['lookahead'] -
|
||||
$this->mnLookahead + $i;
|
||||
if ($k < 0 || $k >= $this->nAction) {
|
||||
break;
|
||||
}
|
||||
if (!isset($this->aAction[$k])) {
|
||||
$this->aAction[$k] = array(
|
||||
'lookahead' => -1,
|
||||
'action' => -1,
|
||||
);
|
||||
}
|
||||
if ($this->aLookahead[$j]['lookahead'] !=
|
||||
$this->aAction[$k]['lookahead']) {
|
||||
break;
|
||||
}
|
||||
if ($this->aLookahead[$j]['action'] !=
|
||||
$this->aAction[$k]['action']) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($j < $this->nLookahead) {
|
||||
continue;
|
||||
}
|
||||
$n = 0;
|
||||
for ($j = 0; $j < $this->nAction; $j++) {
|
||||
if (!isset($this->aAction[$j])) {
|
||||
$this->aAction[$j] = array(
|
||||
'lookahead' => -1,
|
||||
'action' => -1,
|
||||
);
|
||||
}
|
||||
if ($this->aAction[$j]['lookahead'] < 0) {
|
||||
continue;
|
||||
}
|
||||
if ($this->aAction[$j]['lookahead'] == $j +
|
||||
$this->mnLookahead - $i) {
|
||||
$n++;
|
||||
}
|
||||
}
|
||||
if ($n == $this->nLookahead) {
|
||||
break; /* Same as a prior transaction set */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Insert transaction set at index i. */
|
||||
for ($j = 0; $j < $this->nLookahead; $j++) {
|
||||
if (!isset($this->aLookahead[$j])) {
|
||||
$this->aLookahead[$j] = array(
|
||||
'lookahead' => 0,
|
||||
'action' => 0,
|
||||
);
|
||||
}
|
||||
$k = $this->aLookahead[$j]['lookahead'] - $this->mnLookahead + $i;
|
||||
$this->aAction[$k] = $this->aLookahead[$j];
|
||||
if ($k >= $this->nAction) {
|
||||
$this->nAction = $k + 1;
|
||||
}
|
||||
}
|
||||
$this->nLookahead = 0;
|
||||
$this->aLookahead = array();
|
||||
|
||||
/* Return the offset that is added to the lookahead in order to get the
|
||||
** index into yy_action of the action */
|
||||
|
||||
return $i - $this->mnLookahead;
|
||||
}
|
||||
}
|
||||
580
vendor/smarty/smarty-lexer/ParserGenerator/Config.php
vendored
Normal file
580
vendor/smarty/smarty-lexer/ParserGenerator/Config.php
vendored
Normal file
|
|
@ -0,0 +1,580 @@
|
|||
<?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: Config.php,v 1.1 2006/07/18 00:53:10 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
/** A configuration is a production rule of the grammar together with
|
||||
* a mark (dot) showing how much of that rule has been processed so far.
|
||||
*
|
||||
* Configurations also contain a follow-set which is a list of terminal
|
||||
* symbols which are allowed to immediately follow the end of the rule.
|
||||
* Every configuration is recorded as an instance of the following class.
|
||||
*
|
||||
* @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 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_Config
|
||||
{
|
||||
const COMPLETE = 1;
|
||||
const INCOMPLETE = 2;
|
||||
/**
|
||||
* The parser rule upon with the configuration is based.
|
||||
*
|
||||
* A parser rule is something like:
|
||||
* <pre>
|
||||
* blah ::= FOO bar.
|
||||
* </pre>
|
||||
* @var PHP_ParserGenerator_Rule
|
||||
*/
|
||||
public $rp;
|
||||
/**
|
||||
* The parse point.
|
||||
*
|
||||
* This is the index into the right-hand side of a rule that is
|
||||
* represented by this configuration. In other words, possible
|
||||
* dots for this rule:
|
||||
*
|
||||
* <pre>
|
||||
* blah ::= FOO bar.
|
||||
* </pre>
|
||||
*
|
||||
* are (represented by "[here]"):
|
||||
*
|
||||
* <pre>
|
||||
* blah ::= [here] FOO bar.
|
||||
* blah ::= FOO [here] bar.
|
||||
* blah ::= FOO bar [here].
|
||||
* </pre>
|
||||
* @var int
|
||||
*/
|
||||
public $dot;
|
||||
/**
|
||||
* Follow-set for this configuration only
|
||||
*
|
||||
* This is the list of terminals and non-terminals that
|
||||
* can follow this configuration.
|
||||
* @var array
|
||||
*/
|
||||
public $fws;
|
||||
/**
|
||||
* Follow-set forward propagation links.
|
||||
* @var PHP_ParserGenerator_PropagationLink
|
||||
*/
|
||||
public $fplp;
|
||||
/**
|
||||
* Follow-set backwards propagation links
|
||||
* @var PHP_ParserGenerator_PropagationLink
|
||||
*/
|
||||
public $bplp;
|
||||
/**
|
||||
* State that contains this configuration
|
||||
* @var PHP_ParserGenerator_State
|
||||
*/
|
||||
public $stp;
|
||||
/* enum {
|
||||
COMPLETE, /* The status is used during followset and
|
||||
INCOMPLETE /* shift computations
|
||||
} */
|
||||
/**
|
||||
* Status during followset and shift computations.
|
||||
*
|
||||
* One of PHP_ParserGenerator_Config::COMPLETE or
|
||||
* PHP_ParserGenerator_Config::INCOMPLETE.
|
||||
* @var int
|
||||
*/
|
||||
public $status;
|
||||
/**
|
||||
* Next configuration in the state.
|
||||
*
|
||||
* Index of next PHP_ParserGenerator_Config object.
|
||||
* @var int
|
||||
*/
|
||||
public $next;
|
||||
/**
|
||||
* Index of the next basis configuration PHP_ParserGenerator_Config object
|
||||
* @var int
|
||||
*/
|
||||
public $bp;
|
||||
|
||||
/**
|
||||
* Top of the list of configurations for the current state.
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static $current;
|
||||
/**
|
||||
* Last on the list of configurations for the current state.
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static $currentend;
|
||||
|
||||
/**
|
||||
* Top of the list of basis configurations for the current state.
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static $basis;
|
||||
/**
|
||||
* Last on the list of basis configurations for the current state.
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static $basisend;
|
||||
|
||||
/**
|
||||
* Associative array representation of the linked list of configurations
|
||||
* found in {@link $current}
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $x4a = array();
|
||||
|
||||
/**
|
||||
* Return a pointer to a new configuration
|
||||
* @return PHP_ParserGenerator_Config
|
||||
*/
|
||||
private static function newconfig()
|
||||
{
|
||||
return new PHP_ParserGenerator_Config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the current configuration for the .out file
|
||||
*
|
||||
* @param PHP_ParserGenerator_Config $cfp
|
||||
* @see PHP_ParserGenerator_Data::ReportOutput()
|
||||
*/
|
||||
public static function Configshow(PHP_ParserGenerator_Config $cfp)
|
||||
{
|
||||
$fp = fopen('php://output', 'w');
|
||||
while ($cfp) {
|
||||
if ($cfp->dot == $cfp->rp->nrhs) {
|
||||
$buf = sprintf('(%d)', $cfp->rp->index);
|
||||
fprintf($fp, ' %5s ', $buf);
|
||||
} else {
|
||||
fwrite($fp,' ');
|
||||
}
|
||||
$cfp->ConfigPrint($fp);
|
||||
fwrite($fp, "\n");
|
||||
if (0) {
|
||||
//SetPrint(fp,cfp->fws,$this);
|
||||
//PlinkPrint(fp,cfp->fplp,"To ");
|
||||
//PlinkPrint(fp,cfp->bplp,"From");
|
||||
}
|
||||
$cfp = $cfp->next;
|
||||
}
|
||||
fwrite($fp, "\n");
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the configuration list builder for a new state.
|
||||
*/
|
||||
public static function Configlist_init()
|
||||
{
|
||||
self::$current = 0;
|
||||
self::$currentend = &self::$current;
|
||||
self::$basis = 0;
|
||||
self::$basisend = &self::$basis;
|
||||
self::$x4a = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all data from the table.
|
||||
*
|
||||
* Pass each data to the function $f as it is removed if
|
||||
* $f is a valid callback.
|
||||
* @param callback|null
|
||||
* @see Configtable_clear()
|
||||
*/
|
||||
public static function Configtable_reset($f)
|
||||
{
|
||||
self::$current = 0;
|
||||
self::$currentend = &self::$current;
|
||||
self::$basis = 0;
|
||||
self::$basisend = &self::$basis;
|
||||
self::Configtable_clear(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all data from the associative array representation
|
||||
* of configurations.
|
||||
*
|
||||
* Pass each data to the function $f as it is removed if
|
||||
* $f is a valid callback.
|
||||
* @param callback|null
|
||||
*/
|
||||
public static function Configtable_clear($f)
|
||||
{
|
||||
if (!count(self::$x4a)) {
|
||||
return;
|
||||
}
|
||||
if ($f) {
|
||||
for ($i = 0; $i < count(self::$x4a); $i++) {
|
||||
call_user_func($f, self::$x4a[$i]->data);
|
||||
}
|
||||
}
|
||||
self::$x4a = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the configuration list builder for a new state.
|
||||
* @see Configtable_clear()
|
||||
*/
|
||||
public static function Configlist_reset()
|
||||
{
|
||||
self::Configtable_clear(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add another configuration to the configuration list for this parser state.
|
||||
* @param PHP_ParserGenerator_Rule the rule
|
||||
* @param int Index into the right-hand side of the rule where the dot goes
|
||||
* @return PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static function Configlist_add($rp, $dot)
|
||||
{
|
||||
$model = new PHP_ParserGenerator_Config;
|
||||
$model->rp = $rp;
|
||||
$model->dot = $dot;
|
||||
$cfp = self::Configtable_find($model);
|
||||
if ($cfp === 0) {
|
||||
$cfp = self::newconfig();
|
||||
$cfp->rp = $rp;
|
||||
$cfp->dot = $dot;
|
||||
$cfp->fws = array();
|
||||
$cfp->stp = 0;
|
||||
$cfp->fplp = $cfp->bplp = 0;
|
||||
$cfp->next = 0;
|
||||
$cfp->bp = 0;
|
||||
self::$currentend = $cfp;
|
||||
self::$currentend = &$cfp->next;
|
||||
self::Configtable_insert($cfp);
|
||||
}
|
||||
|
||||
return $cfp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a basis configuration to the configuration list for this parser state.
|
||||
*
|
||||
* Basis configurations are the root for a configuration. This method also
|
||||
* inserts the configuration into the regular list of configurations for this
|
||||
* reason.
|
||||
* @param PHP_ParserGenerator_Rule the rule
|
||||
* @param int Index into the right-hand side of the rule where the dot goes
|
||||
* @return PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static function Configlist_addbasis($rp, $dot)
|
||||
{
|
||||
$model = new PHP_ParserGenerator_Config;
|
||||
$model->rp = $rp;
|
||||
$model->dot = $dot;
|
||||
$cfp = self::Configtable_find($model);
|
||||
if ($cfp === 0) {
|
||||
$cfp = self::newconfig();
|
||||
$cfp->rp = $rp;
|
||||
$cfp->dot = $dot;
|
||||
$cfp->fws = array();
|
||||
$cfp->stp = 0;
|
||||
$cfp->fplp = $cfp->bplp = 0;
|
||||
$cfp->next = 0;
|
||||
$cfp->bp = 0;
|
||||
self::$currentend = $cfp;
|
||||
self::$currentend = &$cfp->next;
|
||||
self::$basisend = $cfp;
|
||||
self::$basisend = &$cfp->bp;
|
||||
self::Configtable_insert($cfp);
|
||||
}
|
||||
|
||||
return $cfp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the closure of the configuration list.
|
||||
*
|
||||
* This calculates all of the possible continuations of
|
||||
* each configuration, ensuring that each state accounts
|
||||
* for every configuration that could arrive at that state.
|
||||
*/
|
||||
public static function Configlist_closure(PHP_ParserGenerator_Data $lemp)
|
||||
{
|
||||
for ($cfp = self::$current; $cfp; $cfp = $cfp->next) {
|
||||
$rp = $cfp->rp;
|
||||
$dot = $cfp->dot;
|
||||
if ($dot >= $rp->nrhs) {
|
||||
continue;
|
||||
}
|
||||
$sp = $rp->rhs[$dot];
|
||||
if ($sp->type == PHP_ParserGenerator_Symbol::NONTERMINAL) {
|
||||
if ($sp->rule === 0 && $sp !== $lemp->errsym) {
|
||||
PHP_ParserGenerator::ErrorMsg($lemp->filename, $rp->line,
|
||||
"Nonterminal \"%s\" has no rules.", $sp->name);
|
||||
$lemp->errorcnt++;
|
||||
}
|
||||
for ($newrp = $sp->rule; $newrp; $newrp = $newrp->nextlhs) {
|
||||
$newcfp = self::Configlist_add($newrp, 0);
|
||||
for ($i = $dot + 1; $i < $rp->nrhs; $i++) {
|
||||
$xsp = $rp->rhs[$i];
|
||||
if ($xsp->type == PHP_ParserGenerator_Symbol::TERMINAL) {
|
||||
$newcfp->fws[$xsp->index] = 1;
|
||||
break;
|
||||
} elseif ($xsp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) {
|
||||
for ($k = 0; $k < $xsp->nsubsym; $k++) {
|
||||
$newcfp->fws[$xsp->subsym[$k]->index] = 1;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
$a = array_diff_key($xsp->firstset, $newcfp->fws);
|
||||
$newcfp->fws += $a;
|
||||
if ($xsp->lambda === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($i == $rp->nrhs) {
|
||||
PHP_ParserGenerator_PropagationLink::Plink_add($cfp->fplp, $newcfp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the configuration list
|
||||
* @uses Configcmp()
|
||||
*/
|
||||
public static function Configlist_sort()
|
||||
{
|
||||
$a = 0;
|
||||
//self::Configshow(self::$current);
|
||||
self::$current = PHP_ParserGenerator::msort(self::$current,'next', array('PHP_ParserGenerator_Config', 'Configcmp'));
|
||||
//self::Configshow(self::$current);
|
||||
self::$currentend = &$a;
|
||||
self::$currentend = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the configuration list
|
||||
* @uses Configcmp
|
||||
*/
|
||||
public static function Configlist_sortbasis()
|
||||
{
|
||||
$a = 0;
|
||||
self::$basis = PHP_ParserGenerator::msort(self::$current,'bp', array('PHP_ParserGenerator_Config', 'Configcmp'));
|
||||
self::$basisend = &$a;
|
||||
self::$basisend = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the head of the configuration list and
|
||||
* reset the list
|
||||
* @see $current
|
||||
* @return PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static function Configlist_return()
|
||||
{
|
||||
$old = self::$current;
|
||||
self::$current = 0;
|
||||
self::$currentend = &self::$current;
|
||||
|
||||
return $old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the head of the basis list and
|
||||
* reset the list
|
||||
* @see $basis
|
||||
* @return PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static function Configlist_basis()
|
||||
{
|
||||
$old = self::$basis;
|
||||
self::$basis = 0;
|
||||
self::$basisend = &self::$basis;
|
||||
|
||||
return $old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all elements of the given configuration list
|
||||
* @param PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static function Configlist_eat($cfp)
|
||||
{
|
||||
$nextcfp = null;
|
||||
for (; $cfp; $cfp = $nextcfp) {
|
||||
$nextcfp = $cfp->next;
|
||||
if ($cfp->fplp !=0) {
|
||||
throw new Exception('fplp of configuration non-zero?');
|
||||
}
|
||||
if ($cfp->bplp !=0) {
|
||||
throw new Exception('bplp of configuration non-zero?');
|
||||
}
|
||||
if ($cfp->fws) {
|
||||
$cfp->fws = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two configurations for sorting purposes.
|
||||
*
|
||||
* Configurations based on higher precedence rules
|
||||
* (those earlier in the file) are chosen first. Two
|
||||
* configurations that are the same rule are sorted by
|
||||
* dot (see {@link $dot}), and those configurations
|
||||
* with a dot closer to the left-hand side are chosen first.
|
||||
* @param unknown_type $a
|
||||
* @param unknown_type $b
|
||||
* @return unknown
|
||||
*/
|
||||
public static function Configcmp($a, $b)
|
||||
{
|
||||
$x = $a->rp->index - $b->rp->index;
|
||||
if (!$x) {
|
||||
$x = $a->dot - $b->dot;
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out information on this configuration.
|
||||
*
|
||||
* @param resource $fp
|
||||
* @see PHP_ParserGenerator_Data::ReportOutput()
|
||||
*/
|
||||
public function ConfigPrint($fp)
|
||||
{
|
||||
$rp = $this->rp;
|
||||
fprintf($fp, "%s ::=", $rp->lhs->name);
|
||||
for ($i = 0; $i <= $rp->nrhs; $i++) {
|
||||
if ($i === $this->dot) {
|
||||
fwrite($fp,' *');
|
||||
}
|
||||
if ($i === $rp->nrhs) {
|
||||
break;
|
||||
}
|
||||
$sp = $rp->rhs[$i];
|
||||
fprintf($fp,' %s', $sp->name);
|
||||
if ($sp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) {
|
||||
for ($j = 1; $j < $sp->nsubsym; $j++) {
|
||||
fprintf($fp, '|%s', $sp->subsym[$j]->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a configuration for the associative array {@link $x4a}
|
||||
*/
|
||||
private static function confighash(PHP_ParserGenerator_Config $a)
|
||||
{
|
||||
$h = 0;
|
||||
$h = $h * 571 + $a->rp->index * 37 + $a->dot;
|
||||
|
||||
return $h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new record into the array. Return TRUE if successful.
|
||||
* Prior data with the same key is NOT overwritten
|
||||
*/
|
||||
public static function Configtable_insert(PHP_ParserGenerator_Config $data)
|
||||
{
|
||||
$h = self::confighash($data);
|
||||
if (isset(self::$x4a[$h])) {
|
||||
$np = self::$x4a[$h];
|
||||
} else {
|
||||
$np = 0;
|
||||
}
|
||||
while ($np) {
|
||||
if (self::Configcmp($np->data, $data) == 0) {
|
||||
/* An existing entry with the same key is found. */
|
||||
/* Fail because overwrite is not allows. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
$np = $np->next;
|
||||
}
|
||||
/* Insert the new data */
|
||||
$np = array('data' => $data, 'next' => 0, 'from' => 0);
|
||||
$np = new PHP_ParserGenerator_StateNode;
|
||||
$np->data = $data;
|
||||
if (isset(self::$x4a[$h])) {
|
||||
self::$x4a[$h]->from = $np->next;
|
||||
$np->next = self::$x4a[$h];
|
||||
}
|
||||
$np->from = $np;
|
||||
self::$x4a[$h] = $np;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to data assigned to the given key. Return NULL
|
||||
* if no such key.
|
||||
* @return PHP_ParserGenerator_Config|0
|
||||
*/
|
||||
public static function Configtable_find(PHP_ParserGenerator_Config $key)
|
||||
{
|
||||
$h = self::confighash($key);
|
||||
if (!isset(self::$x4a[$h])) {
|
||||
return 0;
|
||||
}
|
||||
$np = self::$x4a[$h];
|
||||
while ($np) {
|
||||
if (self::Configcmp($np->data, $key) == 0) {
|
||||
break;
|
||||
}
|
||||
$np = $np->next;
|
||||
}
|
||||
|
||||
return $np ? $np->data : 0;
|
||||
}
|
||||
}
|
||||
1858
vendor/smarty/smarty-lexer/ParserGenerator/Data.php
vendored
Normal file
1858
vendor/smarty/smarty-lexer/ParserGenerator/Data.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
849
vendor/smarty/smarty-lexer/ParserGenerator/Parser.php
vendored
Normal file
849
vendor/smarty/smarty-lexer/ParserGenerator/Parser.php
vendored
Normal file
|
|
@ -0,0 +1,849 @@
|
|||
<?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: This source file is subject to version 3.01 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_01.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category php
|
||||
* @package PHP_ParserGenerator
|
||||
* @author Gregory Beaver <cellog@php.net>
|
||||
* @copyright 2006 Gregory Beaver
|
||||
* @license http://www.php.net/license/3_01.txt PHP License 3.01
|
||||
* @version CVS: $Id: Parser.php,v 1.2 2007/03/02 16:36:24 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
* The grammar parser for lemon grammar files.
|
||||
*
|
||||
* @package PHP_ParserGenerator
|
||||
* @author Gregory Beaver <cellog@php.net>
|
||||
* @copyright 2006 Gregory Beaver
|
||||
* @license http://www.php.net/license/3_01.txt PHP License 3.01
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_Parser
|
||||
{
|
||||
const INITIALIZE = 1;
|
||||
const WAITING_FOR_DECL_OR_RULE = 2;
|
||||
const WAITING_FOR_DECL_KEYWORD = 3;
|
||||
const WAITING_FOR_DECL_ARG = 4;
|
||||
const WAITING_FOR_PRECEDENCE_SYMBOL = 5;
|
||||
const WAITING_FOR_ARROW = 6;
|
||||
const IN_RHS = 7;
|
||||
const LHS_ALIAS_1 = 8;
|
||||
const LHS_ALIAS_2 = 9;
|
||||
const LHS_ALIAS_3 = 10;
|
||||
const RHS_ALIAS_1 = 11;
|
||||
const RHS_ALIAS_2 = 12;
|
||||
const PRECEDENCE_MARK_1 = 13;
|
||||
const PRECEDENCE_MARK_2 = 14;
|
||||
const RESYNC_AFTER_RULE_ERROR = 15;
|
||||
const RESYNC_AFTER_DECL_ERROR = 16;
|
||||
const WAITING_FOR_DESTRUCTOR_SYMBOL = 17;
|
||||
const WAITING_FOR_DATATYPE_SYMBOL = 18;
|
||||
const WAITING_FOR_FALLBACK_ID = 19;
|
||||
|
||||
/**
|
||||
* Name of the input file
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $filename;
|
||||
/**
|
||||
* Linenumber at which current token starts
|
||||
* @var int
|
||||
*/
|
||||
public $tokenlineno;
|
||||
/**
|
||||
* Number of parsing errors so far
|
||||
* @var int
|
||||
*/
|
||||
public $errorcnt;
|
||||
/**
|
||||
* Index of current token within the input string
|
||||
* @var int
|
||||
*/
|
||||
public $tokenstart;
|
||||
/**
|
||||
* Global state vector
|
||||
* @var PHP_ParserGenerator_Data
|
||||
*/
|
||||
public $gp;
|
||||
/**
|
||||
* Parser state (one of the class constants for this class)
|
||||
*
|
||||
* - PHP_ParserGenerator_Parser::INITIALIZE,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_DECL_OR_RULE,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_DECL_KEYWORD,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_DECL_ARG,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_PRECEDENCE_SYMBOL,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_ARROW,
|
||||
* - PHP_ParserGenerator_Parser::IN_RHS,
|
||||
* - PHP_ParserGenerator_Parser::LHS_ALIAS_1,
|
||||
* - PHP_ParserGenerator_Parser::LHS_ALIAS_2,
|
||||
* - PHP_ParserGenerator_Parser::LHS_ALIAS_3,
|
||||
* - PHP_ParserGenerator_Parser::RHS_ALIAS_1,
|
||||
* - PHP_ParserGenerator_Parser::RHS_ALIAS_2,
|
||||
* - PHP_ParserGenerator_Parser::PRECEDENCE_MARK_1,
|
||||
* - PHP_ParserGenerator_Parser::PRECEDENCE_MARK_2,
|
||||
* - PHP_ParserGenerator_Parser::RESYNC_AFTER_RULE_ERROR,
|
||||
* - PHP_ParserGenerator_Parser::RESYNC_AFTER_DECL_ERROR,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_DESTRUCTOR_SYMBOL,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_DATATYPE_SYMBOL,
|
||||
* - PHP_ParserGenerator_Parser::WAITING_FOR_FALLBACK_ID
|
||||
* @var int
|
||||
*/
|
||||
public $state;
|
||||
/**
|
||||
* The fallback token
|
||||
* @var PHP_ParserGenerator_Symbol
|
||||
*/
|
||||
public $fallback;
|
||||
/**
|
||||
* Left-hand side of the current rule
|
||||
* @var PHP_ParserGenerator_Symbol
|
||||
*/
|
||||
public $lhs;
|
||||
/**
|
||||
* Alias for the LHS
|
||||
* @var string
|
||||
*/
|
||||
public $lhsalias;
|
||||
/**
|
||||
* Number of right-hand side symbols seen
|
||||
* @var int
|
||||
*/
|
||||
public $nrhs;
|
||||
/**
|
||||
* Right-hand side symbols
|
||||
* @var array array of {@link PHP_ParserGenerator_Symbol} objects
|
||||
*/
|
||||
public $rhs = array();
|
||||
/**
|
||||
* Aliases for each RHS symbol name (or NULL)
|
||||
* @var array array of strings
|
||||
*/
|
||||
public $alias = array();
|
||||
/**
|
||||
* Previous rule parsed
|
||||
* @var PHP_ParserGenerator_Rule
|
||||
*/
|
||||
public $prevrule;
|
||||
/**
|
||||
* Keyword of a declaration
|
||||
*
|
||||
* This is one of the %keyword keywords in the grammar file
|
||||
* @var string
|
||||
*/
|
||||
public $declkeyword;
|
||||
/**
|
||||
* Where the declaration argument should be put
|
||||
*
|
||||
* This is assigned as a reference to an internal variable
|
||||
* @var mixed
|
||||
*/
|
||||
public $declargslot = array();
|
||||
/**
|
||||
* Where the declaration linenumber is put
|
||||
*
|
||||
* This is assigned as a reference to an internal variable
|
||||
* @var mixed
|
||||
*/
|
||||
public $decllnslot;
|
||||
/*enum e_assoc*/
|
||||
public $declassoc; /* Assign this association to decl arguments */
|
||||
public $preccounter; /* Assign this precedence to decl arguments */
|
||||
/**
|
||||
* @var PHP_ParserGenerator_Rule
|
||||
*/
|
||||
public $firstrule; /* Pointer to first rule in the grammar */
|
||||
/**
|
||||
* @var PHP_ParserGenerator_Rule
|
||||
*/
|
||||
public $lastrule; /* Pointer to the most recently parsed rule */
|
||||
|
||||
/**
|
||||
* @var PHP_ParserGenerator
|
||||
*/
|
||||
private $lemon;
|
||||
|
||||
public function __construct(PHP_ParserGenerator $lem)
|
||||
{
|
||||
$this->lemon = $lem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the preprocessor over the input file text. The Lemon variable
|
||||
* $azDefine contains the names of all defined
|
||||
* macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and
|
||||
* comments them out. Text in between is also commented out as appropriate.
|
||||
* @param string
|
||||
*/
|
||||
private function preprocess_input(&$z)
|
||||
{
|
||||
$start = 0;
|
||||
$lineno = $exclude = 0;
|
||||
for ($i=0; $i < strlen($z); $i++) {
|
||||
if ($z[$i] == "\n") {
|
||||
$lineno++;
|
||||
}
|
||||
if ($z[$i] != '%' || ($i > 0 && $z[$i-1] != "\n")) {
|
||||
continue;
|
||||
}
|
||||
if (substr($z, $i, 6) === "%endif" && trim($z[$i+6]) === '') {
|
||||
if ($exclude) {
|
||||
$exclude--;
|
||||
if ($exclude === 0) {
|
||||
for ($j = $start; $j < $i; $j++) {
|
||||
if ($z[$j] != "\n") $z[$j] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
for ($j = $i; $j < strlen($z) && $z[$j] != "\n"; $j++) {
|
||||
$z[$j] = ' ';
|
||||
}
|
||||
} elseif (substr($z, $i, 6) === "%ifdef" && trim($z[$i+6]) === '' ||
|
||||
substr($z, $i, 7) === "%ifndef" && trim($z[$i+7]) === '') {
|
||||
if ($exclude) {
|
||||
$exclude++;
|
||||
} else {
|
||||
$j = $i;
|
||||
$n = strtok(substr($z, $j), " \t");
|
||||
$exclude = 1;
|
||||
if (isset($this->lemon->azDefine[$n])) {
|
||||
$exclude = 0;
|
||||
}
|
||||
if ($z[$i + 3]=='n') {
|
||||
// this is a rather obtuse way of checking whether this is %ifndef
|
||||
$exclude = !$exclude;
|
||||
}
|
||||
if ($exclude) {
|
||||
$start = $i;
|
||||
$start_lineno = $lineno;
|
||||
}
|
||||
}
|
||||
//for ($j = $i; $j < strlen($z) && $z[$j] != "\n"; $j++) $z[$j] = ' ';
|
||||
$j = strpos(substr($z, $i), "\n");
|
||||
if ($j === false) {
|
||||
$z = substr($z, 0, $i); // remove instead of adding ' '
|
||||
} else {
|
||||
$z = substr($z, 0, $i) . substr($z, $i + $j); // remove instead of adding ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($exclude) {
|
||||
throw new Exception("unterminated %ifdef starting on line $start_lineno\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In spite of its name, this function is really a scanner.
|
||||
*
|
||||
* It reads in the entire input file (all at once) then tokenizes it.
|
||||
* Each token is passed to the function "parseonetoken" which builds all
|
||||
* the appropriate data structures in the global state vector "gp".
|
||||
* @param PHP_ParserGenerator_Data
|
||||
*/
|
||||
public function Parse(PHP_ParserGenerator_Data $gp)
|
||||
{
|
||||
$startline = 0;
|
||||
|
||||
$this->gp = $gp;
|
||||
$this->filename = $gp->filename;
|
||||
$this->errorcnt = 0;
|
||||
$this->state = self::INITIALIZE;
|
||||
|
||||
/* Begin by reading the input file */
|
||||
$filebuf = file_get_contents($this->filename);
|
||||
if (!$filebuf) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, 0, "Can't open this file for reading.");
|
||||
$gp->errorcnt++;
|
||||
|
||||
return;
|
||||
}
|
||||
if (filesize($this->filename) != strlen($filebuf)) {
|
||||
ErrorMsg($this->filename, 0, "Can't read in all %d bytes of this file.",
|
||||
filesize($this->filename));
|
||||
$gp->errorcnt++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make an initial pass through the file to handle %ifdef and %ifndef */
|
||||
$this->preprocess_input($filebuf);
|
||||
|
||||
/* Now scan the text of the input file */
|
||||
$lineno = 1;
|
||||
for ($cp = 0, $c = $filebuf[0]; $cp < strlen($filebuf); $cp++) {
|
||||
$c = $filebuf[$cp];
|
||||
$lineno = substr_count(substr($filebuf, 0, $cp), "\n")+1;
|
||||
//if ($c == "\n") $lineno++; /* Keep track of the line number */
|
||||
if (trim($c) === '') {
|
||||
continue;
|
||||
} /* Skip all white space */
|
||||
if ($filebuf[$cp] == '/' && ($cp + 1 < strlen($filebuf)) && $filebuf[$cp + 1] == '/') {
|
||||
/* Skip C++ style comments */
|
||||
$cp += 2;
|
||||
$z = strpos(substr($filebuf, $cp), "\n");
|
||||
if ($z === false) {
|
||||
$cp = strlen($filebuf);
|
||||
break;
|
||||
}
|
||||
$lineno++;
|
||||
$cp += $z;
|
||||
continue;
|
||||
}
|
||||
if ($filebuf[$cp] == '/' && ($cp + 1 < strlen($filebuf)) && $filebuf[$cp + 1] == '*') {
|
||||
/* Skip C style comments */
|
||||
$cp += 2;
|
||||
$z = strpos(substr($filebuf, $cp), '*/');
|
||||
if ($z !== false) {
|
||||
$lineno += count(explode("\n", substr($filebuf, $cp, $z))) - 1;
|
||||
}
|
||||
$cp += $z + 1;
|
||||
continue;
|
||||
}
|
||||
$this->tokenstart = $cp; /* Mark the beginning of the token */
|
||||
$this->tokenlineno = $lineno; /* Linenumber on which token begins */
|
||||
if ($filebuf[$cp] == '"') { /* String literals */
|
||||
$cp++;
|
||||
$oldcp = $cp;
|
||||
$test = strpos(substr($filebuf, $cp), '"');
|
||||
if ($test === false) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $startline,
|
||||
"String starting on this line is not terminated before the end of the file.");
|
||||
$this->errorcnt++;
|
||||
$nextcp = $cp = strlen($filebuf);
|
||||
} else {
|
||||
$cp += $test;
|
||||
$nextcp = $cp + 1;
|
||||
}
|
||||
$lineno += count(explode("\n", substr($filebuf, $oldcp, $cp - $oldcp))) - 1;
|
||||
} elseif ($filebuf[$cp] == '{') { /* A block of C code */
|
||||
$cp++;
|
||||
for ($level = 1; $cp < strlen($filebuf) && ($level > 1 || $filebuf[$cp] != '}'); $cp++) {
|
||||
if ($filebuf[$cp] == "\n") {
|
||||
$lineno++;
|
||||
} elseif ($filebuf[$cp] == '{') {
|
||||
$level++;
|
||||
} elseif ($filebuf[$cp] == '}') {
|
||||
$level--;
|
||||
} elseif ($filebuf[$cp] == '/' && $filebuf[$cp + 1] == '*') {
|
||||
/* Skip comments */
|
||||
$cp += 2;
|
||||
$z = strpos(substr($filebuf, $cp), '*/');
|
||||
if ($z !== false) {
|
||||
$lineno += count(explode("\n", substr($filebuf, $cp, $z))) - 1;
|
||||
}
|
||||
$cp += $z + 2;
|
||||
} elseif ($filebuf[$cp] == '/' && $filebuf[$cp + 1] == '/') {
|
||||
/* Skip C++ style comments too */
|
||||
$cp += 2;
|
||||
$z = strpos(substr($filebuf, $cp), "\n");
|
||||
if ($z === false) {
|
||||
$cp = strlen($filebuf);
|
||||
break;
|
||||
} else {
|
||||
$lineno++;
|
||||
}
|
||||
$cp += $z;
|
||||
} elseif ($filebuf[$cp] == "'" || $filebuf[$cp] == '"') {
|
||||
/* String a character literals */
|
||||
$startchar = $filebuf[$cp];
|
||||
$prevc = 0;
|
||||
for ($cp++; $cp < strlen($filebuf) && ($filebuf[$cp] != $startchar || $prevc === '\\'); $cp++) {
|
||||
if ($filebuf[$cp] == "\n") {
|
||||
$lineno++;
|
||||
}
|
||||
if ($prevc === '\\') {
|
||||
$prevc = 0;
|
||||
} else {
|
||||
$prevc = $filebuf[$cp];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($cp >= strlen($filebuf)) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"PHP code starting on this line is not terminated before the end of the file.");
|
||||
$this->errorcnt++;
|
||||
$nextcp = $cp;
|
||||
} else {
|
||||
$nextcp = $cp + 1;
|
||||
}
|
||||
} elseif (preg_match('/[a-zA-Z0-9]/', $filebuf[$cp])) {
|
||||
/* Identifiers */
|
||||
preg_match('/[a-zA-Z0-9_]+/', substr($filebuf, $cp), $preg_results);
|
||||
$cp += strlen($preg_results[0]);
|
||||
$nextcp = $cp;
|
||||
} elseif ($filebuf[$cp] == ':' && $filebuf[$cp + 1] == ':' &&
|
||||
$filebuf[$cp + 2] == '=') {
|
||||
/* The operator "::=" */
|
||||
$cp += 3;
|
||||
$nextcp = $cp;
|
||||
} elseif (($filebuf[$cp] == '/' || $filebuf[$cp] == '|') &&
|
||||
preg_match('/[a-zA-Z]/', $filebuf[$cp + 1])) {
|
||||
$cp += 2;
|
||||
preg_match('/[a-zA-Z0-9_]+/', substr($filebuf, $cp), $preg_results);
|
||||
$cp += strlen($preg_results[0]);
|
||||
$nextcp = $cp;
|
||||
} else {
|
||||
/* All other (one character) operators */
|
||||
$cp ++;
|
||||
$nextcp = $cp;
|
||||
}
|
||||
$this->parseonetoken(substr($filebuf, $this->tokenstart,
|
||||
$cp - $this->tokenstart)); /* Parse the token */
|
||||
$cp = $nextcp - 1;
|
||||
}
|
||||
$gp->rule = $this->firstrule;
|
||||
$gp->errorcnt = $this->errorcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a single token
|
||||
* @param string token
|
||||
*/
|
||||
public function parseonetoken($token)
|
||||
{
|
||||
$x = $token;
|
||||
$this->a = 0; // for referencing in WAITING_FOR_DECL_KEYWORD
|
||||
if (PHP_ParserGenerator::DEBUG) {
|
||||
printf("%s:%d: Token=[%s] state=%d\n",
|
||||
$this->filename, $this->tokenlineno, $token, $this->state);
|
||||
}
|
||||
switch ($this->state) {
|
||||
case self::INITIALIZE:
|
||||
$this->prevrule = 0;
|
||||
$this->preccounter = 0;
|
||||
$this->firstrule = $this->lastrule = 0;
|
||||
$this->gp->nrule = 0;
|
||||
/* Fall thru to next case */
|
||||
case self::WAITING_FOR_DECL_OR_RULE:
|
||||
if ($x[0] == '%') {
|
||||
$this->state = self::WAITING_FOR_DECL_KEYWORD;
|
||||
} elseif (preg_match('/[a-z]/', $x[0])) {
|
||||
$this->lhs = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
$this->nrhs = 0;
|
||||
$this->lhsalias = 0;
|
||||
$this->state = self::WAITING_FOR_ARROW;
|
||||
} elseif ($x[0] == '{') {
|
||||
if ($this->prevrule === 0) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"There is no prior rule opon which to attach the code
|
||||
fragment which begins on this line.");
|
||||
$this->errorcnt++;
|
||||
} elseif ($this->prevrule->code != 0) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Code fragment beginning on this line is not the first \
|
||||
to follow the previous rule.");
|
||||
$this->errorcnt++;
|
||||
} else {
|
||||
$this->prevrule->line = $this->tokenlineno;
|
||||
$this->prevrule->code = substr($x, 1);
|
||||
}
|
||||
} elseif ($x[0] == '[') {
|
||||
$this->state = self::PRECEDENCE_MARK_1;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Token \"%s\" should be either \"%%\" or a nonterminal name.",
|
||||
$x);
|
||||
$this->errorcnt++;
|
||||
}
|
||||
break;
|
||||
case self::PRECEDENCE_MARK_1:
|
||||
if (!preg_match('/[A-Z]/', $x[0])) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"The precedence symbol must be a terminal.");
|
||||
$this->errorcnt++;
|
||||
} elseif ($this->prevrule === 0) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"There is no prior rule to assign precedence \"[%s]\".", $x);
|
||||
$this->errorcnt++;
|
||||
} elseif ($this->prevrule->precsym != 0) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Precedence mark on this line is not the first to follow the previous rule.");
|
||||
$this->errorcnt++;
|
||||
} else {
|
||||
$this->prevrule->precsym = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
}
|
||||
$this->state = self::PRECEDENCE_MARK_2;
|
||||
break;
|
||||
case self::PRECEDENCE_MARK_2:
|
||||
if ($x[0] != ']') {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Missing \"]\" on precedence mark.");
|
||||
$this->errorcnt++;
|
||||
}
|
||||
$this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
break;
|
||||
case self::WAITING_FOR_ARROW:
|
||||
if ($x[0] == ':' && $x[1] == ':' && $x[2] == '=') {
|
||||
$this->state = self::IN_RHS;
|
||||
} elseif ($x[0] == '(') {
|
||||
$this->state = self::LHS_ALIAS_1;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Expected to see a \":\" following the LHS symbol \"%s\".",
|
||||
$this->lhs->name);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::LHS_ALIAS_1:
|
||||
if (preg_match('/[A-Za-z]/', $x[0])) {
|
||||
$this->lhsalias = $x;
|
||||
$this->state = self::LHS_ALIAS_2;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"\"%s\" is not a valid alias for the LHS \"%s\"\n",
|
||||
$x, $this->lhs->name);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::LHS_ALIAS_2:
|
||||
if ($x[0] == ')') {
|
||||
$this->state = self::LHS_ALIAS_3;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Missing \")\" following LHS alias name \"%s\".",$this->lhsalias);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::LHS_ALIAS_3:
|
||||
if ($x == '::=') {
|
||||
$this->state = self::IN_RHS;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Missing \"->\" following: \"%s(%s)\".",
|
||||
$this->lhs->name, $this->lhsalias);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::IN_RHS:
|
||||
if ($x[0] == '.') {
|
||||
$rp = new PHP_ParserGenerator_Rule;
|
||||
$rp->ruleline = $this->tokenlineno;
|
||||
for ($i = 0; $i < $this->nrhs; $i++) {
|
||||
$rp->rhs[$i] = $this->rhs[$i];
|
||||
$rp->rhsalias[$i] = $this->alias[$i];
|
||||
}
|
||||
if (count(array_unique($rp->rhsalias)) != count($rp->rhsalias)) {
|
||||
$used = array();
|
||||
foreach ($rp->rhsalias as $i => $symbol) {
|
||||
if (!is_string($symbol)) {
|
||||
continue;
|
||||
}
|
||||
if (isset($used[$symbol])) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename,
|
||||
$this->tokenlineno,
|
||||
"RHS symbol \"%s\" used multiple times.",
|
||||
$symbol);
|
||||
$this->errorcnt++;
|
||||
} else {
|
||||
$used[$symbol] = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
$rp->lhs = $this->lhs;
|
||||
$rp->lhsalias = $this->lhsalias;
|
||||
$rp->nrhs = $this->nrhs;
|
||||
$rp->code = 0;
|
||||
$rp->precsym = 0;
|
||||
$rp->index = $this->gp->nrule++;
|
||||
$rp->nextlhs = $rp->lhs->rule;
|
||||
$rp->lhs->rule = $rp;
|
||||
$rp->next = 0;
|
||||
if ($this->firstrule === 0) {
|
||||
$this->firstrule = $this->lastrule = $rp;
|
||||
} else {
|
||||
$this->lastrule->next = $rp;
|
||||
$this->lastrule = $rp;
|
||||
}
|
||||
$this->prevrule = $rp;
|
||||
$this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
} elseif (preg_match('/[a-zA-Z]/', $x[0])) {
|
||||
if ($this->nrhs >= PHP_ParserGenerator::MAXRHS) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Too many symbols on RHS or rule beginning at \"%s\".",
|
||||
$x);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
} else {
|
||||
if (isset($this->rhs[$this->nrhs - 1])) {
|
||||
$msp = $this->rhs[$this->nrhs - 1];
|
||||
if ($msp->type == PHP_ParserGenerator_Symbol::MULTITERMINAL) {
|
||||
$inf = array_reduce($msp->subsym,
|
||||
array($this, '_printmulti'), '');
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
'WARNING: symbol ' . $x . ' will not' .
|
||||
' be part of previous multiterminal %s',
|
||||
substr($inf, 0, strlen($inf) - 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->rhs[$this->nrhs] = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
$this->alias[$this->nrhs] = 0;
|
||||
$this->nrhs++;
|
||||
}
|
||||
} elseif (($x[0] == '|' || $x[0] == '/') && $this->nrhs > 0) {
|
||||
$msp = $this->rhs[$this->nrhs - 1];
|
||||
if ($msp->type != PHP_ParserGenerator_Symbol::MULTITERMINAL) {
|
||||
$origsp = $msp;
|
||||
$msp = new PHP_ParserGenerator_Symbol;
|
||||
$msp->type = PHP_ParserGenerator_Symbol::MULTITERMINAL;
|
||||
$msp->nsubsym = 1;
|
||||
$msp->subsym = array($origsp);
|
||||
$msp->name = $origsp->name;
|
||||
$this->rhs[$this->nrhs - 1] = $msp;
|
||||
}
|
||||
$msp->nsubsym++;
|
||||
$msp->subsym[$msp->nsubsym - 1] = PHP_ParserGenerator_Symbol::Symbol_new(substr($x, 1));
|
||||
if (preg_match('/[a-z]/', $x[1]) ||
|
||||
preg_match('/[a-z]/', $msp->subsym[0]->name[0])) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Cannot form a compound containing a non-terminal");
|
||||
$this->errorcnt++;
|
||||
}
|
||||
} elseif ($x[0] == '(' && $this->nrhs > 0) {
|
||||
$this->state = self::RHS_ALIAS_1;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Illegal character on RHS of rule: \"%s\".", $x);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::RHS_ALIAS_1:
|
||||
if (preg_match('/[A-Za-z]/', $x[0])) {
|
||||
$this->alias[$this->nrhs - 1] = $x;
|
||||
$this->state = self::RHS_ALIAS_2;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
|
||||
$x, $this->rhs[$this->nrhs - 1]->name);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::RHS_ALIAS_2:
|
||||
if ($x[0] == ')') {
|
||||
$this->state = self::IN_RHS;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Missing \")\" following LHS alias name \"%s\".", $this->lhsalias);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_RULE_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::WAITING_FOR_DECL_KEYWORD:
|
||||
if (preg_match('/[A-Za-z]/', $x[0])) {
|
||||
$this->declkeyword = $x;
|
||||
$this->declargslot = &$this->a;
|
||||
$this->decllnslot = &$this->a;
|
||||
$this->state = self::WAITING_FOR_DECL_ARG;
|
||||
if ('name' == $x) {
|
||||
$this->declargslot = &$this->gp->name;
|
||||
} elseif ('include' == $x) {
|
||||
$this->declargslot = &$this->gp->include_code;
|
||||
$this->decllnslot = &$this->gp->includeln;
|
||||
} elseif ('include_class' == $x) {
|
||||
$this->declargslot = &$this->gp->include_classcode;
|
||||
$this->decllnslot = &$this->gp->include_classln;
|
||||
} elseif ('declare_class' == $x) {
|
||||
$this->declargslot = &$this->gp->declare_classcode;
|
||||
$this->decllnslot = &$this->gp->declare_classln;
|
||||
} elseif ('code' == $x) {
|
||||
$this->declargslot = &$this->gp->extracode;
|
||||
$this->decllnslot = &$this->gp->extracodeln;
|
||||
} elseif ('token_destructor' == $x) {
|
||||
$this->declargslot = &$this->gp->tokendest;
|
||||
$this->decllnslot = &$this->gp->tokendestln;
|
||||
} elseif ('default_destructor' == $x) {
|
||||
$this->declargslot = &$this->gp->vardest;
|
||||
$this->decllnslot = &$this->gp->vardestln;
|
||||
} elseif ('token_prefix' == $x) {
|
||||
$this->declargslot = &$this->gp->tokenprefix;
|
||||
} elseif ('syntax_error' == $x) {
|
||||
$this->declargslot = &$this->gp->error;
|
||||
$this->decllnslot = &$this->gp->errorln;
|
||||
} elseif ('parse_accept' == $x) {
|
||||
$this->declargslot = &$this->gp->accept;
|
||||
$this->decllnslot = &$this->gp->acceptln;
|
||||
} elseif ('parse_failure' == $x) {
|
||||
$this->declargslot = &$this->gp->failure;
|
||||
$this->decllnslot = &$this->gp->failureln;
|
||||
} elseif ('stack_overflow' == $x) {
|
||||
$this->declargslot = &$this->gp->overflow;
|
||||
$this->decllnslot = &$this->gp->overflowln;
|
||||
} elseif ('token_type' == $x) {
|
||||
$this->declargslot = &$this->gp->tokentype;
|
||||
} elseif ('default_type' == $x) {
|
||||
$this->declargslot = &$this->gp->vartype;
|
||||
} elseif ('stack_size' == $x) {
|
||||
$this->declargslot = &$this->gp->stacksize;
|
||||
} elseif ('start_symbol' == $x) {
|
||||
$this->declargslot = &$this->gp->start;
|
||||
} elseif ('left' == $x) {
|
||||
$this->preccounter++;
|
||||
$this->declassoc = PHP_ParserGenerator_Symbol::LEFT;
|
||||
$this->state = self::WAITING_FOR_PRECEDENCE_SYMBOL;
|
||||
} elseif ('right' == $x) {
|
||||
$this->preccounter++;
|
||||
$this->declassoc = PHP_ParserGenerator_Symbol::RIGHT;
|
||||
$this->state = self::WAITING_FOR_PRECEDENCE_SYMBOL;
|
||||
} elseif ('nonassoc' == $x) {
|
||||
$this->preccounter++;
|
||||
$this->declassoc = PHP_ParserGenerator_Symbol::NONE;
|
||||
$this->state = self::WAITING_FOR_PRECEDENCE_SYMBOL;
|
||||
} elseif ('destructor' == $x) {
|
||||
$this->state = self::WAITING_FOR_DESTRUCTOR_SYMBOL;
|
||||
} elseif ('type' == $x) {
|
||||
$this->state = self::WAITING_FOR_DATATYPE_SYMBOL;
|
||||
} elseif ('fallback' == $x) {
|
||||
$this->fallback = 0;
|
||||
$this->state = self::WAITING_FOR_FALLBACK_ID;
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Unknown declaration keyword: \"%%%s\".", $x);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_DECL_ERROR;
|
||||
}
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Illegal declaration keyword: \"%s\".", $x);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_DECL_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::WAITING_FOR_DESTRUCTOR_SYMBOL:
|
||||
if (!preg_match('/[A-Za-z]/', $x[0])) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Symbol name missing after %destructor keyword");
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_DECL_ERROR;
|
||||
} else {
|
||||
$sp = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
$this->declargslot = &$sp->destructor;
|
||||
$this->decllnslot = &$sp->destructorln;
|
||||
$this->state = self::WAITING_FOR_DECL_ARG;
|
||||
}
|
||||
break;
|
||||
case self::WAITING_FOR_DATATYPE_SYMBOL:
|
||||
if (!preg_match('/[A-Za-z]/', $x[0])) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Symbol name missing after %destructor keyword");
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_DECL_ERROR;
|
||||
} else {
|
||||
$sp = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
$this->declargslot = &$sp->datatype;
|
||||
$this->state = self::WAITING_FOR_DECL_ARG;
|
||||
}
|
||||
break;
|
||||
case self::WAITING_FOR_PRECEDENCE_SYMBOL:
|
||||
if ($x[0] == '.') {
|
||||
$this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
} elseif (preg_match('/[A-Z]/', $x[0])) {
|
||||
$sp = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
if ($sp->prec >= 0) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Symbol \"%s\" has already been given a precedence.", $x);
|
||||
$this->errorcnt++;
|
||||
} else {
|
||||
$sp->prec = $this->preccounter;
|
||||
$sp->assoc = $this->declassoc;
|
||||
}
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Can't assign a precedence to \"%s\".", $x);
|
||||
$this->errorcnt++;
|
||||
}
|
||||
break;
|
||||
case self::WAITING_FOR_DECL_ARG:
|
||||
if (preg_match('/[A-Za-z0-9{"]/', $x[0])) {
|
||||
if ($this->declargslot != 0) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"The argument \"%s\" to declaration \"%%%s\" is not the first.",
|
||||
$x[0] == '"' ? substr($x, 1) : $x, $this->declkeyword);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_DECL_ERROR;
|
||||
} else {
|
||||
$this->declargslot = ($x[0] == '"' || $x[0] == '{') ? substr($x, 1) : $x;
|
||||
$this->a = 1;
|
||||
if (!$this->decllnslot) {
|
||||
$this->decllnslot = $this->tokenlineno;
|
||||
}
|
||||
$this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
}
|
||||
} else {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"Illegal argument to %%%s: %s",$this->declkeyword, $x);
|
||||
$this->errorcnt++;
|
||||
$this->state = self::RESYNC_AFTER_DECL_ERROR;
|
||||
}
|
||||
break;
|
||||
case self::WAITING_FOR_FALLBACK_ID:
|
||||
if ($x[0] == '.') {
|
||||
$this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
} elseif (!preg_match('/[A-Z]/', $x[0])) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"%%fallback argument \"%s\" should be a token", $x);
|
||||
$this->errorcnt++;
|
||||
} else {
|
||||
$sp = PHP_ParserGenerator_Symbol::Symbol_new($x);
|
||||
if ($this->fallback === 0) {
|
||||
$this->fallback = $sp;
|
||||
} elseif (is_object($sp->fallback)) {
|
||||
PHP_ParserGenerator::ErrorMsg($this->filename, $this->tokenlineno,
|
||||
"More than one fallback assigned to token %s", $x);
|
||||
$this->errorcnt++;
|
||||
} else {
|
||||
$sp->fallback = $this->fallback;
|
||||
$this->gp->has_fallback = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case self::RESYNC_AFTER_RULE_ERROR:
|
||||
/* if ($x[0] == '.') $this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
** break; */
|
||||
case self::RESYNC_AFTER_DECL_ERROR:
|
||||
if ($x[0] == '.') {
|
||||
$this->state = self::WAITING_FOR_DECL_OR_RULE;
|
||||
}
|
||||
if ($x[0] == '%') {
|
||||
$this->state = self::WAITING_FOR_DECL_KEYWORD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a descriptive string for a multi-terminal token.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
* @return string
|
||||
*/
|
||||
private function _printmulti($a, $b)
|
||||
{
|
||||
if (!$a) {
|
||||
$a = '';
|
||||
}
|
||||
$a .= $b->name . '|';
|
||||
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
117
vendor/smarty/smarty-lexer/ParserGenerator/PropagationLink.php
vendored
Normal file
117
vendor/smarty/smarty-lexer/ParserGenerator/PropagationLink.php
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<?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: PropagationLink.php,v 1.1 2006/07/18 00:53:10 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
* A followset propagation link indicates that the contents of one
|
||||
* configuration followset should be propagated to another whenever
|
||||
* the first changes.
|
||||
*
|
||||
* @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 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
|
||||
class PHP_ParserGenerator_PropagationLink
|
||||
{
|
||||
/**
|
||||
* The configuration that defines this propagation link
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public $cfp;
|
||||
/**
|
||||
* The next propagation link
|
||||
* @var PHP_ParserGenerator_PropagationLink|0
|
||||
*/
|
||||
public $next = 0;
|
||||
|
||||
/**
|
||||
* Add a propagation link to the current list
|
||||
*
|
||||
* This prepends the configuration passed in to the first parameter
|
||||
* which is either 0 or a PHP_ParserGenerator_PropagationLink defining
|
||||
* an existing list.
|
||||
* @param PHP_ParserGenerator_PropagationLink|null
|
||||
* @param PHP_ParserGenerator_Config
|
||||
*/
|
||||
public static function Plink_add(&$plpp, PHP_ParserGenerator_Config $cfp)
|
||||
{
|
||||
$new = new PHP_ParserGenerator_PropagationLink;
|
||||
$new->next = $plpp;
|
||||
$plpp = $new;
|
||||
$new->cfp = $cfp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer every propagation link on the list "from" to the list "to"
|
||||
*/
|
||||
public static function Plink_copy(PHP_ParserGenerator_PropagationLink &$to,
|
||||
PHP_ParserGenerator_PropagationLink $from)
|
||||
{
|
||||
while ($from) {
|
||||
$nextpl = $from->next;
|
||||
$from->next = $to;
|
||||
$to = $from;
|
||||
$from = $nextpl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete every propagation link on the list
|
||||
* @param PHP_ParserGenerator_PropagationLink|0
|
||||
*/
|
||||
public static function Plink_delete($plp)
|
||||
{
|
||||
while ($plp) {
|
||||
$nextpl = $plp->next;
|
||||
$plp->next = 0;
|
||||
$plp = $nextpl;
|
||||
}
|
||||
}
|
||||
}
|
||||
141
vendor/smarty/smarty-lexer/ParserGenerator/Rule.php
vendored
Normal file
141
vendor/smarty/smarty-lexer/ParserGenerator/Rule.php
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
<?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: Rule.php,v 1.1 2006/07/18 00:53:10 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
* Each production rule in the grammar is stored in this class
|
||||
*
|
||||
* @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 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_Rule
|
||||
{
|
||||
/**
|
||||
* Left-hand side of the rule
|
||||
* @var array an array of {@link PHP_ParserGenerator_Symbol} objects
|
||||
*/
|
||||
public $lhs;
|
||||
/**
|
||||
* Alias for the LHS (NULL if none)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $lhsalias = array();
|
||||
/**
|
||||
* Line number for the rule
|
||||
* @var int
|
||||
*/
|
||||
public $ruleline;
|
||||
/**
|
||||
* Number of right-hand side symbols
|
||||
*/
|
||||
public $nrhs;
|
||||
/**
|
||||
* The right-hand side symbols
|
||||
* @var array an array of {@link PHP_ParserGenerator_Symbol} objects
|
||||
*/
|
||||
public $rhs;
|
||||
/**
|
||||
* Aliases for each right-hand side symbol, or null if no alis.
|
||||
*
|
||||
* In this rule:
|
||||
* <pre>
|
||||
* foo ::= BAR(A) baz(B).
|
||||
* </pre>
|
||||
*
|
||||
* The right-hand side aliases are A for BAR, and B for baz.
|
||||
* @var array aliases are indexed by the right-hand side symbol index.
|
||||
*/
|
||||
public $rhsalias = array();
|
||||
/**
|
||||
* Line number at which code begins
|
||||
* @var int
|
||||
*/
|
||||
public $line;
|
||||
/**
|
||||
* The code executed when this rule is reduced
|
||||
*
|
||||
* <pre>
|
||||
* foo(R) ::= BAR(A) baz(B). {R = A + B;}
|
||||
* </pre>
|
||||
*
|
||||
* In the rule above, the code is "R = A + B;"
|
||||
* @var string|0
|
||||
*/
|
||||
public $code;
|
||||
/**
|
||||
* Precedence symbol for this rule
|
||||
* @var PHP_ParserGenerator_Symbol
|
||||
*/
|
||||
public $precsym;
|
||||
/**
|
||||
* An index number for this rule
|
||||
*
|
||||
* Used in both naming of reduce functions and determining which rule code
|
||||
* to use for reduce actions
|
||||
* @var int
|
||||
*/
|
||||
public $index;
|
||||
/**
|
||||
* True if this rule is ever reduced
|
||||
* @var boolean
|
||||
*/
|
||||
public $canReduce;
|
||||
/**
|
||||
* Next rule with the same left-hand side
|
||||
* @var PHP_ParserGenerator_Rule|0
|
||||
*/
|
||||
public $nextlhs;
|
||||
/**
|
||||
* Next rule in the global list
|
||||
* @var PHP_ParserGenerator_Rule|0
|
||||
*/
|
||||
public $next;
|
||||
}
|
||||
284
vendor/smarty/smarty-lexer/ParserGenerator/State.php
vendored
Normal file
284
vendor/smarty/smarty-lexer/ParserGenerator/State.php
vendored
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
<?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: State.php,v 1.1 2006/07/18 00:53:10 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* The structure used to represent a state in the associative array
|
||||
* for a PHP_ParserGenerator_Config.
|
||||
* @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 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_StateNode
|
||||
{
|
||||
public $key;
|
||||
public $data;
|
||||
public $from = 0;
|
||||
public $next = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each state of the generated parser's finite state machine
|
||||
* is encoded as an instance of this class
|
||||
*
|
||||
* @package PHP_ParserGenerator
|
||||
* @author Gregory Beaver <cellog@php.net>
|
||||
* @copyright 2006 Gregory Beaver
|
||||
* @license http://www.php.net/license/3_01.txt PHP License 3.01
|
||||
* @version 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_State
|
||||
{
|
||||
/**
|
||||
* The basis configurations for this state
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public $bp;
|
||||
/**
|
||||
* All configurations in this state
|
||||
* @var PHP_ParserGenerator_Config
|
||||
*/
|
||||
public $cfp;
|
||||
/**
|
||||
* Sequential number for this state
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $statenum;
|
||||
/**
|
||||
* Linked list of actions for this state.
|
||||
* @var PHP_ParserGenerator_Action
|
||||
*/
|
||||
public $ap;
|
||||
/**
|
||||
* Number of terminal (token) actions
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $nTknAct,
|
||||
/**
|
||||
* Number of non-terminal actions
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
$nNtAct;
|
||||
/**
|
||||
* The offset into the $yy_action table for terminal tokens.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $iTknOfst,
|
||||
/**
|
||||
* The offset into the $yy_action table for non-terminals.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
$iNtOfst;
|
||||
/**
|
||||
* Default action
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $iDflt;
|
||||
/**
|
||||
* Associative array of PHP_ParserGenerator_State objects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $x3a = array();
|
||||
/**
|
||||
* Array of PHP_ParserGenerator_State objects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $states = array();
|
||||
|
||||
/**
|
||||
* Compare two states for sorting purposes. The smaller state is the
|
||||
* one with the most non-terminal actions. If they have the same number
|
||||
* of non-terminal actions, then the smaller is the one with the most
|
||||
* token actions.
|
||||
*/
|
||||
public static function stateResortCompare($a, $b)
|
||||
{
|
||||
$n = $b->nNtAct - $a->nNtAct;
|
||||
if ($n === 0) {
|
||||
$n = $b->nTknAct - $a->nTknAct;
|
||||
}
|
||||
|
||||
return $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two states based on their configurations
|
||||
*
|
||||
* @param PHP_ParserGenerator_Config|0 $a
|
||||
* @param PHP_ParserGenerator_Config|0 $b
|
||||
* @return int
|
||||
*/
|
||||
public static function statecmp($a, $b)
|
||||
{
|
||||
for ($rc = 0; $rc == 0 && $a && $b; $a = $a->bp, $b = $b->bp) {
|
||||
$rc = $a->rp->index - $b->rp->index;
|
||||
if ($rc === 0) {
|
||||
$rc = $a->dot - $b->dot;
|
||||
}
|
||||
}
|
||||
if ($rc == 0) {
|
||||
if ($a) {
|
||||
$rc = 1;
|
||||
}
|
||||
if ($b) {
|
||||
$rc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a state based on its configuration
|
||||
* @return int
|
||||
*/
|
||||
private static function statehash(PHP_ParserGenerator_Config $a)
|
||||
{
|
||||
$h = 0;
|
||||
while ($a) {
|
||||
$h = $h * 571 + $a->rp->index * 37 + $a->dot;
|
||||
$a = $a->bp;
|
||||
}
|
||||
|
||||
return (int) $h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to data assigned to the given key. Return NULL
|
||||
* if no such key.
|
||||
* @param PHP_ParserGenerator_Config
|
||||
* @return null|PHP_ParserGenerator_State
|
||||
*/
|
||||
public static function State_find(PHP_ParserGenerator_Config $key)
|
||||
{
|
||||
if (!count(self::$x3a)) {
|
||||
return 0;
|
||||
}
|
||||
$h = self::statehash($key);
|
||||
if (!isset(self::$x3a[$h])) {
|
||||
return 0;
|
||||
}
|
||||
$np = self::$x3a[$h];
|
||||
while ($np) {
|
||||
if (self::statecmp($np->key, $key) == 0) {
|
||||
break;
|
||||
}
|
||||
$np = $np->next;
|
||||
}
|
||||
|
||||
return $np ? $np->data : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new record into the array. Return TRUE if successful.
|
||||
* Prior data with the same key is NOT overwritten
|
||||
*
|
||||
* @param PHP_ParserGenerator_State $state
|
||||
* @param PHP_ParserGenerator_Config $key
|
||||
* @return unknown
|
||||
*/
|
||||
public static function State_insert(PHP_ParserGenerator_State $state,
|
||||
PHP_ParserGenerator_Config $key)
|
||||
{
|
||||
$h = self::statehash($key);
|
||||
if (isset(self::$x3a[$h])) {
|
||||
$np = self::$x3a[$h];
|
||||
} else {
|
||||
$np = 0;
|
||||
}
|
||||
while ($np) {
|
||||
if (self::statecmp($np->key, $key) == 0) {
|
||||
/* An existing entry with the same key is found. */
|
||||
/* Fail because overwrite is not allows. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
$np = $np->next;
|
||||
}
|
||||
/* Insert the new data */
|
||||
$np = new PHP_ParserGenerator_StateNode;
|
||||
$np->key = $key;
|
||||
$np->data = $state;
|
||||
self::$states[] = $np;
|
||||
// the original lemon code sets the from link always to itself
|
||||
// setting up a faulty double-linked list
|
||||
// however, the from links are never used, so I suspect a copy/paste
|
||||
// error from a standard algorithm that was never caught
|
||||
if (isset(self::$x3a[$h])) {
|
||||
self::$x3a[$h]->from = $np; // lemon has $np->next here
|
||||
} else {
|
||||
self::$x3a[$h] = 0; // dummy to avoid notice
|
||||
}
|
||||
$np->next = self::$x3a[$h];
|
||||
self::$x3a[$h] = $np;
|
||||
$np->from = self::$x3a[$h];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array indexed by state number
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function State_arrayof()
|
||||
{
|
||||
return self::$states;
|
||||
}
|
||||
}
|
||||
288
vendor/smarty/smarty-lexer/ParserGenerator/Symbol.php
vendored
Normal file
288
vendor/smarty/smarty-lexer/ParserGenerator/Symbol.php
vendored
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
<?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: Symbol.php,v 1.1 2006/07/18 00:53:10 cellog Exp $
|
||||
* @since File available since Release 0.1.0
|
||||
*/
|
||||
/**
|
||||
* Symbols (terminals and nonterminals) of the grammar are stored in this class
|
||||
*
|
||||
* @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 0.1.5
|
||||
* @since Class available since Release 0.1.0
|
||||
*/
|
||||
class PHP_ParserGenerator_Symbol
|
||||
{
|
||||
/**
|
||||
* Symbols that start with a capital letter like FOO.
|
||||
*
|
||||
* These are tokens directly from the lexer
|
||||
*/
|
||||
const TERMINAL = 1;
|
||||
/**
|
||||
* Symbols that start with a lower-case letter like foo.
|
||||
*
|
||||
* These are grammar rules like "foo ::= BLAH."
|
||||
*/
|
||||
const NONTERMINAL = 2;
|
||||
/**
|
||||
* Multiple terminal symbols.
|
||||
*
|
||||
* These are a grammar rule that consists of several terminals like
|
||||
* FOO|BAR|BAZ. Note that non-terminals cannot be in a multi-terminal,
|
||||
* and a multi-terminal acts like a single terminal.
|
||||
*
|
||||
* "FOO|BAR FOO|BAZ" is actually two multi-terminals, FOO|BAR and FOO|BAZ.
|
||||
*/
|
||||
const MULTITERMINAL = 3;
|
||||
|
||||
const LEFT = 1;
|
||||
const RIGHT = 2;
|
||||
const NONE = 3;
|
||||
const UNK = 4;
|
||||
/**
|
||||
* Name of the symbol
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* Index of this symbol.
|
||||
*
|
||||
* This will ultimately end up representing the symbol in the generated
|
||||
* parser
|
||||
* @var int
|
||||
*/
|
||||
public $index;
|
||||
/**
|
||||
* Symbol type
|
||||
*
|
||||
* One of PHP_ParserGenerator_Symbol::TERMINAL,
|
||||
* PHP_ParserGenerator_Symbol::NONTERMINAL or
|
||||
* PHP_ParserGenerator_Symbol::MULTITERMINAL
|
||||
* @var int
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* Linked list of rules that use this symbol, if it is a non-terminal.
|
||||
* @var PHP_ParserGenerator_Rule
|
||||
*/
|
||||
public $rule;
|
||||
/**
|
||||
* Fallback token in case this token doesn't parse
|
||||
* @var PHP_ParserGenerator_Symbol
|
||||
*/
|
||||
public $fallback;
|
||||
/**
|
||||
* Precendence, if defined.
|
||||
*
|
||||
* -1 if no unusual precedence
|
||||
* @var int
|
||||
*/
|
||||
public $prec = -1;
|
||||
/**
|
||||
* Associativity if precedence is defined.
|
||||
*
|
||||
* One of PHP_ParserGenerator_Symbol::LEFT,
|
||||
* PHP_ParserGenerator_Symbol::RIGHT, PHP_ParserGenerator_Symbol::NONE
|
||||
* or PHP_ParserGenerator_Symbol::UNK
|
||||
* @var unknown_type
|
||||
*/
|
||||
public $assoc;
|
||||
/**
|
||||
* First-set for all rules of this symbol
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $firstset;
|
||||
/**
|
||||
* True if this symbol is a non-terminal and can generate an empty
|
||||
* result.
|
||||
*
|
||||
* For instance "foo ::= ."
|
||||
* @var boolean
|
||||
*/
|
||||
public $lambda;
|
||||
/**
|
||||
* Code that executes whenever this symbol is popped from the stack during
|
||||
* error processing.
|
||||
*
|
||||
* @var string|0
|
||||
*/
|
||||
public $destructor = 0;
|
||||
/**
|
||||
* Line number of destructor code
|
||||
* @var int
|
||||
*/
|
||||
public $destructorln;
|
||||
/**
|
||||
* Unused relic of the C version of Lemon.
|
||||
*
|
||||
* The data type of information held by this object. Only used
|
||||
* if this is a non-terminal
|
||||
* @var string
|
||||
*/
|
||||
public $datatype;
|
||||
/**
|
||||
* Unused relic of the C version of Lemon.
|
||||
*
|
||||
* The data type number. In the parser, the value
|
||||
* stack is a union. The .yy%d element of this
|
||||
* union is the correct data type for this object
|
||||
* @var string
|
||||
*/
|
||||
public $dtnum;
|
||||
/**#@+
|
||||
* The following fields are used by MULTITERMINALs only
|
||||
*/
|
||||
/**
|
||||
* Number of terminal symbols in the MULTITERMINAL
|
||||
*
|
||||
* This is of course the same as count($this->subsym)
|
||||
* @var int
|
||||
*/
|
||||
public $nsubsym;
|
||||
/**
|
||||
* Array of terminal symbols in the MULTITERMINAL
|
||||
* @var array an array of {@link PHP_ParserGenerator_Symbol} objects
|
||||
*/
|
||||
public $subsym = array();
|
||||
/**#@-*/
|
||||
/**
|
||||
* Singleton storage of symbols
|
||||
*
|
||||
* @var array an array of PHP_ParserGenerator_Symbol objects
|
||||
*/
|
||||
private static $symbol_table = array();
|
||||
/**
|
||||
* Return a pointer to the (terminal or nonterminal) symbol "x".
|
||||
* Create a new symbol if this is the first time "x" has been seen.
|
||||
* (this is a singleton)
|
||||
* @param string
|
||||
* @return PHP_ParserGenerator_Symbol
|
||||
*/
|
||||
public static function Symbol_new($x)
|
||||
{
|
||||
if (isset(self::$symbol_table[$x])) {
|
||||
return self::$symbol_table[$x];
|
||||
}
|
||||
$sp = new PHP_ParserGenerator_Symbol;
|
||||
$sp->name = $x;
|
||||
$sp->type = preg_match('/[A-Z]/', $x[0]) ? self::TERMINAL : self::NONTERMINAL;
|
||||
$sp->rule = 0;
|
||||
$sp->fallback = 0;
|
||||
$sp->prec = -1;
|
||||
$sp->assoc = self::UNK;
|
||||
$sp->firstset = array();
|
||||
$sp->lambda = false;
|
||||
$sp->destructor = 0;
|
||||
$sp->datatype = 0;
|
||||
self::$symbol_table[$sp->name] = $sp;
|
||||
|
||||
return $sp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of unique symbols
|
||||
* @return int
|
||||
*/
|
||||
public static function Symbol_count()
|
||||
{
|
||||
return count(self::$symbol_table);
|
||||
}
|
||||
|
||||
public static function Symbol_arrayof()
|
||||
{
|
||||
return array_values(self::$symbol_table);
|
||||
}
|
||||
|
||||
public static function Symbol_find($x)
|
||||
{
|
||||
if (isset(self::$symbol_table[$x])) {
|
||||
return self::$symbol_table[$x];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort function helper for symbols
|
||||
*
|
||||
* Symbols that begin with upper case letters (terminals or tokens)
|
||||
* must sort before symbols that begin with lower case letters
|
||||
* (non-terminals). Other than that, the order does not matter.
|
||||
*
|
||||
* We find experimentally that leaving the symbols in their original
|
||||
* order (the order they appeared in the grammar file) gives the
|
||||
* smallest parser tables in SQLite.
|
||||
* @param PHP_ParserGenerator_Symbol
|
||||
* @param PHP_ParserGenerator_Symbol
|
||||
*/
|
||||
public static function sortSymbols($a, $b)
|
||||
{
|
||||
$i1 = $a->index + 10000000*(ord($a->name[0]) > ord('Z'));
|
||||
$i2 = $b->index + 10000000*(ord($b->name[0]) > ord('Z'));
|
||||
|
||||
return $i1 - $i2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if two symbols are the same.
|
||||
*/
|
||||
public static function same_symbol(PHP_ParserGenerator_Symbol $a, PHP_ParserGenerator_Symbol $b)
|
||||
{
|
||||
if ($a === $b) return 1;
|
||||
if ($a->type != self::MULTITERMINAL) return 0;
|
||||
if ($b->type != self::MULTITERMINAL) return 0;
|
||||
if ($a->nsubsym != $b->nsubsym) return 0;
|
||||
for ($i = 0; $i < $a->nsubsym; $i++) {
|
||||
if ($a->subsym[$i] != $b->subsym[$i]) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
6
vendor/smarty/smarty-lexer/ParserGenerator/cli.php
vendored
Normal file
6
vendor/smarty/smarty-lexer/ParserGenerator/cli.php
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
require_once './ParserGenerator.php';
|
||||
ini_set('max_execution_time',300);
|
||||
ini_set('xdebug.max_nesting_level',300);
|
||||
$me = new PHP_ParserGenerator;
|
||||
$me->main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue