/vendor/ParserGenerator/PHP/ParserGenerator/Symbol.php
PHP | 288 lines | 78 code | 6 blank | 204 comment | 12 complexity | 45740f2626eb12ff32f8a77307e30b71 MD5 | raw file
- <?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 302382 2010-08-17 06:08:09Z jespino $
- * @link http://pear.php.net/package/PHP_ParserGenerator
- * @since File available since Release 0.1.0
- */
- /**
- * Symbols (terminals and nonterminals) of the grammar are stored in this class
- *
- * @category PHP
- * @package PHP_ParserGenerator
- * @author Gregory Beaver <cellog@php.net>
- * @copyright 2006 Gregory Beaver
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/PHP_ParserGenerator
- * @since Class available since Release 0.1.0
- */
- class PHP_ParserGenerator_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;
- }
- }