vendor/doctrine/lib/Doctrine/ORM/Query/Parser.php
author cavaliet
Wed, 11 Apr 2012 12:07:42 +0200
changeset 86 38ee151428dc
parent 0 7f95f8617b0b
permissions -rwxr-xr-x
remove original label column from all tags list
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
 * This software consists of voluntary contributions made by many individuals
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
 * and is licensed under the LGPL. For more information, see
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 * <http://www.doctrine-project.org>.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
namespace Doctrine\ORM\Query;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
use Doctrine\ORM\Query;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
use Doctrine\ORM\Mapping\ClassMetadata;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
 * An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
 * Parses a DQL query, reports any errors in it, and generates an AST.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
 * @since   2.0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
 * @author  Jonathan Wage <jonwage@gmail.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
 * @author  Roman Borschel <roman@code-factory.org>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
 * @author  Janne Vanhala <jpvanhal@cc.hut.fi>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
class Parser
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    /** READ-ONLY: Maps BUILT-IN string function names to AST class names. */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    private static $_STRING_FUNCTIONS = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        'concat'    => 'Doctrine\ORM\Query\AST\Functions\ConcatFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
        'substring' => 'Doctrine\ORM\Query\AST\Functions\SubstringFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        'trim'      => 'Doctrine\ORM\Query\AST\Functions\TrimFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        'lower'     => 'Doctrine\ORM\Query\AST\Functions\LowerFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        'upper'     => 'Doctrine\ORM\Query\AST\Functions\UpperFunction'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
    );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
    /** READ-ONLY: Maps BUILT-IN numeric function names to AST class names. */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    private static $_NUMERIC_FUNCTIONS = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
        'length'    => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        'locate'    => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
        'abs'       => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        'sqrt'      => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        'mod'       => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
        'size'      => 'Doctrine\ORM\Query\AST\Functions\SizeFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
        'date_diff' => 'Doctrine\ORM\Query\AST\Functions\DateDiffFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
    );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
    /** READ-ONLY: Maps BUILT-IN datetime function names to AST class names. */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
    private static $_DATETIME_FUNCTIONS = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        'current_date'      => 'Doctrine\ORM\Query\AST\Functions\CurrentDateFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
        'current_time'      => 'Doctrine\ORM\Query\AST\Functions\CurrentTimeFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        'date_add'          => 'Doctrine\ORM\Query\AST\Functions\DateAddFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        'date_sub'          => 'Doctrine\ORM\Query\AST\Functions\DateSubFunction',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
    );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
     * Expressions that were encountered during parsing of identifiers and expressions
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
     * and still need to be validated.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    private $_deferredIdentificationVariables = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
    private $_deferredPartialObjectExpressions = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
    private $_deferredPathExpressions = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
    private $_deferredResultVariables = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
     * The lexer.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
     * @var Doctrine\ORM\Query\Lexer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
    private $_lexer;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
     * The parser result.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
     * @var Doctrine\ORM\Query\ParserResult
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    private $_parserResult;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
     * The EntityManager.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
     * @var EnityManager
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
    private $_em;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
     * The Query to parse.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
     * @var Query
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
    private $_query;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
     * Map of declared query components in the parsed query.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
     * @var array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
    private $_queryComponents = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
     * Keeps the nesting level of defined ResultVariables
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
     * @var integer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
    private $_nestingLevel = 0;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
     * Any additional custom tree walkers that modify the AST.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
     * @var array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
    private $_customTreeWalkers = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
     * The custom last tree walker, if any, that is responsible for producing the output.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
     * @var TreeWalker
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
    private $_customOutputWalker;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
     * @var array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
    private $_identVariableExpressions = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
     * Creates a new query parser object.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
     * @param Query $query The Query to parse.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
    public function __construct(Query $query)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        $this->_query = $query;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
        $this->_em = $query->getEntityManager();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
        $this->_lexer = new Lexer($query->getDql());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
        $this->_parserResult = new ParserResult();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
     * Sets a custom tree walker that produces output.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
     * This tree walker will be run last over the AST, after any other walkers.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
     * @param string $className
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
    public function setCustomOutputTreeWalker($className)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
        $this->_customOutputWalker = $className;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
     * Adds a custom tree walker for modifying the AST.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
     * @param string $className
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
    public function addCustomTreeWalker($className)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
        $this->_customTreeWalkers[] = $className;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
     * Gets the lexer used by the parser.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
     * @return Doctrine\ORM\Query\Lexer
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
    public function getLexer()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
        return $this->_lexer;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
     * Gets the ParserResult that is being filled with information during parsing.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
     * @return Doctrine\ORM\Query\ParserResult
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
    public function getParserResult()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
        return $this->_parserResult;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
     * Gets the EntityManager used by the parser.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
     * @return EntityManager
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
    public function getEntityManager()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
        return $this->_em;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
     * Parse and build AST for the given Query.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
     * @return \Doctrine\ORM\Query\AST\SelectStatement |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
     *         \Doctrine\ORM\Query\AST\UpdateStatement |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
     *         \Doctrine\ORM\Query\AST\DeleteStatement
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
    public function getAST()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
        // Parse & build AST
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
        $AST = $this->QueryLanguage();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
        // Process any deferred validations of some nodes in the AST.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
        // This also allows post-processing of the AST for modification purposes.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
        $this->_processDeferredIdentificationVariables();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
        if ($this->_deferredPartialObjectExpressions) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
            $this->_processDeferredPartialObjectExpressions();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
        if ($this->_deferredPathExpressions) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
            $this->_processDeferredPathExpressions($AST);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
        if ($this->_deferredResultVariables) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
            $this->_processDeferredResultVariables();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
        return $AST;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
     * Attempts to match the given token with the current lookahead token.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
     * If they match, updates the lookahead token; otherwise raises a syntax
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
     * error.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
     * @param int token type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
     * @throws QueryException If the tokens dont match.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
    public function match($token)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
        // short-circuit on first condition, usually types match
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
        if ($this->_lexer->lookahead['type'] !== $token &&
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
                $token !== Lexer::T_IDENTIFIER &&
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
                $this->_lexer->lookahead['type'] <= Lexer::T_IDENTIFIER
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
         ) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
            $this->syntaxError($this->_lexer->getLiteral($token));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
        $this->_lexer->moveNext();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
     * Free this parser enabling it to be reused
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
     * @param boolean $deep     Whether to clean peek and reset errors
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
     * @param integer $position Position to reset
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
    public function free($deep = false, $position = 0)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
        // WARNING! Use this method with care. It resets the scanner!
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
        $this->_lexer->resetPosition($position);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
        // Deep = true cleans peek and also any previously defined errors
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
        if ($deep) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
            $this->_lexer->resetPeek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
        $this->_lexer->token = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
        $this->_lexer->lookahead = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
     * Parses a query string.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
     * @return ParserResult
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
    public function parse()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
        $AST = $this->getAST();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
        $this->fixIdentificationVariableOrder($AST);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
        $this->assertSelectEntityRootAliasRequirement();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
        if (($customWalkers = $this->_query->getHint(Query::HINT_CUSTOM_TREE_WALKERS)) !== false) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
            $this->_customTreeWalkers = $customWalkers;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
        if (($customOutputWalker = $this->_query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER)) !== false) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
            $this->_customOutputWalker = $customOutputWalker;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
        // Run any custom tree walkers over the AST
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
        if ($this->_customTreeWalkers) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
            $treeWalkerChain = new TreeWalkerChain($this->_query, $this->_parserResult, $this->_queryComponents);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
            foreach ($this->_customTreeWalkers as $walker) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
                $treeWalkerChain->addTreeWalker($walker);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
            if ($AST instanceof AST\SelectStatement) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
                $treeWalkerChain->walkSelectStatement($AST);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
            } else if ($AST instanceof AST\UpdateStatement) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
                $treeWalkerChain->walkUpdateStatement($AST);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
                $treeWalkerChain->walkDeleteStatement($AST);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
        if ($this->_customOutputWalker) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
            $outputWalker = new $this->_customOutputWalker(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
                $this->_query, $this->_parserResult, $this->_queryComponents
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
            $outputWalker = new SqlWalker(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
                $this->_query, $this->_parserResult, $this->_queryComponents
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
        // Assign an SQL executor to the parser result
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
        $this->_parserResult->setSqlExecutor($outputWalker->getExecutor($AST));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
        return $this->_parserResult;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
    
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
    private function assertSelectEntityRootAliasRequirement()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
        if ( count($this->_identVariableExpressions) > 0) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
            $foundRootEntity = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
            foreach ($this->_identVariableExpressions AS $dqlAlias => $expr) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
                if (isset($this->_queryComponents[$dqlAlias]) && $this->_queryComponents[$dqlAlias]['parent'] === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
                    $foundRootEntity = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
            
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
            if (!$foundRootEntity) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
                $this->semanticalError('Cannot select entity through identification variables without choosing at least one root entity alias.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
    
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
     * Fix order of identification variables.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
     * They have to appear in the select clause in the same order as the
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
     * declarations (from ... x join ... y join ... z ...) appear in the query
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
     * as the hydration process relies on that order for proper operation.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
     * @param AST\SelectStatement|AST\DeleteStatement|AST\UpdateStatement $AST
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
    private function fixIdentificationVariableOrder($AST)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
        if ( count($this->_identVariableExpressions) > 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
            foreach ($this->_queryComponents as $dqlAlias => $qComp) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
                if (isset($this->_identVariableExpressions[$dqlAlias])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
                    $expr = $this->_identVariableExpressions[$dqlAlias];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
                    $key = array_search($expr, $AST->selectClause->selectExpressions);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
                    unset($AST->selectClause->selectExpressions[$key]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
                    $AST->selectClause->selectExpressions[] = $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
     * Generates a new syntax error.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
     * @param string $expected Expected string.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
     * @param array $token Got token.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
     * @throws \Doctrine\ORM\Query\QueryException
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
    public function syntaxError($expected = '', $token = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
        if ($token === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
            $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
        $tokenPos = (isset($token['position'])) ? $token['position'] : '-1';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
        $message  = "line 0, col {$tokenPos}: Error: ";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
        if ($expected !== '') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
            $message .= "Expected {$expected}, got ";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
            $message .= 'Unexpected ';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
        if ($this->_lexer->lookahead === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
            $message .= 'end of string.';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
            $message .= "'{$token['value']}'";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
        throw QueryException::syntaxError($message);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
     * Generates a new semantical error.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
     * @param string $message Optional message.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
     * @param array $token Optional token.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
     * @throws \Doctrine\ORM\Query\QueryException
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
    public function semanticalError($message = '', $token = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
        if ($token === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
            $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
        // Minimum exposed chars ahead of token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
        $distance = 12;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
        // Find a position of a final word to display in error string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
        $dql = $this->_query->getDql();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
        $length = strlen($dql);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
        $pos = $token['position'] + $distance;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
        $pos = strpos($dql, ' ', ($length > $pos) ? $pos : $length);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
        $length = ($pos !== false) ? $pos - $token['position'] : $distance;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
        // Building informative message
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
        $message = 'line 0, col ' . (
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
            (isset($token['position']) && $token['position'] > 0) ? $token['position'] : '-1'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
        ) . " near '" . substr($dql, $token['position'], $length) . "': Error: " . $message;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
        throw \Doctrine\ORM\Query\QueryException::semanticalError($message);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
     * Peeks beyond the specified token and returns the first token after that one.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
     * @param array $token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
     * @return array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
    private function _peekBeyond($token)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
        $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
        while ($peek['value'] != $token) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
            $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
        $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
        $this->_lexer->resetPeek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
        return $peek;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
     * Peek beyond the matched closing parenthesis and return the first token after that one.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
     * @return array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
    private function _peekBeyondClosingParenthesis()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
        $token = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
        $numUnmatched = 1;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
        while ($numUnmatched > 0 && $token !== null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
            if ($token['value'] == ')') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
                --$numUnmatched;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
            } else if ($token['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
                ++$numUnmatched;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
            $token = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
        $this->_lexer->resetPeek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
        return $token;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
     * Checks if the given token indicates a mathematical operator.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
     * @return boolean TRUE if the token is a mathematical operator, FALSE otherwise.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
    private function _isMathOperator($token)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
        return in_array($token['value'], array("+", "-", "/", "*"));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
     * Checks if the next-next (after lookahead) token starts a function.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
     * @return boolean TRUE if the next-next tokens start a function, FALSE otherwise.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
    private function _isFunction()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
        $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
        $nextpeek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
        $this->_lexer->resetPeek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
        // We deny the COUNT(SELECT * FROM User u) here. COUNT won't be considered a function
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
        return ($peek['value'] === '(' && $nextpeek['type'] !== Lexer::T_SELECT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
     * Checks whether the given token type indicates an aggregate function.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
     * @return boolean TRUE if the token type is an aggregate function, FALSE otherwise.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
    private function _isAggregateFunction($tokenType)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
        return $tokenType == Lexer::T_AVG || $tokenType == Lexer::T_MIN ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
               $tokenType == Lexer::T_MAX || $tokenType == Lexer::T_SUM ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
               $tokenType == Lexer::T_COUNT;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   511
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   512
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   513
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   514
     * Checks whether the current lookahead token of the lexer has the type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   515
     * T_ALL, T_ANY or T_SOME.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   516
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   517
     * @return boolean
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   518
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   519
    private function _isNextAllAnySome()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   520
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   521
        return $this->_lexer->lookahead['type'] === Lexer::T_ALL ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   522
               $this->_lexer->lookahead['type'] === Lexer::T_ANY ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   523
               $this->_lexer->lookahead['type'] === Lexer::T_SOME;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   524
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   525
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   526
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   527
     * Checks whether the next 2 tokens start a subselect.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   528
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   529
     * @return boolean TRUE if the next 2 tokens start a subselect, FALSE otherwise.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   530
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   531
    private function _isSubselect()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   532
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   533
        $la = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   534
        $next = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   535
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   536
        return ($la['value'] === '(' && $next['type'] === Lexer::T_SELECT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   537
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   538
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   539
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   540
     * Validates that the given <tt>IdentificationVariable</tt> is semantically correct.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   541
     * It must exist in query components list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   542
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   543
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   544
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   545
    private function _processDeferredIdentificationVariables()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   546
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   547
        foreach ($this->_deferredIdentificationVariables as $deferredItem) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   548
            $identVariable = $deferredItem['expression'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   549
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   550
            // Check if IdentificationVariable exists in queryComponents
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   551
            if ( ! isset($this->_queryComponents[$identVariable])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   552
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   553
                    "'$identVariable' is not defined.", $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   554
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   555
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   556
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   557
            $qComp = $this->_queryComponents[$identVariable];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   558
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   559
            // Check if queryComponent points to an AbstractSchemaName or a ResultVariable
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   560
            if ( ! isset($qComp['metadata'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   561
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   562
                    "'$identVariable' does not point to a Class.", $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   563
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   564
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   565
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   566
            // Validate if identification variable nesting level is lower or equal than the current one
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   567
            if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   568
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   569
                    "'$identVariable' is used outside the scope of its declaration.", $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   570
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   571
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   572
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   573
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   574
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   575
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   576
     * Validates that the given <tt>PartialObjectExpression</tt> is semantically correct.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   577
     * It must exist in query components list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   578
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   579
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   580
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   581
    private function _processDeferredPartialObjectExpressions()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   582
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   583
        foreach ($this->_deferredPartialObjectExpressions as $deferredItem) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   584
            $expr = $deferredItem['expression'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   585
            $class = $this->_queryComponents[$expr->identificationVariable]['metadata'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   586
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   587
            foreach ($expr->partialFieldSet as $field) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   588
                if ( ! isset($class->fieldMappings[$field])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   589
                    $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   590
                        "There is no mapped field named '$field' on class " . $class->name . ".",
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   591
                        $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   592
                    );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   593
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   594
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   595
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   596
            if (array_intersect($class->identifier, $expr->partialFieldSet) != $class->identifier) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   597
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   598
                    "The partial field selection of class " . $class->name . " must contain the identifier.",
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   599
                    $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   600
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   601
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   602
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   603
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   604
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   605
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   606
     * Validates that the given <tt>ResultVariable</tt> is semantically correct.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   607
     * It must exist in query components list.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   608
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   609
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   610
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   611
    private function _processDeferredResultVariables()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   612
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   613
        foreach ($this->_deferredResultVariables as $deferredItem) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   614
            $resultVariable = $deferredItem['expression'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   615
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   616
            // Check if ResultVariable exists in queryComponents
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   617
            if ( ! isset($this->_queryComponents[$resultVariable])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   618
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   619
                    "'$resultVariable' is not defined.", $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   620
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   621
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   622
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   623
            $qComp = $this->_queryComponents[$resultVariable];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   624
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   625
            // Check if queryComponent points to an AbstractSchemaName or a ResultVariable
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   626
            if ( ! isset($qComp['resultVariable'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   627
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   628
                    "'$identVariable' does not point to a ResultVariable.", $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   629
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   630
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   631
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   632
            // Validate if identification variable nesting level is lower or equal than the current one
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   633
            if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   634
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   635
                    "'$resultVariable' is used outside the scope of its declaration.", $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   636
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   637
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   638
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   639
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   640
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   641
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   642
     * Validates that the given <tt>PathExpression</tt> is semantically correct for grammar rules:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   643
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   644
     * AssociationPathExpression             ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   645
     * SingleValuedPathExpression            ::= StateFieldPathExpression | SingleValuedAssociationPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   646
     * StateFieldPathExpression              ::= IdentificationVariable "." StateField
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   647
     * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   648
     * CollectionValuedPathExpression        ::= IdentificationVariable "." CollectionValuedAssociationField
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   649
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   650
     * @param array $deferredItem
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   651
     * @param mixed $AST
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   652
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   653
    private function _processDeferredPathExpressions($AST)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   654
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   655
        foreach ($this->_deferredPathExpressions as $deferredItem) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   656
            $pathExpression = $deferredItem['expression'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   657
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   658
            $qComp = $this->_queryComponents[$pathExpression->identificationVariable];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   659
            $class = $qComp['metadata'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   660
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   661
            if (($field = $pathExpression->field) === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   662
                $field = $pathExpression->field = $class->identifier[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   663
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   664
            
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   665
            // Check if field or association exists
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   666
            if ( ! isset($class->associationMappings[$field]) && ! isset($class->fieldMappings[$field])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   667
                $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   668
                    'Class ' . $class->name . ' has no field or association named ' . $field,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   669
                    $deferredItem['token']
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   670
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   671
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   672
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   673
            if (isset($class->fieldMappings[$field])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   674
                $fieldType = AST\PathExpression::TYPE_STATE_FIELD;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   675
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   676
                $assoc = $class->associationMappings[$field];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   677
                $class = $this->_em->getClassMetadata($assoc['targetEntity']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   678
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   679
                if ($assoc['type'] & ClassMetadata::TO_ONE) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   680
                    $fieldType = AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   681
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   682
                    $fieldType = AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   683
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   684
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   685
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   686
            // Validate if PathExpression is one of the expected types
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   687
            $expectedType = $pathExpression->expectedType;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   688
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   689
            if ( ! ($expectedType & $fieldType)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   690
                // We need to recognize which was expected type(s)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   691
                $expectedStringTypes = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   692
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   693
                // Validate state field type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   694
                if ($expectedType & AST\PathExpression::TYPE_STATE_FIELD) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   695
                    $expectedStringTypes[] = 'StateFieldPathExpression';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   696
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   697
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   698
                // Validate single valued association (*-to-one)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   699
                if ($expectedType & AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   700
                    $expectedStringTypes[] = 'SingleValuedAssociationField';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   701
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   702
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   703
                // Validate single valued association (*-to-many)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   704
                if ($expectedType & AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   705
                    $expectedStringTypes[] = 'CollectionValuedAssociationField';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   706
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   707
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   708
                // Build the error message
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   709
                $semanticalError = 'Invalid PathExpression. ';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   710
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   711
                if (count($expectedStringTypes) == 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   712
                    $semanticalError .= 'Must be a ' . $expectedStringTypes[0] . '.';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   713
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   714
                    $semanticalError .= implode(' or ', $expectedStringTypes) . ' expected.';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   715
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   716
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   717
                $this->semanticalError($semanticalError, $deferredItem['token']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   718
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   719
            
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   720
            // We need to force the type in PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   721
            $pathExpression->type = $fieldType;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   722
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   723
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   724
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   725
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   726
     * QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   727
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   728
     * @return \Doctrine\ORM\Query\AST\SelectStatement |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   729
     *         \Doctrine\ORM\Query\AST\UpdateStatement |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   730
     *         \Doctrine\ORM\Query\AST\DeleteStatement
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   731
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   732
    public function QueryLanguage()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   733
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   734
        $this->_lexer->moveNext();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   735
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   736
        switch ($this->_lexer->lookahead['type']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   737
            case Lexer::T_SELECT:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   738
                $statement = $this->SelectStatement();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   739
                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   740
            case Lexer::T_UPDATE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   741
                $statement = $this->UpdateStatement();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   742
                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   743
            case Lexer::T_DELETE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   744
                $statement = $this->DeleteStatement();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   745
                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   746
            default:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   747
                $this->syntaxError('SELECT, UPDATE or DELETE');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   748
                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   749
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   750
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   751
        // Check for end of string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   752
        if ($this->_lexer->lookahead !== null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   753
            $this->syntaxError('end of string');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   754
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   755
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   756
        return $statement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   757
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   758
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   759
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   760
     * SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   761
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   762
     * @return \Doctrine\ORM\Query\AST\SelectStatement
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   763
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   764
    public function SelectStatement()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   765
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   766
        $selectStatement = new AST\SelectStatement($this->SelectClause(), $this->FromClause());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   767
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   768
        $selectStatement->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   769
            ? $this->WhereClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   770
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   771
        $selectStatement->groupByClause = $this->_lexer->isNextToken(Lexer::T_GROUP)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   772
            ? $this->GroupByClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   773
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   774
        $selectStatement->havingClause = $this->_lexer->isNextToken(Lexer::T_HAVING)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   775
            ? $this->HavingClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   776
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   777
        $selectStatement->orderByClause = $this->_lexer->isNextToken(Lexer::T_ORDER)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   778
            ? $this->OrderByClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   779
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   780
        return $selectStatement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   781
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   782
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   783
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   784
     * UpdateStatement ::= UpdateClause [WhereClause]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   785
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   786
     * @return \Doctrine\ORM\Query\AST\UpdateStatement
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   787
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   788
    public function UpdateStatement()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   789
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   790
        $updateStatement = new AST\UpdateStatement($this->UpdateClause());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   791
        $updateStatement->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   792
                ? $this->WhereClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   793
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   794
        return $updateStatement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   795
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   796
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   797
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   798
     * DeleteStatement ::= DeleteClause [WhereClause]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   799
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   800
     * @return \Doctrine\ORM\Query\AST\DeleteStatement
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   801
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   802
    public function DeleteStatement()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   803
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   804
        $deleteStatement = new AST\DeleteStatement($this->DeleteClause());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   805
        $deleteStatement->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   806
                ? $this->WhereClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   807
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   808
        return $deleteStatement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   809
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   810
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   811
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   812
     * IdentificationVariable ::= identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   813
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   814
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   815
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   816
    public function IdentificationVariable()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   817
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   818
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   819
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   820
        $identVariable = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   821
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   822
        $this->_deferredIdentificationVariables[] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   823
            'expression'   => $identVariable,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   824
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   825
            'token'        => $this->_lexer->token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   826
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   827
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   828
        return $identVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   829
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   830
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   831
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   832
     * AliasIdentificationVariable = identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   833
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   834
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   835
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   836
    public function AliasIdentificationVariable()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   837
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   838
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   839
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   840
        $aliasIdentVariable = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   841
        $exists = isset($this->_queryComponents[$aliasIdentVariable]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   842
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   843
        if ($exists) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   844
            $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   845
                "'$aliasIdentVariable' is already defined.", $this->_lexer->token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   846
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   847
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   848
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   849
        return $aliasIdentVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   850
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   851
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   852
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   853
     * AbstractSchemaName ::= identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   854
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   855
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   856
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   857
    public function AbstractSchemaName()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   858
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   859
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   860
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   861
        $schemaName = ltrim($this->_lexer->token['value'], '\\');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   862
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   863
        if (strrpos($schemaName, ':') !== false) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   864
            list($namespaceAlias, $simpleClassName) = explode(':', $schemaName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   865
            $schemaName = $this->_em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   866
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   867
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   868
        $exists = class_exists($schemaName, true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   869
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   870
        if ( ! $exists) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   871
            $this->semanticalError("Class '$schemaName' is not defined.", $this->_lexer->token);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   872
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   873
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   874
        return $schemaName;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   875
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   876
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   877
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   878
     * AliasResultVariable ::= identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   879
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   880
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   881
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   882
    public function AliasResultVariable()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   883
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   884
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   885
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   886
        $resultVariable = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   887
        $exists = isset($this->_queryComponents[$resultVariable]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   888
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   889
        if ($exists) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   890
            $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   891
                "'$resultVariable' is already defined.", $this->_lexer->token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   892
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   893
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   894
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   895
        return $resultVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   896
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   897
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   898
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   899
     * ResultVariable ::= identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   900
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   901
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   902
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   903
    public function ResultVariable()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   904
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   905
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   906
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   907
        $resultVariable = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   908
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   909
        // Defer ResultVariable validation
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   910
        $this->_deferredResultVariables[] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   911
            'expression'   => $resultVariable,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   912
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   913
            'token'        => $this->_lexer->token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   914
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   915
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   916
        return $resultVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   917
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   918
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   919
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   920
     * JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   921
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   922
     * @return \Doctrine\ORM\Query\AST\JoinAssociationPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   923
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   924
    public function JoinAssociationPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   925
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   926
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   927
        $identVariable = $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   928
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   929
        if (!isset($this->_queryComponents[$identVariable])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   930
            $this->semanticalError('Identification Variable ' . $identVariable .' used in join path expression but was not defined before.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   931
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   932
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   933
        $this->match(Lexer::T_DOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   934
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   935
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   936
        $field = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   937
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   938
        // Validate association field
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   939
        $qComp = $this->_queryComponents[$identVariable];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   940
        $class = $qComp['metadata'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   941
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   942
        if ( ! isset($class->associationMappings[$field])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   943
            $this->semanticalError('Class ' . $class->name . ' has no association named ' . $field);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   944
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   945
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   946
        return new AST\JoinAssociationPathExpression($identVariable, $field);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   947
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   948
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   949
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   950
     * Parses an arbitrary path expression and defers semantical validation
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   951
     * based on expected types.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   952
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   953
     * PathExpression ::= IdentificationVariable "." identifier
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   954
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   955
     * @param integer $expectedTypes
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   956
     * @return \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   957
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   958
    public function PathExpression($expectedTypes)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   959
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   960
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   961
        $identVariable = $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   962
        $field = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   963
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   964
        if ($this->_lexer->isNextToken(Lexer::T_DOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   965
            $this->match(Lexer::T_DOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   966
            $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   967
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   968
            $field = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   969
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   970
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   971
        // Creating AST node
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   972
        $pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $field);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   973
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   974
        // Defer PathExpression validation if requested to be defered
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   975
        $this->_deferredPathExpressions[] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   976
            'expression'   => $pathExpr,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   977
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   978
            'token'        => $this->_lexer->token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   979
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   980
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   981
        return $pathExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   982
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   983
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   984
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   985
     * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   986
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   987
     * @return \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   988
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   989
    public function AssociationPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   990
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   991
        return $this->PathExpression(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   992
            AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   993
            AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   994
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   995
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   996
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   997
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   998
     * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   999
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1000
     * @return \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1001
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1002
    public function SingleValuedPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1003
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1004
        return $this->PathExpression(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1005
            AST\PathExpression::TYPE_STATE_FIELD |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1006
            AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1007
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1008
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1009
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1010
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1011
     * StateFieldPathExpression ::= IdentificationVariable "." StateField
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1012
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1013
     * @return \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1014
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1015
    public function StateFieldPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1016
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1017
        return $this->PathExpression(AST\PathExpression::TYPE_STATE_FIELD);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1018
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1019
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1020
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1021
     * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1022
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1023
     * @return \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1024
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1025
    public function SingleValuedAssociationPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1026
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1027
        return $this->PathExpression(AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1028
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1029
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1030
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1031
     * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1032
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1033
     * @return \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1034
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1035
    public function CollectionValuedPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1036
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1037
        return $this->PathExpression(AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1038
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1039
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1040
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1041
     * SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1042
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1043
     * @return \Doctrine\ORM\Query\AST\SelectClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1044
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1045
    public function SelectClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1046
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1047
        $isDistinct = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1048
        $this->match(Lexer::T_SELECT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1049
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1050
        // Check for DISTINCT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1051
        if ($this->_lexer->isNextToken(Lexer::T_DISTINCT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1052
            $this->match(Lexer::T_DISTINCT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1053
            $isDistinct = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1054
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1055
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1056
        // Process SelectExpressions (1..N)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1057
        $selectExpressions = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1058
        $selectExpressions[] = $this->SelectExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1059
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1060
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1061
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1062
            $selectExpressions[] = $this->SelectExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1063
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1064
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1065
        return new AST\SelectClause($selectExpressions, $isDistinct);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1066
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1067
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1068
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1069
     * SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1070
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1071
     * @return \Doctrine\ORM\Query\AST\SimpleSelectClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1072
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1073
    public function SimpleSelectClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1074
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1075
        $isDistinct = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1076
        $this->match(Lexer::T_SELECT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1077
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1078
        if ($this->_lexer->isNextToken(Lexer::T_DISTINCT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1079
            $this->match(Lexer::T_DISTINCT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1080
            $isDistinct = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1081
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1082
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1083
        return new AST\SimpleSelectClause($this->SimpleSelectExpression(), $isDistinct);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1084
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1085
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1086
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1087
     * UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1088
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1089
     * @return \Doctrine\ORM\Query\AST\UpdateClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1090
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1091
    public function UpdateClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1092
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1093
        $this->match(Lexer::T_UPDATE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1094
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1095
        $abstractSchemaName = $this->AbstractSchemaName();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1096
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1097
        if ($this->_lexer->isNextToken(Lexer::T_AS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1098
            $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1099
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1100
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1101
        $aliasIdentificationVariable = $this->AliasIdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1102
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1103
        $class = $this->_em->getClassMetadata($abstractSchemaName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1104
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1105
        // Building queryComponent
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1106
        $queryComponent = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1107
            'metadata'     => $class,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1108
            'parent'       => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1109
            'relation'     => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1110
            'map'          => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1111
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1112
            'token'        => $token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1113
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1114
        $this->_queryComponents[$aliasIdentificationVariable] = $queryComponent;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1115
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1116
        $this->match(Lexer::T_SET);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1117
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1118
        $updateItems = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1119
        $updateItems[] = $this->UpdateItem();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1120
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1121
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1122
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1123
            $updateItems[] = $this->UpdateItem();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1124
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1125
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1126
        $updateClause = new AST\UpdateClause($abstractSchemaName, $updateItems);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1127
        $updateClause->aliasIdentificationVariable = $aliasIdentificationVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1128
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1129
        return $updateClause;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1130
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1131
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1132
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1133
     * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1134
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1135
     * @return \Doctrine\ORM\Query\AST\DeleteClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1136
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1137
    public function DeleteClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1138
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1139
        $this->match(Lexer::T_DELETE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1140
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1141
        if ($this->_lexer->isNextToken(Lexer::T_FROM)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1142
            $this->match(Lexer::T_FROM);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1143
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1144
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1145
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1146
        $deleteClause = new AST\DeleteClause($this->AbstractSchemaName());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1147
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1148
        if ($this->_lexer->isNextToken(Lexer::T_AS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1149
            $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1150
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1151
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1152
        $aliasIdentificationVariable = $this->AliasIdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1153
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1154
        $deleteClause->aliasIdentificationVariable = $aliasIdentificationVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1155
        $class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1156
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1157
        // Building queryComponent
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1158
        $queryComponent = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1159
            'metadata'     => $class,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1160
            'parent'       => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1161
            'relation'     => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1162
            'map'          => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1163
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1164
            'token'        => $token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1165
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1166
        $this->_queryComponents[$aliasIdentificationVariable] = $queryComponent;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1167
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1168
        return $deleteClause;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1169
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1170
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1171
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1172
     * FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1173
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1174
     * @return \Doctrine\ORM\Query\AST\FromClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1175
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1176
    public function FromClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1177
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1178
        $this->match(Lexer::T_FROM);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1179
        $identificationVariableDeclarations = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1180
        $identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1181
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1182
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1183
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1184
            $identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1185
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1186
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1187
        return new AST\FromClause($identificationVariableDeclarations);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1188
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1189
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1190
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1191
     * SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1192
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1193
     * @return \Doctrine\ORM\Query\AST\SubselectFromClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1194
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1195
    public function SubselectFromClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1196
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1197
        $this->match(Lexer::T_FROM);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1198
        $identificationVariables = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1199
        $identificationVariables[] = $this->SubselectIdentificationVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1200
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1201
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1202
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1203
            $identificationVariables[] = $this->SubselectIdentificationVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1204
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1205
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1206
        return new AST\SubselectFromClause($identificationVariables);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1207
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1208
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1209
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1210
     * WhereClause ::= "WHERE" ConditionalExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1211
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1212
     * @return \Doctrine\ORM\Query\AST\WhereClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1213
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1214
    public function WhereClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1215
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1216
        $this->match(Lexer::T_WHERE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1217
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1218
        return new AST\WhereClause($this->ConditionalExpression());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1219
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1220
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1221
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1222
     * HavingClause ::= "HAVING" ConditionalExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1223
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1224
     * @return \Doctrine\ORM\Query\AST\HavingClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1225
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1226
    public function HavingClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1227
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1228
        $this->match(Lexer::T_HAVING);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1229
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1230
        return new AST\HavingClause($this->ConditionalExpression());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1231
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1232
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1233
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1234
     * GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1235
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1236
     * @return \Doctrine\ORM\Query\AST\GroupByClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1237
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1238
    public function GroupByClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1239
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1240
        $this->match(Lexer::T_GROUP);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1241
        $this->match(Lexer::T_BY);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1242
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1243
        $groupByItems = array($this->GroupByItem());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1244
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1245
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1246
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1247
            $groupByItems[] = $this->GroupByItem();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1248
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1249
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1250
        return new AST\GroupByClause($groupByItems);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1251
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1252
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1253
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1254
     * OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1255
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1256
     * @return \Doctrine\ORM\Query\AST\OrderByClause
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1257
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1258
    public function OrderByClause()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1259
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1260
        $this->match(Lexer::T_ORDER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1261
        $this->match(Lexer::T_BY);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1262
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1263
        $orderByItems = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1264
        $orderByItems[] = $this->OrderByItem();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1265
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1266
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1267
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1268
            $orderByItems[] = $this->OrderByItem();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1269
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1270
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1271
        return new AST\OrderByClause($orderByItems);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1272
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1273
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1274
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1275
     * Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1276
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1277
     * @return \Doctrine\ORM\Query\AST\Subselect
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1278
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1279
    public function Subselect()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1280
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1281
        // Increase query nesting level
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1282
        $this->_nestingLevel++;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1283
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1284
        $subselect = new AST\Subselect($this->SimpleSelectClause(), $this->SubselectFromClause());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1285
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1286
        $subselect->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1287
            ? $this->WhereClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1288
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1289
        $subselect->groupByClause = $this->_lexer->isNextToken(Lexer::T_GROUP)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1290
            ? $this->GroupByClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1291
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1292
        $subselect->havingClause = $this->_lexer->isNextToken(Lexer::T_HAVING)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1293
            ? $this->HavingClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1294
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1295
        $subselect->orderByClause = $this->_lexer->isNextToken(Lexer::T_ORDER)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1296
            ? $this->OrderByClause() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1297
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1298
        // Decrease query nesting level
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1299
        $this->_nestingLevel--;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1300
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1301
        return $subselect;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1302
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1303
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1304
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1305
     * UpdateItem ::= SingleValuedPathExpression "=" NewValue
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1306
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1307
     * @return \Doctrine\ORM\Query\AST\UpdateItem
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1308
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1309
    public function UpdateItem()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1310
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1311
        $pathExpr = $this->SingleValuedPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1312
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1313
        $this->match(Lexer::T_EQUALS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1314
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1315
        $updateItem = new AST\UpdateItem($pathExpr, $this->NewValue());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1316
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1317
        return $updateItem;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1318
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1319
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1320
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1321
     * GroupByItem ::= IdentificationVariable | SingleValuedPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1322
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1323
     * @return string | \Doctrine\ORM\Query\AST\PathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1324
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1325
    public function GroupByItem()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1326
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1327
        // We need to check if we are in a IdentificationVariable or SingleValuedPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1328
        $glimpse = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1329
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1330
        if ($glimpse['type'] != Lexer::T_DOT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1331
            $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1332
            $identVariable = $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1333
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1334
            if (!isset($this->_queryComponents[$identVariable])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1335
                $this->semanticalError('Cannot group by undefined identification variable.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1336
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1337
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1338
            return $identVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1339
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1340
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1341
        return $this->SingleValuedPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1342
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1343
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1344
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1345
     * OrderByItem ::= (ResultVariable | StateFieldPathExpression) ["ASC" | "DESC"]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1346
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1347
     * @todo Post 2.0 release. Support general SingleValuedPathExpression instead
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1348
     * of only StateFieldPathExpression.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1349
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1350
     * @return \Doctrine\ORM\Query\AST\OrderByItem
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1351
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1352
    public function OrderByItem()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1353
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1354
        $type = 'ASC';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1355
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1356
        // We need to check if we are in a ResultVariable or StateFieldPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1357
        $glimpse = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1358
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1359
        if ($glimpse['type'] != Lexer::T_DOT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1360
            $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1361
            $expr = $this->ResultVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1362
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1363
            $expr = $this->StateFieldPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1364
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1365
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1366
        $item = new AST\OrderByItem($expr);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1367
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1368
        if ($this->_lexer->isNextToken(Lexer::T_ASC)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1369
            $this->match(Lexer::T_ASC);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1370
        } else if ($this->_lexer->isNextToken(Lexer::T_DESC)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1371
            $this->match(Lexer::T_DESC);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1372
            $type = 'DESC';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1373
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1374
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1375
        $item->type = $type;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1376
        return $item;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1377
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1378
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1379
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1380
     * NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1381
     *      EnumPrimary | SimpleEntityExpression | "NULL"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1382
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1383
     * NOTE: Since it is not possible to correctly recognize individual types, here is the full
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1384
     * grammar that needs to be supported:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1385
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1386
     * NewValue ::= SimpleArithmeticExpression | "NULL"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1387
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1388
     * SimpleArithmeticExpression covers all *Primary grammar rules and also SimplEntityExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1389
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1390
    public function NewValue()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1391
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1392
        if ($this->_lexer->isNextToken(Lexer::T_NULL)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1393
            $this->match(Lexer::T_NULL);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1394
            return null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1395
        } else if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1396
            $this->match(Lexer::T_INPUT_PARAMETER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1397
            return new AST\InputParameter($this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1398
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1399
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1400
        return $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1401
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1402
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1403
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1404
     * IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1405
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1406
     * @return \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1407
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1408
    public function IdentificationVariableDeclaration()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1409
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1410
        $rangeVariableDeclaration = $this->RangeVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1411
        $indexBy = $this->_lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1412
        $joinVariableDeclarations = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1413
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1414
        while (
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1415
            $this->_lexer->isNextToken(Lexer::T_LEFT) ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1416
            $this->_lexer->isNextToken(Lexer::T_INNER) ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1417
            $this->_lexer->isNextToken(Lexer::T_JOIN)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1418
        ) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1419
            $joinVariableDeclarations[] = $this->JoinVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1420
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1421
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1422
        return new AST\IdentificationVariableDeclaration(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1423
            $rangeVariableDeclaration, $indexBy, $joinVariableDeclarations
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1424
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1425
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1426
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1427
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1428
     * SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | (AssociationPathExpression ["AS"] AliasIdentificationVariable)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1429
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1430
     * @return \Doctrine\ORM\Query\AST\SubselectIdentificationVariableDeclaration |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1431
     *         \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1432
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1433
    public function SubselectIdentificationVariableDeclaration()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1434
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1435
        $glimpse = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1436
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1437
        /* NOT YET IMPLEMENTED!
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1438
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1439
        if ($glimpse['type'] == Lexer::T_DOT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1440
            $subselectIdVarDecl = new AST\SubselectIdentificationVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1441
            $subselectIdVarDecl->associationPathExpression = $this->AssociationPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1442
            $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1443
            $subselectIdVarDecl->aliasIdentificationVariable = $this->AliasIdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1444
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1445
            return $subselectIdVarDecl;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1446
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1447
        */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1448
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1449
        return $this->IdentificationVariableDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1450
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1451
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1452
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1453
     * JoinVariableDeclaration ::= Join [IndexBy]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1454
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1455
     * @return \Doctrine\ORM\Query\AST\JoinVariableDeclaration
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1456
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1457
    public function JoinVariableDeclaration()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1458
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1459
        $join = $this->Join();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1460
        $indexBy = $this->_lexer->isNextToken(Lexer::T_INDEX)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1461
                ? $this->IndexBy() : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1462
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1463
        return new AST\JoinVariableDeclaration($join, $indexBy);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1464
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1465
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1466
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1467
     * RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1468
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1469
     * @return Doctrine\ORM\Query\AST\RangeVariableDeclaration
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1470
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1471
    public function RangeVariableDeclaration()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1472
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1473
        $abstractSchemaName = $this->AbstractSchemaName();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1474
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1475
        if ($this->_lexer->isNextToken(Lexer::T_AS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1476
            $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1477
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1478
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1479
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1480
        $aliasIdentificationVariable = $this->AliasIdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1481
        $classMetadata = $this->_em->getClassMetadata($abstractSchemaName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1482
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1483
        // Building queryComponent
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1484
        $queryComponent = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1485
            'metadata'     => $classMetadata,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1486
            'parent'       => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1487
            'relation'     => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1488
            'map'          => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1489
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1490
            'token'        => $token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1491
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1492
        $this->_queryComponents[$aliasIdentificationVariable] = $queryComponent;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1493
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1494
        return new AST\RangeVariableDeclaration($abstractSchemaName, $aliasIdentificationVariable);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1495
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1496
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1497
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1498
     * PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1499
     * PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1500
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1501
     * @return array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1502
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1503
    public function PartialObjectExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1504
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1505
        $this->match(Lexer::T_PARTIAL);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1506
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1507
        $partialFieldSet = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1508
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1509
        $identificationVariable = $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1510
        $this->match(Lexer::T_DOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1511
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1512
        $this->match(Lexer::T_OPEN_CURLY_BRACE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1513
        $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1514
        $partialFieldSet[] = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1515
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1516
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1517
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1518
            $this->match(Lexer::T_IDENTIFIER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1519
            $partialFieldSet[] = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1520
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1521
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1522
        $this->match(Lexer::T_CLOSE_CURLY_BRACE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1523
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1524
        $partialObjectExpression = new AST\PartialObjectExpression($identificationVariable, $partialFieldSet);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1525
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1526
        // Defer PartialObjectExpression validation
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1527
        $this->_deferredPartialObjectExpressions[] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1528
            'expression'   => $partialObjectExpression,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1529
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1530
            'token'        => $this->_lexer->token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1531
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1532
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1533
        return $partialObjectExpression;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1534
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1535
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1536
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1537
     * Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1538
     *          ["AS"] AliasIdentificationVariable ["WITH" ConditionalExpression]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1539
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1540
     * @return Doctrine\ORM\Query\AST\Join
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1541
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1542
    public function Join()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1543
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1544
        // Check Join type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1545
        $joinType = AST\Join::JOIN_TYPE_INNER;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1546
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1547
        if ($this->_lexer->isNextToken(Lexer::T_LEFT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1548
            $this->match(Lexer::T_LEFT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1549
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1550
            // Possible LEFT OUTER join
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1551
            if ($this->_lexer->isNextToken(Lexer::T_OUTER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1552
                $this->match(Lexer::T_OUTER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1553
                $joinType = AST\Join::JOIN_TYPE_LEFTOUTER;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1554
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1555
                $joinType = AST\Join::JOIN_TYPE_LEFT;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1556
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1557
        } else if ($this->_lexer->isNextToken(Lexer::T_INNER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1558
            $this->match(Lexer::T_INNER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1559
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1560
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1561
        $this->match(Lexer::T_JOIN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1562
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1563
        $joinPathExpression = $this->JoinAssociationPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1564
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1565
        if ($this->_lexer->isNextToken(Lexer::T_AS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1566
            $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1567
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1568
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1569
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1570
        $aliasIdentificationVariable = $this->AliasIdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1571
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1572
        // Verify that the association exists.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1573
        $parentClass = $this->_queryComponents[$joinPathExpression->identificationVariable]['metadata'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1574
        $assocField = $joinPathExpression->associationField;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1575
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1576
        if ( ! $parentClass->hasAssociation($assocField)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1577
            $this->semanticalError(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1578
                "Class " . $parentClass->name . " has no association named '$assocField'."
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1579
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1580
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1581
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1582
        $targetClassName = $parentClass->associationMappings[$assocField]['targetEntity'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1583
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1584
        // Building queryComponent
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1585
        $joinQueryComponent = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1586
            'metadata'     => $this->_em->getClassMetadata($targetClassName),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1587
            'parent'       => $joinPathExpression->identificationVariable,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1588
            'relation'     => $parentClass->getAssociationMapping($assocField),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1589
            'map'          => null,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1590
            'nestingLevel' => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1591
            'token'        => $token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1592
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1593
        $this->_queryComponents[$aliasIdentificationVariable] = $joinQueryComponent;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1594
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1595
        // Create AST node
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1596
        $join = new AST\Join($joinType, $joinPathExpression, $aliasIdentificationVariable);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1597
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1598
        // Check for ad-hoc Join conditions
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1599
        if ($this->_lexer->isNextToken(Lexer::T_WITH)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1600
            $this->match(Lexer::T_WITH);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1601
            $join->conditionalExpression = $this->ConditionalExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1602
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1603
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1604
        return $join;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1605
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1606
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1607
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1608
     * IndexBy ::= "INDEX" "BY" StateFieldPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1609
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1610
     * @return Doctrine\ORM\Query\AST\IndexBy
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1611
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1612
    public function IndexBy()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1613
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1614
        $this->match(Lexer::T_INDEX);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1615
        $this->match(Lexer::T_BY);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1616
        $pathExpr = $this->StateFieldPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1617
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1618
        // Add the INDEX BY info to the query component
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1619
        $this->_queryComponents[$pathExpr->identificationVariable]['map'] = $pathExpr->field;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1620
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1621
        return new AST\IndexBy($pathExpr);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1622
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1623
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1624
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1625
     * ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1626
     *                      StateFieldPathExpression | BooleanPrimary | CaseExpression |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1627
     *                      EntityTypeExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1628
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1629
     * @return mixed One of the possible expressions or subexpressions.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1630
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1631
    public function ScalarExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1632
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1633
        $lookahead = $this->_lexer->lookahead['type'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1634
        if ($lookahead === Lexer::T_IDENTIFIER) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1635
            $this->_lexer->peek(); // lookahead => '.'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1636
            $this->_lexer->peek(); // lookahead => token after '.'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1637
            $peek = $this->_lexer->peek(); // lookahead => token after the token after the '.'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1638
            $this->_lexer->resetPeek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1639
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1640
            if ($this->_isMathOperator($peek)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1641
                return $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1642
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1643
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1644
            return $this->StateFieldPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1645
        } else if ($lookahead == Lexer::T_INTEGER || $lookahead == Lexer::T_FLOAT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1646
            return $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1647
        } else if ($lookahead == Lexer::T_CASE || $lookahead == Lexer::T_COALESCE || $lookahead == Lexer::T_NULLIF) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1648
            // Since NULLIF and COALESCE can be identified as a function, 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1649
            // we need to check if before check for FunctionDeclaration
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1650
            return $this->CaseExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1651
        } else if ($this->_isFunction() || $this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1652
            // We may be in an ArithmeticExpression (find the matching ")" and inspect for Math operator)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1653
            $this->_lexer->peek(); // "("
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1654
            $peek = $this->_peekBeyondClosingParenthesis();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1655
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1656
            if ($this->_isMathOperator($peek)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1657
                return $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1658
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1659
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1660
            if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1661
                return $this->AggregateExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1662
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1663
                return $this->FunctionDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1664
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1665
        } else if ($lookahead == Lexer::T_STRING) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1666
            return $this->StringPrimary();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1667
        } else if ($lookahead == Lexer::T_INPUT_PARAMETER) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1668
            return $this->InputParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1669
        } else if ($lookahead == Lexer::T_TRUE || $lookahead == Lexer::T_FALSE) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1670
            $this->match($lookahead);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1671
            return new AST\Literal(AST\Literal::BOOLEAN, $this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1672
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1673
            $this->syntaxError();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1674
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1675
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1676
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1677
    public function CaseExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1678
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1679
        $lookahead = $this->_lexer->lookahead['type'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1680
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1681
        // if "CASE" "WHEN" => GeneralCaseExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1682
        // else if "CASE" => SimpleCaseExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1683
        // [DONE] else if "COALESCE" => CoalesceExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1684
        // [DONE] else if "NULLIF" => NullifExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1685
        switch ($lookahead) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1686
            case Lexer::T_NULLIF:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1687
                return $this->NullIfExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1688
                
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1689
            case Lexer::T_COALESCE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1690
                return $this->CoalesceExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1691
                
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1692
            default:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1693
                $this->semanticalError('CaseExpression not yet supported.');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1694
                return null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1695
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1696
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1697
    
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1698
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1699
     * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1700
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1701
     * @return Doctrine\ORM\Query\AST\CoalesceExpression 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1702
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1703
    public function CoalesceExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1704
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1705
        $this->match(Lexer::T_COALESCE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1706
        $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1707
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1708
        // Process ScalarExpressions (1..N)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1709
        $scalarExpressions = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1710
        $scalarExpressions[] = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1711
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1712
        while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1713
            $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1714
            $scalarExpressions[] = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1715
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1716
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1717
        $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1718
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1719
        return new AST\CoalesceExpression($scalarExpressions);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1720
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1721
    
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1722
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1723
     * NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1724
     * 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1725
     * @return Doctrine\ORM\Query\AST\ExistsExpression 
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1726
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1727
    public function NullIfExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1728
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1729
        $this->match(Lexer::T_NULLIF);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1730
        $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1731
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1732
        $firstExpression = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1733
        $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1734
        $secondExpression = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1735
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1736
        $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1737
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1738
        return new AST\NullIfExpression($firstExpression, $secondExpression);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1739
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1740
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1741
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1742
     * SelectExpression ::=
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1743
     *      IdentificationVariable | StateFieldPathExpression |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1744
     *      (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1745
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1746
     * @return Doctrine\ORM\Query\AST\SelectExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1747
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1748
    public function SelectExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1749
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1750
        $expression = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1751
        $identVariable = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1752
        $fieldAliasIdentificationVariable = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1753
        $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1754
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1755
        $supportsAlias = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1756
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1757
        if ($peek['value'] != '(' && $this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1758
            if ($peek['value'] == '.') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1759
                // ScalarExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1760
                $expression = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1761
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1762
                $supportsAlias = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1763
                $expression = $identVariable = $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1764
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1765
        } else if ($this->_lexer->lookahead['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1766
            if ($peek['type'] == Lexer::T_SELECT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1767
                // Subselect
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1768
                $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1769
                $expression = $this->Subselect();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1770
                $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1771
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1772
                // Shortcut: ScalarExpression => SimpleArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1773
                $expression = $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1774
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1775
        } else if ($this->_isFunction()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1776
            $this->_lexer->peek(); // "("
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1777
            
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1778
            $lookaheadType = $this->_lexer->lookahead['type'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1779
            $beyond        = $this->_peekBeyondClosingParenthesis();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1780
            
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1781
            if ($this->_isMathOperator($beyond)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1782
                $expression = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1783
            } else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1784
                $expression = $this->AggregateExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1785
            } else if (in_array ($lookaheadType, array(Lexer::T_CASE, Lexer::T_COALESCE, Lexer::T_NULLIF))) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1786
                $expression = $this->CaseExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1787
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1788
                // Shortcut: ScalarExpression => Function
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1789
                $expression = $this->FunctionDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1790
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1791
        } else if ($this->_lexer->lookahead['type'] == Lexer::T_PARTIAL) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1792
            $supportsAlias = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1793
            $expression = $this->PartialObjectExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1794
            $identVariable = $expression->identificationVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1795
        } else if ($this->_lexer->lookahead['type'] == Lexer::T_INTEGER ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1796
                $this->_lexer->lookahead['type'] == Lexer::T_FLOAT ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1797
                $this->_lexer->lookahead['type'] == Lexer::T_STRING) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1798
            // Shortcut: ScalarExpression => SimpleArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1799
            $expression = $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1800
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1801
            $this->syntaxError('IdentificationVariable | StateFieldPathExpression'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1802
                    . ' | AggregateExpression | "(" Subselect ")" | ScalarExpression',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1803
                    $this->_lexer->lookahead);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1804
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1805
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1806
        if ($supportsAlias) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1807
            if ($this->_lexer->isNextToken(Lexer::T_AS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1808
                $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1809
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1810
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1811
            if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1812
                $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1813
                $fieldAliasIdentificationVariable = $this->AliasResultVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1814
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1815
                // Include AliasResultVariable in query components.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1816
                $this->_queryComponents[$fieldAliasIdentificationVariable] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1817
                    'resultVariable' => $expression,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1818
                    'nestingLevel'   => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1819
                    'token'          => $token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1820
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1821
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1822
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1823
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1824
        $expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1825
        if (!$supportsAlias) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1826
            $this->_identVariableExpressions[$identVariable] = $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1827
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1828
        return $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1829
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1830
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1831
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1832
     * SimpleSelectExpression ::=
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1833
     *      StateFieldPathExpression | IdentificationVariable |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1834
     *      ((AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable])
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1835
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1836
     * @return \Doctrine\ORM\Query\AST\SimpleSelectExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1837
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1838
    public function SimpleSelectExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1839
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1840
        $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1841
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1842
        if ($peek['value'] != '(' && $this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1843
            // SingleValuedPathExpression | IdentificationVariable
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1844
            if ($peek['value'] == '.') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1845
                $expression = $this->StateFieldPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1846
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1847
                $expression = $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1848
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1849
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1850
            return new AST\SimpleSelectExpression($expression);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1851
        } else if ($this->_lexer->lookahead['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1852
            if ($peek['type'] == Lexer::T_SELECT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1853
                // Subselect
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1854
                $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1855
                $expression = $this->Subselect();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1856
                $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1857
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1858
                // Shortcut: ScalarExpression => SimpleArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1859
                $expression = $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1860
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1861
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1862
            return new AST\SimpleSelectExpression($expression);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1863
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1864
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1865
        $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1866
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1867
        $expression = $this->ScalarExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1868
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1869
        $expr = new AST\SimpleSelectExpression($expression);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1870
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1871
        if ($this->_lexer->isNextToken(Lexer::T_AS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1872
            $this->match(Lexer::T_AS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1873
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1874
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1875
        if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1876
            $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1877
            $resultVariable = $this->AliasResultVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1878
            $expr->fieldIdentificationVariable = $resultVariable;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1879
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1880
            // Include AliasResultVariable in query components.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1881
            $this->_queryComponents[$resultVariable] = array(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1882
                'resultvariable' => $expr,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1883
                'nestingLevel'   => $this->_nestingLevel,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1884
                'token'          => $token,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1885
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1886
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1887
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1888
        return $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1889
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1890
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1891
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1892
     * ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1893
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1894
     * @return \Doctrine\ORM\Query\AST\ConditionalExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1895
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1896
    public function ConditionalExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1897
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1898
        $conditionalTerms = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1899
        $conditionalTerms[] = $this->ConditionalTerm();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1900
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1901
        while ($this->_lexer->isNextToken(Lexer::T_OR)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1902
            $this->match(Lexer::T_OR);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1903
            $conditionalTerms[] = $this->ConditionalTerm();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1904
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1905
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1906
        // Phase 1 AST optimization: Prevent AST\ConditionalExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1907
        // if only one AST\ConditionalTerm is defined
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1908
        if (count($conditionalTerms) == 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1909
            return $conditionalTerms[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1910
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1911
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1912
        return new AST\ConditionalExpression($conditionalTerms);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1913
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1914
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1915
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1916
     * ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1917
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1918
     * @return \Doctrine\ORM\Query\AST\ConditionalTerm
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1919
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1920
    public function ConditionalTerm()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1921
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1922
        $conditionalFactors = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1923
        $conditionalFactors[] = $this->ConditionalFactor();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1924
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1925
        while ($this->_lexer->isNextToken(Lexer::T_AND)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1926
            $this->match(Lexer::T_AND);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1927
            $conditionalFactors[] = $this->ConditionalFactor();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1928
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1929
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1930
        // Phase 1 AST optimization: Prevent AST\ConditionalTerm
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1931
        // if only one AST\ConditionalFactor is defined
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1932
        if (count($conditionalFactors) == 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1933
            return $conditionalFactors[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1934
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1935
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1936
        return new AST\ConditionalTerm($conditionalFactors);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1937
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1938
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1939
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1940
     * ConditionalFactor ::= ["NOT"] ConditionalPrimary
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1941
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1942
     * @return \Doctrine\ORM\Query\AST\ConditionalFactor
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1943
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1944
    public function ConditionalFactor()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1945
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1946
        $not = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1947
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1948
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1949
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1950
            $not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1951
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1952
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1953
        $conditionalPrimary = $this->ConditionalPrimary();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1954
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1955
        // Phase 1 AST optimization: Prevent AST\ConditionalFactor
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1956
        // if only one AST\ConditionalPrimary is defined
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1957
        if ( ! $not) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1958
            return $conditionalPrimary;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1959
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1960
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1961
        $conditionalFactor = new AST\ConditionalFactor($conditionalPrimary);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1962
        $conditionalFactor->not = $not;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1963
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1964
        return $conditionalFactor;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1965
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1966
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1967
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1968
     * ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1969
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1970
     * @return Doctrine\ORM\Query\AST\ConditionalPrimary
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1971
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1972
    public function ConditionalPrimary()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1973
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1974
        $condPrimary = new AST\ConditionalPrimary;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1975
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1976
        if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1977
            // Peek beyond the matching closing paranthesis ')'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1978
            $peek = $this->_peekBeyondClosingParenthesis();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1979
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1980
            if (in_array($peek['value'], array("=",  "<", "<=", "<>", ">", ">=", "!=")) ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1981
                    $peek['type'] === Lexer::T_NOT ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1982
                    $peek['type'] === Lexer::T_BETWEEN ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1983
                    $peek['type'] === Lexer::T_LIKE ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1984
                    $peek['type'] === Lexer::T_IN ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1985
                    $peek['type'] === Lexer::T_IS ||
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1986
                    $peek['type'] === Lexer::T_EXISTS) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1987
                $condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1988
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1989
                $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1990
                $condPrimary->conditionalExpression = $this->ConditionalExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1991
                $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1992
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1993
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1994
            $condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1995
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1996
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1997
        return $condPrimary;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1998
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1999
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2000
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2001
     * SimpleConditionalExpression ::=
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2002
     *      ComparisonExpression | BetweenExpression | LikeExpression |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2003
     *      InExpression | NullComparisonExpression | ExistsExpression |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2004
     *      EmptyCollectionComparisonExpression | CollectionMemberExpression |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2005
     *      InstanceOfExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2006
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2007
    public function SimpleConditionalExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2008
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2009
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2010
            $token = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2011
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2012
            $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2013
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2014
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2015
        if ($token['type'] === Lexer::T_EXISTS) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2016
            return $this->ExistsExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2017
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2018
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2019
        $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2020
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2021
        if ($token['type'] === Lexer::T_IDENTIFIER || $token['type'] === Lexer::T_INPUT_PARAMETER) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2022
            if ($peek['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2023
                // Peek beyond the matching closing paranthesis ')'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2024
                $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2025
                $token = $this->_peekBeyondClosingParenthesis();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2026
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2027
                // Peek beyond the PathExpression (or InputParameter)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2028
                $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2029
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2030
                while ($peek['value'] === '.') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2031
                    $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2032
                    $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2033
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2034
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2035
                // Also peek beyond a NOT if there is one
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2036
                if ($peek['type'] === Lexer::T_NOT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2037
                    $peek = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2038
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2039
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2040
                $token = $peek;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2041
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2042
                // We need to go even further in case of IS (differenciate between NULL and EMPTY)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2043
                $lookahead = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2044
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2045
                // Also peek beyond a NOT if there is one
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2046
                if ($lookahead['type'] === Lexer::T_NOT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2047
                    $lookahead = $this->_lexer->peek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2048
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2049
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2050
                $this->_lexer->resetPeek();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2051
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2052
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2053
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2054
        switch ($token['type']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2055
            case Lexer::T_BETWEEN:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2056
                return $this->BetweenExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2057
            case Lexer::T_LIKE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2058
                return $this->LikeExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2059
            case Lexer::T_IN:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2060
                return $this->InExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2061
            case Lexer::T_INSTANCE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2062
                return $this->InstanceOfExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2063
            case Lexer::T_IS:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2064
                if ($lookahead['type'] == Lexer::T_NULL) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2065
                    return $this->NullComparisonExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2066
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2067
                return $this->EmptyCollectionComparisonExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2068
            case Lexer::T_MEMBER:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2069
                return $this->CollectionMemberExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2070
            default:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2071
                return $this->ComparisonExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2072
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2073
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2074
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2075
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2076
     * EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2077
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2078
     * @return \Doctrine\ORM\Query\AST\EmptyCollectionComparisonExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2079
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2080
    public function EmptyCollectionComparisonExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2081
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2082
        $emptyColletionCompExpr = new AST\EmptyCollectionComparisonExpression(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2083
            $this->CollectionValuedPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2084
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2085
        $this->match(Lexer::T_IS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2086
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2087
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2088
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2089
            $emptyColletionCompExpr->not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2090
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2091
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2092
        $this->match(Lexer::T_EMPTY);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2093
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2094
        return $emptyColletionCompExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2095
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2096
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2097
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2098
     * CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2099
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2100
     * EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2101
     * SimpleEntityExpression ::= IdentificationVariable | InputParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2102
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2103
     * @return \Doctrine\ORM\Query\AST\CollectionMemberExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2104
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2105
    public function CollectionMemberExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2106
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2107
        $not = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2108
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2109
        $entityExpr = $this->EntityExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2110
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2111
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2112
            $not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2113
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2114
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2115
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2116
        $this->match(Lexer::T_MEMBER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2117
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2118
        if ($this->_lexer->isNextToken(Lexer::T_OF)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2119
            $this->match(Lexer::T_OF);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2120
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2121
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2122
        $collMemberExpr = new AST\CollectionMemberExpression(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2123
            $entityExpr, $this->CollectionValuedPathExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2124
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2125
        $collMemberExpr->not = $not;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2126
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2127
        return $collMemberExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2128
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2129
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2130
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2131
     * Literal ::= string | char | integer | float | boolean
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2132
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2133
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2134
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2135
    public function Literal()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2136
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2137
        switch ($this->_lexer->lookahead['type']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2138
            case Lexer::T_STRING:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2139
                $this->match(Lexer::T_STRING);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2140
                return new AST\Literal(AST\Literal::STRING, $this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2141
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2142
            case Lexer::T_INTEGER:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2143
            case Lexer::T_FLOAT:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2144
                $this->match(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2145
                    $this->_lexer->isNextToken(Lexer::T_INTEGER) ? Lexer::T_INTEGER : Lexer::T_FLOAT
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2146
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2147
                return new AST\Literal(AST\Literal::NUMERIC, $this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2148
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2149
            case Lexer::T_TRUE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2150
            case Lexer::T_FALSE:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2151
                $this->match(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2152
                    $this->_lexer->isNextToken(Lexer::T_TRUE) ? Lexer::T_TRUE : Lexer::T_FALSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2153
                );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2154
                return new AST\Literal(AST\Literal::BOOLEAN, $this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2155
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2156
            default:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2157
                $this->syntaxError('Literal');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2158
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2159
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2160
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2161
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2162
     * InParameter ::= Literal | InputParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2163
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2164
     * @return string | \Doctrine\ORM\Query\AST\InputParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2165
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2166
    public function InParameter()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2167
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2168
        if ($this->_lexer->lookahead['type'] == Lexer::T_INPUT_PARAMETER) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2169
            return $this->InputParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2170
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2171
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2172
        return $this->Literal();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2173
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2174
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2175
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2176
     * InputParameter ::= PositionalParameter | NamedParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2177
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2178
     * @return \Doctrine\ORM\Query\AST\InputParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2179
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2180
    public function InputParameter()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2181
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2182
        $this->match(Lexer::T_INPUT_PARAMETER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2183
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2184
        return new AST\InputParameter($this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2185
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2186
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2187
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2188
     * ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2189
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2190
     * @return \Doctrine\ORM\Query\AST\ArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2191
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2192
    public function ArithmeticExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2193
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2194
        $expr = new AST\ArithmeticExpression;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2195
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2196
        if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2197
            $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2198
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2199
            if ($peek['type'] === Lexer::T_SELECT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2200
                $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2201
                $expr->subselect = $this->Subselect();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2202
                $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2203
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2204
                return $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2205
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2206
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2207
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2208
        $expr->simpleArithmeticExpression = $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2209
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2210
        return $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2211
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2212
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2213
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2214
     * SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2215
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2216
     * @return \Doctrine\ORM\Query\AST\SimpleArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2217
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2218
    public function SimpleArithmeticExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2219
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2220
        $terms = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2221
        $terms[] = $this->ArithmeticTerm();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2222
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2223
        while (($isPlus = $this->_lexer->isNextToken(Lexer::T_PLUS)) || $this->_lexer->isNextToken(Lexer::T_MINUS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2224
            $this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2225
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2226
            $terms[] = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2227
            $terms[] = $this->ArithmeticTerm();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2228
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2229
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2230
        // Phase 1 AST optimization: Prevent AST\SimpleArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2231
        // if only one AST\ArithmeticTerm is defined
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2232
        if (count($terms) == 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2233
            return $terms[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2234
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2235
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2236
        return new AST\SimpleArithmeticExpression($terms);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2237
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2238
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2239
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2240
     * ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2241
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2242
     * @return \Doctrine\ORM\Query\AST\ArithmeticTerm
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2243
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2244
    public function ArithmeticTerm()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2245
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2246
        $factors = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2247
        $factors[] = $this->ArithmeticFactor();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2248
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2249
        while (($isMult = $this->_lexer->isNextToken(Lexer::T_MULTIPLY)) || $this->_lexer->isNextToken(Lexer::T_DIVIDE)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2250
            $this->match(($isMult) ? Lexer::T_MULTIPLY : Lexer::T_DIVIDE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2251
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2252
            $factors[] = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2253
            $factors[] = $this->ArithmeticFactor();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2254
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2255
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2256
        // Phase 1 AST optimization: Prevent AST\ArithmeticTerm
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2257
        // if only one AST\ArithmeticFactor is defined
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2258
        if (count($factors) == 1) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2259
            return $factors[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2260
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2261
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2262
        return new AST\ArithmeticTerm($factors);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2263
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2264
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2265
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2266
     * ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2267
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2268
     * @return \Doctrine\ORM\Query\AST\ArithmeticFactor
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2269
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2270
    public function ArithmeticFactor()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2271
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2272
        $sign = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2273
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2274
        if (($isPlus = $this->_lexer->isNextToken(Lexer::T_PLUS)) || $this->_lexer->isNextToken(Lexer::T_MINUS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2275
            $this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2276
            $sign = $isPlus;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2277
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2278
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2279
        $primary = $this->ArithmeticPrimary();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2280
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2281
        // Phase 1 AST optimization: Prevent AST\ArithmeticFactor
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2282
        // if only one AST\ArithmeticPrimary is defined
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2283
        if ($sign === null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2284
            return $primary;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2285
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2286
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2287
        return new AST\ArithmeticFactor($primary, $sign);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2288
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2289
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2290
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2291
     * ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2292
     *          | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2293
     *          | FunctionsReturningDatetime | IdentificationVariable
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2294
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2295
    public function ArithmeticPrimary()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2296
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2297
        if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2298
            $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2299
            $expr = $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2300
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2301
            $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2302
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2303
            return $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2304
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2305
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2306
        switch ($this->_lexer->lookahead['type']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2307
            case Lexer::T_IDENTIFIER:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2308
                $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2309
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2310
                if ($peek['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2311
                    return $this->FunctionDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2312
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2313
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2314
                if ($peek['value'] == '.') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2315
                    return $this->SingleValuedPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2316
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2317
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2318
                return $this->StateFieldPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2319
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2320
            case Lexer::T_INPUT_PARAMETER:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2321
                return $this->InputParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2322
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2323
            default:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2324
                $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2325
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2326
                if ($peek['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2327
                    if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2328
                        return $this->AggregateExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2329
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2330
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2331
                    return $this->FunctionDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2332
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2333
                    return $this->Literal();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2334
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2335
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2336
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2337
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2338
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2339
     * StringExpression ::= StringPrimary | "(" Subselect ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2340
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2341
     * @return \Doctrine\ORM\Query\AST\StringPrimary |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2342
     *         \Doctrine]ORM\Query\AST\Subselect
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2343
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2344
    public function StringExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2345
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2346
        if ($this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2347
            $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2348
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2349
            if ($peek['type'] === Lexer::T_SELECT) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2350
                $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2351
                $expr = $this->Subselect();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2352
                $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2353
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2354
                return $expr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2355
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2356
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2357
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2358
        return $this->StringPrimary();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2359
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2360
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2361
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2362
     * StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2363
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2364
    public function StringPrimary()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2365
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2366
        if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2367
            $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2368
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2369
            if ($peek['value'] == '.') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2370
                return $this->StateFieldPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2371
            } else if ($peek['value'] == '(') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2372
                // do NOT directly go to FunctionsReturningString() because it doesnt check for custom functions.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2373
                return $this->FunctionDeclaration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2374
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2375
                $this->syntaxError("'.' or '('");
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2376
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2377
        } else if ($this->_lexer->isNextToken(Lexer::T_STRING)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2378
            $this->match(Lexer::T_STRING);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2379
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2380
            return $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2381
        } else if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2382
            return $this->InputParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2383
        } else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2384
            return $this->AggregateExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2385
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2386
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2387
        $this->syntaxError('StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2388
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2389
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2390
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2391
     * EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2392
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2393
     * @return \Doctrine\ORM\Query\AST\SingleValuedAssociationPathExpression |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2394
     *         \Doctrine\ORM\Query\AST\SimpleEntityExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2395
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2396
    public function EntityExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2397
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2398
        $glimpse = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2399
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2400
        if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER) && $glimpse['value'] === '.') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2401
            return $this->SingleValuedAssociationPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2402
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2403
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2404
        return $this->SimpleEntityExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2405
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2406
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2407
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2408
     * SimpleEntityExpression ::= IdentificationVariable | InputParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2409
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2410
     * @return string | \Doctrine\ORM\Query\AST\InputParameter
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2411
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2412
    public function SimpleEntityExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2413
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2414
        if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2415
            return $this->InputParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2416
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2417
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2418
        return $this->IdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2419
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2420
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2421
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2422
     * AggregateExpression ::=
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2423
     *  ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2424
     *  "COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedPathExpression) ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2425
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2426
     * @return \Doctrine\ORM\Query\AST\AggregateExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2427
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2428
    public function AggregateExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2429
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2430
        $isDistinct = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2431
        $functionName = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2432
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2433
        if ($this->_lexer->isNextToken(Lexer::T_COUNT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2434
            $this->match(Lexer::T_COUNT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2435
            $functionName = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2436
            $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2437
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2438
            if ($this->_lexer->isNextToken(Lexer::T_DISTINCT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2439
                $this->match(Lexer::T_DISTINCT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2440
                $isDistinct = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2441
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2442
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2443
            $pathExp = $this->SingleValuedPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2444
            $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2445
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2446
            if ($this->_lexer->isNextToken(Lexer::T_AVG)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2447
                $this->match(Lexer::T_AVG);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2448
            } else if ($this->_lexer->isNextToken(Lexer::T_MAX)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2449
                $this->match(Lexer::T_MAX);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2450
            } else if ($this->_lexer->isNextToken(Lexer::T_MIN)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2451
                $this->match(Lexer::T_MIN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2452
            } else if ($this->_lexer->isNextToken(Lexer::T_SUM)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2453
                $this->match(Lexer::T_SUM);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2454
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2455
                $this->syntaxError('One of: MAX, MIN, AVG, SUM, COUNT');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2456
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2457
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2458
            $functionName = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2459
            $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2460
            $pathExp = $this->SimpleArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2461
            $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2462
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2463
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2464
        return new AST\AggregateExpression($functionName, $pathExp, $isDistinct);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2465
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2466
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2467
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2468
     * QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2469
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2470
     * @return \Doctrine\ORM\Query\AST\QuantifiedExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2471
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2472
    public function QuantifiedExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2473
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2474
        $type = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2475
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2476
        if ($this->_lexer->isNextToken(Lexer::T_ALL)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2477
            $this->match(Lexer::T_ALL);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2478
            $type = 'ALL';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2479
        } else if ($this->_lexer->isNextToken(Lexer::T_ANY)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2480
            $this->match(Lexer::T_ANY);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2481
             $type = 'ANY';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2482
        } else if ($this->_lexer->isNextToken(Lexer::T_SOME)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2483
            $this->match(Lexer::T_SOME);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2484
             $type = 'SOME';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2485
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2486
            $this->syntaxError('ALL, ANY or SOME');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2487
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2488
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2489
        $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2490
        $qExpr = new AST\QuantifiedExpression($this->Subselect());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2491
        $qExpr->type = $type;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2492
        $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2493
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2494
        return $qExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2495
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2496
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2497
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2498
     * BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2499
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2500
     * @return \Doctrine\ORM\Query\AST\BetweenExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2501
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2502
    public function BetweenExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2503
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2504
        $not = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2505
        $arithExpr1 = $this->ArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2506
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2507
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2508
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2509
            $not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2510
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2511
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2512
        $this->match(Lexer::T_BETWEEN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2513
        $arithExpr2 = $this->ArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2514
        $this->match(Lexer::T_AND);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2515
        $arithExpr3 = $this->ArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2516
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2517
        $betweenExpr = new AST\BetweenExpression($arithExpr1, $arithExpr2, $arithExpr3);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2518
        $betweenExpr->not = $not;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2519
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2520
        return $betweenExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2521
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2522
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2523
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2524
     * ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression )
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2525
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2526
     * @return \Doctrine\ORM\Query\AST\ComparisonExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2527
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2528
    public function ComparisonExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2529
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2530
        $peek = $this->_lexer->glimpse();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2531
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2532
        $leftExpr = $this->ArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2533
        $operator = $this->ComparisonOperator();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2534
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2535
        if ($this->_isNextAllAnySome()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2536
            $rightExpr = $this->QuantifiedExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2537
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2538
            $rightExpr = $this->ArithmeticExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2539
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2540
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2541
        return new AST\ComparisonExpression($leftExpr, $operator, $rightExpr);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2542
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2543
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2544
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2545
     * InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2546
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2547
     * @return \Doctrine\ORM\Query\AST\InExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2548
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2549
    public function InExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2550
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2551
        $inExpression = new AST\InExpression($this->SingleValuedPathExpression());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2552
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2553
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2554
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2555
            $inExpression->not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2556
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2557
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2558
        $this->match(Lexer::T_IN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2559
        $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2560
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2561
        if ($this->_lexer->isNextToken(Lexer::T_SELECT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2562
            $inExpression->subselect = $this->Subselect();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2563
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2564
            $literals = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2565
            $literals[] = $this->InParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2566
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2567
            while ($this->_lexer->isNextToken(Lexer::T_COMMA)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2568
                $this->match(Lexer::T_COMMA);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2569
                $literals[] = $this->InParameter();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2570
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2571
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2572
            $inExpression->literals = $literals;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2573
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2574
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2575
        $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2576
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2577
        return $inExpression;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2578
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2579
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2580
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2581
     * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (AbstractSchemaName | InputParameter)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2582
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2583
     * @return \Doctrine\ORM\Query\AST\InstanceOfExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2584
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2585
    public function InstanceOfExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2586
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2587
        $instanceOfExpression = new AST\InstanceOfExpression($this->IdentificationVariable());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2588
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2589
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2590
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2591
            $instanceOfExpression->not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2592
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2593
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2594
        $this->match(Lexer::T_INSTANCE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2595
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2596
        if ($this->_lexer->isNextToken(Lexer::T_OF)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2597
            $this->match(Lexer::T_OF);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2598
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2599
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2600
        if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2601
            $this->match(Lexer::T_INPUT_PARAMETER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2602
            $exprValue = new AST\InputParameter($this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2603
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2604
            $exprValue = $this->AliasIdentificationVariable();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2605
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2606
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2607
        $instanceOfExpression->value = $exprValue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2608
        
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2609
        return $instanceOfExpression;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2610
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2611
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2612
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2613
     * LikeExpression ::= StringExpression ["NOT"] "LIKE" (string | input_parameter) ["ESCAPE" char]
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2614
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2615
     * @return \Doctrine\ORM\Query\AST\LikeExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2616
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2617
    public function LikeExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2618
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2619
        $stringExpr = $this->StringExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2620
        $not = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2621
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2622
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2623
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2624
            $not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2625
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2626
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2627
        $this->match(Lexer::T_LIKE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2628
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2629
        if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2630
            $this->match(Lexer::T_INPUT_PARAMETER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2631
            $stringPattern = new AST\InputParameter($this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2632
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2633
            $this->match(Lexer::T_STRING);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2634
            $stringPattern = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2635
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2636
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2637
        $escapeChar = null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2638
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2639
        if ($this->_lexer->lookahead['type'] === Lexer::T_ESCAPE) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2640
            $this->match(Lexer::T_ESCAPE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2641
            $this->match(Lexer::T_STRING);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2642
            $escapeChar = $this->_lexer->token['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2643
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2644
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2645
        $likeExpr = new AST\LikeExpression($stringExpr, $stringPattern, $escapeChar);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2646
        $likeExpr->not = $not;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2647
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2648
        return $likeExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2649
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2650
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2651
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2652
     * NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2653
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2654
     * @return \Doctrine\ORM\Query\AST\NullComparisonExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2655
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2656
    public function NullComparisonExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2657
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2658
        if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2659
            $this->match(Lexer::T_INPUT_PARAMETER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2660
            $expr = new AST\InputParameter($this->_lexer->token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2661
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2662
            $expr = $this->SingleValuedPathExpression();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2663
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2664
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2665
        $nullCompExpr = new AST\NullComparisonExpression($expr);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2666
        $this->match(Lexer::T_IS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2667
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2668
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2669
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2670
            $nullCompExpr->not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2671
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2672
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2673
        $this->match(Lexer::T_NULL);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2674
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2675
        return $nullCompExpr;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2676
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2677
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2678
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2679
     * ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2680
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2681
     * @return \Doctrine\ORM\Query\AST\ExistsExpression
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2682
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2683
    public function ExistsExpression()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2684
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2685
        $not = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2686
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2687
        if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2688
            $this->match(Lexer::T_NOT);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2689
            $not = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2690
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2691
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2692
        $this->match(Lexer::T_EXISTS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2693
        $this->match(Lexer::T_OPEN_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2694
        $existsExpression = new AST\ExistsExpression($this->Subselect());
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2695
        $existsExpression->not = $not;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2696
        $this->match(Lexer::T_CLOSE_PARENTHESIS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2697
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2698
        return $existsExpression;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2699
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2700
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2701
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2702
     * ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2703
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2704
     * @return string
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2705
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2706
    public function ComparisonOperator()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2707
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2708
        switch ($this->_lexer->lookahead['value']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2709
            case '=':
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2710
                $this->match(Lexer::T_EQUALS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2711
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2712
                return '=';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2713
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2714
            case '<':
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2715
                $this->match(Lexer::T_LOWER_THAN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2716
                $operator = '<';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2717
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2718
                if ($this->_lexer->isNextToken(Lexer::T_EQUALS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2719
                    $this->match(Lexer::T_EQUALS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2720
                    $operator .= '=';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2721
                } else if ($this->_lexer->isNextToken(Lexer::T_GREATER_THAN)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2722
                    $this->match(Lexer::T_GREATER_THAN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2723
                    $operator .= '>';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2724
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2725
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2726
                return $operator;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2727
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2728
            case '>':
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2729
                $this->match(Lexer::T_GREATER_THAN);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2730
                $operator = '>';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2731
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2732
                if ($this->_lexer->isNextToken(Lexer::T_EQUALS)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2733
                    $this->match(Lexer::T_EQUALS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2734
                    $operator .= '=';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2735
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2736
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2737
                return $operator;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2738
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2739
            case '!':
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2740
                $this->match(Lexer::T_NEGATE);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2741
                $this->match(Lexer::T_EQUALS);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2742
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2743
                return '<>';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2744
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2745
            default:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2746
                $this->syntaxError('=, <, <=, <>, >, >=, !=');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2747
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2748
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2749
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2750
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2751
     * FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDatetime
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2752
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2753
    public function FunctionDeclaration()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2754
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2755
        $token = $this->_lexer->lookahead;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2756
        $funcName = strtolower($token['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2757
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2758
        // Check for built-in functions first!
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2759
        if (isset(self::$_STRING_FUNCTIONS[$funcName])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2760
            return $this->FunctionsReturningStrings();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2761
        } else if (isset(self::$_NUMERIC_FUNCTIONS[$funcName])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2762
            return $this->FunctionsReturningNumerics();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2763
        } else if (isset(self::$_DATETIME_FUNCTIONS[$funcName])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2764
            return $this->FunctionsReturningDatetime();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2765
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2766
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2767
        // Check for custom functions afterwards
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2768
        $config = $this->_em->getConfiguration();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2769
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2770
        if ($config->getCustomStringFunction($funcName) !== null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2771
            return $this->CustomFunctionsReturningStrings();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2772
        } else if ($config->getCustomNumericFunction($funcName) !== null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2773
            return $this->CustomFunctionsReturningNumerics();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2774
        } else if ($config->getCustomDatetimeFunction($funcName) !== null) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2775
            return $this->CustomFunctionsReturningDatetime();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2776
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2777
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2778
        $this->syntaxError('known function', $token);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2779
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2780
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2781
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2782
     * FunctionsReturningNumerics ::=
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2783
     *      "LENGTH" "(" StringPrimary ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2784
     *      "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2785
     *      "ABS" "(" SimpleArithmeticExpression ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2786
     *      "SQRT" "(" SimpleArithmeticExpression ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2787
     *      "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2788
     *      "SIZE" "(" CollectionValuedPathExpression ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2789
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2790
    public function FunctionsReturningNumerics()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2791
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2792
        $funcNameLower = strtolower($this->_lexer->lookahead['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2793
        $funcClass = self::$_NUMERIC_FUNCTIONS[$funcNameLower];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2794
        $function = new $funcClass($funcNameLower);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2795
        $function->parse($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2796
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2797
        return $function;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2798
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2799
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2800
    public function CustomFunctionsReturningNumerics()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2801
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2802
        $funcName = strtolower($this->_lexer->lookahead['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2803
        // getCustomNumericFunction is case-insensitive
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2804
        $funcClass = $this->_em->getConfiguration()->getCustomNumericFunction($funcName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2805
        $function = new $funcClass($funcName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2806
        $function->parse($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2807
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2808
        return $function;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2809
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2810
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2811
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2812
     * FunctionsReturningDateTime ::= "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2813
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2814
    public function FunctionsReturningDatetime()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2815
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2816
        $funcNameLower = strtolower($this->_lexer->lookahead['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2817
        $funcClass = self::$_DATETIME_FUNCTIONS[$funcNameLower];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2818
        $function = new $funcClass($funcNameLower);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2819
        $function->parse($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2820
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2821
        return $function;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2822
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2823
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2824
    public function CustomFunctionsReturningDatetime()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2825
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2826
        $funcName = $this->_lexer->lookahead['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2827
        // getCustomDatetimeFunction is case-insensitive
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2828
        $funcClass = $this->_em->getConfiguration()->getCustomDatetimeFunction($funcName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2829
        $function = new $funcClass($funcName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2830
        $function->parse($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2831
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2832
        return $function;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2833
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2834
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2835
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2836
     * FunctionsReturningStrings ::=
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2837
     *   "CONCAT" "(" StringPrimary "," StringPrimary ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2838
     *   "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2839
     *   "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2840
     *   "LOWER" "(" StringPrimary ")" |
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2841
     *   "UPPER" "(" StringPrimary ")"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2842
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2843
    public function FunctionsReturningStrings()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2844
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2845
        $funcNameLower = strtolower($this->_lexer->lookahead['value']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2846
        $funcClass = self::$_STRING_FUNCTIONS[$funcNameLower];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2847
        $function = new $funcClass($funcNameLower);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2848
        $function->parse($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2849
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2850
        return $function;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2851
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2852
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2853
    public function CustomFunctionsReturningStrings()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2854
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2855
        $funcName = $this->_lexer->lookahead['value'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2856
        // getCustomStringFunction is case-insensitive
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2857
        $funcClass = $this->_em->getConfiguration()->getCustomStringFunction($funcName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2858
        $function = new $funcClass($funcName);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2859
        $function->parse($this);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2860
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2861
        return $function;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2862
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2863
}