<?php
							 | 
						|
								
							 | 
						|
								/*
							 | 
						|
								PARTLY BASED ON:
							 | 
						|
								    Copyright (c) 2007 E. W. Bachtal, Inc.
							 | 
						|
								
							 | 
						|
								    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
							 | 
						|
								    and associated documentation files (the "Software"), to deal in the Software without restriction,
							 | 
						|
								    including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
							 | 
						|
								    and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
							 | 
						|
								    subject to the following conditions:
							 | 
						|
								
							 | 
						|
								      The above copyright notice and this permission notice shall be included in all copies or substantial
							 | 
						|
								      portions of the Software.
							 | 
						|
								
							 | 
						|
								    The software is provided "as is", without warranty of any kind, express or implied, including but not
							 | 
						|
								    limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In
							 | 
						|
								    no event shall the authors or copyright holders be liable for any claim, damages or other liability,
							 | 
						|
								    whether in an action of contract, tort or otherwise, arising from, out of or in connection with the
							 | 
						|
								    software or the use or other dealings in the software.
							 | 
						|
								
							 | 
						|
								    http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html
							 | 
						|
								    http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * PHPExcel_Calculation_FormulaParser
							 | 
						|
								 *
							 | 
						|
								 * Copyright (c) 2006 - 2015 PHPExcel
							 | 
						|
								 *
							 | 
						|
								 * This library is free software; you can redistribute it and/or
							 | 
						|
								 * modify it under the terms of the GNU Lesser General Public
							 | 
						|
								 * License as published by the Free Software Foundation; either
							 | 
						|
								 * version 2.1 of the License, or (at your option) any later version.
							 | 
						|
								 *
							 | 
						|
								 * This library is distributed in the hope that it will be useful,
							 | 
						|
								 * but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						|
								 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
							 | 
						|
								 * Lesser General Public License for more details.
							 | 
						|
								 *
							 | 
						|
								 * You should have received a copy of the GNU Lesser General Public
							 | 
						|
								 * License along with this library; if not, write to the Free Software
							 | 
						|
								 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
							 | 
						|
								 *
							 | 
						|
								 * @category   PHPExcel
							 | 
						|
								 * @package    PHPExcel_Calculation
							 | 
						|
								 * @copyright  Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
							 | 
						|
								 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
							 | 
						|
								 * @version    ##VERSION##, ##DATE##
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class PHPExcel_Calculation_FormulaParser
							 | 
						|
								{
							 | 
						|
								    /* Character constants */
							 | 
						|
								    const QUOTE_DOUBLE  = '"';
							 | 
						|
								    const QUOTE_SINGLE  = '\'';
							 | 
						|
								    const BRACKET_CLOSE = ']';
							 | 
						|
								    const BRACKET_OPEN  = '[';
							 | 
						|
								    const BRACE_OPEN    = '{';
							 | 
						|
								    const BRACE_CLOSE   = '}';
							 | 
						|
								    const PAREN_OPEN    = '(';
							 | 
						|
								    const PAREN_CLOSE   = ')';
							 | 
						|
								    const SEMICOLON     = ';';
							 | 
						|
								    const WHITESPACE    = ' ';
							 | 
						|
								    const COMMA         = ',';
							 | 
						|
								    const ERROR_START   = '#';
							 | 
						|
								
							 | 
						|
								    const OPERATORS_SN             = "+-";
							 | 
						|
								    const OPERATORS_INFIX         = "+-*/^&=><";
							 | 
						|
								    const OPERATORS_POSTFIX     = "%";
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Formula
							 | 
						|
								     *
							 | 
						|
								     * @var string
							 | 
						|
								     */
							 | 
						|
								    private $formula;
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Tokens
							 | 
						|
								     *
							 | 
						|
								     * @var PHPExcel_Calculation_FormulaToken[]
							 | 
						|
								     */
							 | 
						|
								    private $tokens = array();
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Create a new PHPExcel_Calculation_FormulaParser
							 | 
						|
								     *
							 | 
						|
								     * @param     string        $pFormula    Formula to parse
							 | 
						|
								     * @throws     PHPExcel_Calculation_Exception
							 | 
						|
								     */
							 | 
						|
								    public function __construct($pFormula = '')
							 | 
						|
								    {
							 | 
						|
								        // Check parameters
							 | 
						|
								        if (is_null($pFormula)) {
							 | 
						|
								            throw new PHPExcel_Calculation_Exception("Invalid parameter passed: formula");
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Initialise values
							 | 
						|
								        $this->formula = trim($pFormula);
							 | 
						|
								        // Parse!
							 | 
						|
								        $this->parseToTokens();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get Formula
							 | 
						|
								     *
							 | 
						|
								     * @return string
							 | 
						|
								     */
							 | 
						|
								    public function getFormula()
							 | 
						|
								    {
							 | 
						|
								        return $this->formula;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get Token
							 | 
						|
								     *
							 | 
						|
								     * @param     int        $pId    Token id
							 | 
						|
								     * @return    string
							 | 
						|
								     * @throws  PHPExcel_Calculation_Exception
							 | 
						|
								     */
							 | 
						|
								    public function getToken($pId = 0)
							 | 
						|
								    {
							 | 
						|
								        if (isset($this->tokens[$pId])) {
							 | 
						|
								            return $this->tokens[$pId];
							 | 
						|
								        } else {
							 | 
						|
								            throw new PHPExcel_Calculation_Exception("Token with id $pId does not exist.");
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get Token count
							 | 
						|
								     *
							 | 
						|
								     * @return string
							 | 
						|
								     */
							 | 
						|
								    public function getTokenCount()
							 | 
						|
								    {
							 | 
						|
								        return count($this->tokens);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Get Tokens
							 | 
						|
								     *
							 | 
						|
								     * @return PHPExcel_Calculation_FormulaToken[]
							 | 
						|
								     */
							 | 
						|
								    public function getTokens()
							 | 
						|
								    {
							 | 
						|
								        return $this->tokens;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /**
							 | 
						|
								     * Parse to tokens
							 | 
						|
								     */
							 | 
						|
								    private function parseToTokens()
							 | 
						|
								    {
							 | 
						|
								        // No attempt is made to verify formulas; assumes formulas are derived from Excel, where
							 | 
						|
								        // they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions.
							 | 
						|
								
							 | 
						|
								        // Check if the formula has a valid starting =
							 | 
						|
								        $formulaLength = strlen($this->formula);
							 | 
						|
								        if ($formulaLength < 2 || $this->formula[0] != '=') {
							 | 
						|
								            return;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Helper variables
							 | 
						|
								        $tokens1    = $tokens2     = $stack = array();
							 | 
						|
								        $inString    = $inPath     = $inRange     = $inError = false;
							 | 
						|
								        $token        = $previousToken    = $nextToken    = null;
							 | 
						|
								
							 | 
						|
								        $index    = 1;
							 | 
						|
								        $value    = '';
							 | 
						|
								
							 | 
						|
								        $ERRORS             = array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A");
							 | 
						|
								        $COMPARATORS_MULTI     = array(">=", "<=", "<>");
							 | 
						|
								
							 | 
						|
								        while ($index < $formulaLength) {
							 | 
						|
								            // state-dependent character evaluation (order is important)
							 | 
						|
								
							 | 
						|
								            // double-quoted strings
							 | 
						|
								            // embeds are doubled
							 | 
						|
								            // end marks token
							 | 
						|
								            if ($inString) {
							 | 
						|
								                if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
							 | 
						|
								                    if ((($index + 2) <= $formulaLength) && ($this->formula[$index + 1] == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) {
							 | 
						|
								                        $value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE;
							 | 
						|
								                        ++$index;
							 | 
						|
								                    } else {
							 | 
						|
								                        $inString = false;
							 | 
						|
								                        $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT);
							 | 
						|
								                        $value = "";
							 | 
						|
								                    }
							 | 
						|
								                } else {
							 | 
						|
								                    $value .= $this->formula[$index];
							 | 
						|
								                }
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // single-quoted strings (links)
							 | 
						|
								            // embeds are double
							 | 
						|
								            // end does not mark a token
							 | 
						|
								            if ($inPath) {
							 | 
						|
								                if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
							 | 
						|
								                    if ((($index + 2) <= $formulaLength) && ($this->formula[$index + 1] == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) {
							 | 
						|
								                        $value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE;
							 | 
						|
								                        ++$index;
							 | 
						|
								                    } else {
							 | 
						|
								                        $inPath = false;
							 | 
						|
								                    }
							 | 
						|
								                } else {
							 | 
						|
								                    $value .= $this->formula[$index];
							 | 
						|
								                }
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // bracked strings (R1C1 range index or linked workbook name)
							 | 
						|
								            // no embeds (changed to "()" by Excel)
							 | 
						|
								            // end does not mark a token
							 | 
						|
								            if ($inRange) {
							 | 
						|
								                if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) {
							 | 
						|
								                    $inRange = false;
							 | 
						|
								                }
							 | 
						|
								                $value .= $this->formula[$index];
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // error values
							 | 
						|
								            // end marks a token, determined from absolute list of values
							 | 
						|
								            if ($inError) {
							 | 
						|
								                $value .= $this->formula[$index];
							 | 
						|
								                ++$index;
							 | 
						|
								                if (in_array($value, $ERRORS)) {
							 | 
						|
								                    $inError = false;
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // scientific notation check
							 | 
						|
								            if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->formula[$index]) !== false) {
							 | 
						|
								                if (strlen($value) > 1) {
							 | 
						|
								                    if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->formula[$index]) != 0) {
							 | 
						|
								                        $value .= $this->formula[$index];
							 | 
						|
								                        ++$index;
							 | 
						|
								                        continue;
							 | 
						|
								                    }
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // independent character evaluation (order not important)
							 | 
						|
								
							 | 
						|
								            // establish state-dependent character evaluations
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
							 | 
						|
								                if (strlen($value > 0)) {
							 | 
						|
								                    // unexpected
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                $inString = true;
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    // unexpected
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                $inPath = true;
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) {
							 | 
						|
								                $inRange = true;
							 | 
						|
								                $value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN;
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::ERROR_START) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    // unexpected
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                $inError = true;
							 | 
						|
								                $value .= PHPExcel_Calculation_FormulaParser::ERROR_START;
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // mark start and end of arrays and array rows
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    // unexpected
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								                $stack[] = clone $tmp;
							 | 
						|
								
							 | 
						|
								                $tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								                $stack[] = clone $tmp;
							 | 
						|
								
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::SEMICOLON) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $tmp = array_pop($stack);
							 | 
						|
								                $tmp->setValue("");
							 | 
						|
								                $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								
							 | 
						|
								                $tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								
							 | 
						|
								                $tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								                $stack[] = clone $tmp;
							 | 
						|
								
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $tmp = array_pop($stack);
							 | 
						|
								                $tmp->setValue("");
							 | 
						|
								                $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								
							 | 
						|
								                $tmp = array_pop($stack);
							 | 
						|
								                $tmp->setValue("");
							 | 
						|
								                $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // trim white-space
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::WHITESPACE) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                $tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE);
							 | 
						|
								                ++$index;
							 | 
						|
								                while (($this->formula[$index] == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) {
							 | 
						|
								                    ++$index;
							 | 
						|
								                }
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // multi-character comparators
							 | 
						|
								            if (($index + 2) <= $formulaLength) {
							 | 
						|
								                if (in_array(substr($this->formula, $index, 2), $COMPARATORS_MULTI)) {
							 | 
						|
								                    if (strlen($value) > 0) {
							 | 
						|
								                        $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                        $value = "";
							 | 
						|
								                    }
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
							 | 
						|
								                    $index += 2;
							 | 
						|
								                    continue;
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // standard infix operators
							 | 
						|
								            if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->formula[$index]) !== false) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                $tokens1[] = new PHPExcel_Calculation_FormulaToken($this->formula[$index], PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX);
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // standard postfix operators (only one)
							 | 
						|
								            if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->formula[$index]) !== false) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								                $tokens1[] = new PHPExcel_Calculation_FormulaToken($this->formula[$index], PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX);
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // start subexpression or function
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
							 | 
						|
								                    $tokens1[] = $tmp;
							 | 
						|
								                    $stack[] = clone $tmp;
							 | 
						|
								                    $value = "";
							 | 
						|
								                } else {
							 | 
						|
								                    $tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
							 | 
						|
								                    $tokens1[] = $tmp;
							 | 
						|
								                    $stack[] = clone $tmp;
							 | 
						|
								                }
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // function, subexpression, or array parameters, or operand unions
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::COMMA) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $tmp = array_pop($stack);
							 | 
						|
								                $tmp->setValue("");
							 | 
						|
								                $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
							 | 
						|
								                $stack[] = $tmp;
							 | 
						|
								
							 | 
						|
								                if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION);
							 | 
						|
								                } else {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
							 | 
						|
								                }
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // stop subexpression
							 | 
						|
								            if ($this->formula[$index] == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) {
							 | 
						|
								                if (strlen($value) > 0) {
							 | 
						|
								                    $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								                    $value = "";
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $tmp = array_pop($stack);
							 | 
						|
								                $tmp->setValue("");
							 | 
						|
								                $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
							 | 
						|
								                $tokens1[] = $tmp;
							 | 
						|
								
							 | 
						|
								                ++$index;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // token accumulation
							 | 
						|
								            $value .= $this->formula[$index];
							 | 
						|
								            ++$index;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // dump remaining accumulation
							 | 
						|
								        if (strlen($value) > 0) {
							 | 
						|
								            $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections
							 | 
						|
								        $tokenCount = count($tokens1);
							 | 
						|
								        for ($i = 0; $i < $tokenCount; ++$i) {
							 | 
						|
								            $token = $tokens1[$i];
							 | 
						|
								            if (isset($tokens1[$i - 1])) {
							 | 
						|
								                $previousToken = $tokens1[$i - 1];
							 | 
						|
								            } else {
							 | 
						|
								                $previousToken = null;
							 | 
						|
								            }
							 | 
						|
								            if (isset($tokens1[$i + 1])) {
							 | 
						|
								                $nextToken = $tokens1[$i + 1];
							 | 
						|
								            } else {
							 | 
						|
								                $nextToken = null;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (is_null($token)) {
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) {
							 | 
						|
								                $tokens2[] = $token;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (is_null($previousToken)) {
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (! (
							 | 
						|
								                    (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
							 | 
						|
								                    (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
							 | 
						|
								                    ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
							 | 
						|
								                  ) ) {
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (is_null($nextToken)) {
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (! (
							 | 
						|
								                    (($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
							 | 
						|
								                    (($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
							 | 
						|
								                    ($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
							 | 
						|
								                  ) ) {
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            $tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION);
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators
							 | 
						|
								        // to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names
							 | 
						|
								        $this->tokens = array();
							 | 
						|
								
							 | 
						|
								        $tokenCount = count($tokens2);
							 | 
						|
								        for ($i = 0; $i < $tokenCount; ++$i) {
							 | 
						|
								            $token = $tokens2[$i];
							 | 
						|
								            if (isset($tokens2[$i - 1])) {
							 | 
						|
								                $previousToken = $tokens2[$i - 1];
							 | 
						|
								            } else {
							 | 
						|
								                $previousToken = null;
							 | 
						|
								            }
							 | 
						|
								            if (isset($tokens2[$i + 1])) {
							 | 
						|
								                $nextToken = $tokens2[$i + 1];
							 | 
						|
								            } else {
							 | 
						|
								                $nextToken = null;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (is_null($token)) {
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") {
							 | 
						|
								                if ($i == 0) {
							 | 
						|
								                    $token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
							 | 
						|
								                } elseif ((($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) &&
							 | 
						|
								                    ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
							 | 
						|
								                    (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) &&
							 | 
						|
								                    ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
							 | 
						|
								                    ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
							 | 
						|
								                    ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)) {
							 | 
						|
								                    $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
							 | 
						|
								                } else {
							 | 
						|
								                    $token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $this->tokens[] = $token;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") {
							 | 
						|
								                if ($i == 0) {
							 | 
						|
								                    continue;
							 | 
						|
								                } elseif ((($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) &&
							 | 
						|
								                    ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
							 | 
						|
								                    (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) &&
							 | 
						|
								                    ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
							 | 
						|
								                    ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
							 | 
						|
								                    ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)) {
							 | 
						|
								                    $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
							 | 
						|
								                } else {
							 | 
						|
								                    continue;
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $this->tokens[] = $token;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX &&
							 | 
						|
								                $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
							 | 
						|
								                if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) {
							 | 
						|
								                    $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
							 | 
						|
								                } elseif ($token->getValue() == "&") {
							 | 
						|
								                    $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION);
							 | 
						|
								                } else {
							 | 
						|
								                    $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $this->tokens[] = $token;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND &&
							 | 
						|
								                $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
							 | 
						|
								                if (!is_numeric($token->getValue())) {
							 | 
						|
								                    if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) {
							 | 
						|
								                        $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
							 | 
						|
								                    } else {
							 | 
						|
								                        $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE);
							 | 
						|
								                    }
							 | 
						|
								                } else {
							 | 
						|
								                    $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER);
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                $this->tokens[] = $token;
							 | 
						|
								                continue;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
							 | 
						|
								                if (strlen($token->getValue() > 0)) {
							 | 
						|
								                    if (substr($token->getValue(), 0, 1) == "@") {
							 | 
						|
								                        $token->setValue(substr($token->getValue(), 1));
							 | 
						|
								                    }
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            $this->tokens[] = $token;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								}
							 |