. */ /** * An abstract base class for the productions of the Doctrine Query Language * context-free grammar. * * @author Guilherme Blanco * @author Janne Vanhala * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link http://www.phpdoctrine.org * @since 2.0 * @version $Revision$ */ abstract class Doctrine_ORM_Query_ParserRule { /** * @nodoc */ const SQLALIAS_SEPARATOR = '__'; /** * @nodoc */ const DEFAULT_QUERYCOMPONENT = 'dctrn'; /** * Parser object * * @var Doctrine_ORM_Query_Parser */ protected $_parser; /** * The EntityManager. * * @var EntityManager */ protected $_em; /** * Creates a new production object. * * @param Doctrine_ORM_Query_Parser $parser a parser object */ public function __construct(Doctrine_ORM_Query_Parser $parser) { $this->_parser = $parser; $this->_em = $this->_parser->getEntityManager(); } protected function _isNextToken($token) { $la = $this->_parser->lookahead; return ($la['type'] === $token || $la['value'] === $token); } protected function _isFunction() { $la = $this->_parser->lookahead; $next = $this->_parser->getScanner()->peek(); return ($la['type'] === Doctrine_ORM_Query_Token::T_IDENTIFIER && $next['value'] === '('); } protected function _isSubselect() { $la = $this->_parser->lookahead; $next = $this->_parser->getScanner()->peek(); return ($la['value'] === '(' && $next['type'] === Doctrine_ORM_Query_Token::T_SELECT); } /** * Executes the grammar rule using the specified parameters. * * @param string $RuleName BNF Grammar Rule name * @param array $paramHolder Production parameter holder * @return Doctrine_ORM_Query_ParserRule */ public function parse($RuleName, $paramHolder) { $BNFGrammarRule = $this->_getGrammarRule($RuleName); //echo "Processing class: " . get_class($BNFGrammarRule) . "...\n"; //echo "Params: " . var_export($paramHolder, true) . "\n"; // Syntax check if ( ! $paramHolder->has('syntaxCheck') || $paramHolder->get('syntaxCheck') === true) { //echo "Processing syntax checks of " . $RuleName . "...\n"; $return = $BNFGrammarRule->syntax($paramHolder); if ($return !== null) { //echo "Returning Gramma Rule class: " . (is_object($return) ? get_class($return) : $return) . "...\n"; return $return; } } // Semantical check if ( ! $paramHolder->has('semanticalCheck') || $paramHolder->get('semanticalCheck') === true) { //echo "Processing semantical checks of " . $RuleName . "...\n"; $return = $BNFGrammarRule->semantical($paramHolder); if ($return !== null) { //echo "Returning Gramma Rule class: " . (is_object($return) ? get_class($return) : $return) . "...\n"; return $return; } } return $BNFGrammarRule; } /** * Returns a grammar rule object with the given name. * * @param string $name grammar rule name * @return Doctrine_ORM_Query_ParserRule */ protected function _getGrammarRule($name) { $class = 'Doctrine_ORM_Query_Parser_' . $name; //echo $class . "\r\n"; //TODO: This expensive check is not necessary. Should be removed at the end. // "new $class" will throw an error anyway if the class is not found. if ( ! class_exists($class)) { throw new Doctrine_ORM_Query_Parser_Exception( "Unknown Grammar Rule '$name'. Could not find related compiler class." ); } return new $class($this->_parser); } /** * Creates an AST node with the given name. * * @param string $AstName AST node name * @return Doctrine_ORM_Query_AST */ public function AST($AstName) { $class = 'Doctrine_ORM_Query_AST_' . $AstName; //echo $class . "\r\n"; if ( ! class_exists($class)) { throw new Doctrine_ORM_Query_Parser_Exception( "Unknown AST node '" . $AstName . "'. Could not find related compiler class." ); } return new $class($this->_parser->getParserResult()); } /** * @nodoc */ abstract public function syntax($paramHolder); /** * @nodoc */ public function semantical($paramHolder) { } public function getParser() { return $this->_parser; } }