Subversion Repositories eFlore/Applications.cel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2388 jpm 1
<?php
2
/**
3
 * PHPExcel
4
 *
5
 * Copyright (c) 2006 - 2013 PHPExcel
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
 *
21
 * @category   PHPExcel
22
 * @package    PHPExcel_Calculation
23
 * @copyright  Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
24
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
25
 * @version    ##VERSION##, ##DATE##
26
 */
27
 
28
 
29
/*
30
PARTLY BASED ON:
31
	Copyright (c) 2007 E. W. Bachtal, Inc.
32
 
33
	Permission is hereby granted, free of charge, to any person obtaining a copy of this software
34
	and associated documentation files (the "Software"), to deal in the Software without restriction,
35
	including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
36
	and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
37
	subject to the following conditions:
38
 
39
	  The above copyright notice and this permission notice shall be included in all copies or substantial
40
	  portions of the Software.
41
 
42
	The software is provided "as is", without warranty of any kind, express or implied, including but not
43
	limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In
44
	no event shall the authors or copyright holders be liable for any claim, damages or other liability,
45
	whether in an action of contract, tort or otherwise, arising from, out of or in connection with the
46
	software or the use or other dealings in the software.
47
 
48
	http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html
49
	http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html
50
*/
51
 
52
/**
53
 * PHPExcel_Calculation_FormulaParser
54
 *
55
 * @category   PHPExcel
56
 * @package    PHPExcel_Calculation
57
 * @copyright  Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
58
 */
59
class PHPExcel_Calculation_FormulaParser {
60
	/* Character constants */
61
	const QUOTE_DOUBLE  = '"';
62
	const QUOTE_SINGLE  = '\'';
63
	const BRACKET_CLOSE = ']';
64
	const BRACKET_OPEN  = '[';
65
	const BRACE_OPEN    = '{';
66
	const BRACE_CLOSE   = '}';
67
	const PAREN_OPEN    = '(';
68
	const PAREN_CLOSE   = ')';
69
	const SEMICOLON     = ';';
70
	const WHITESPACE    = ' ';
71
	const COMMA         = ',';
72
	const ERROR_START   = '#';
73
 
74
	const OPERATORS_SN 			= "+-";
75
	const OPERATORS_INFIX 		= "+-*/^&=><";
76
	const OPERATORS_POSTFIX 	= "%";
77
 
78
	/**
79
	 * Formula
80
	 *
81
	 * @var string
82
	 */
83
	private $_formula;
84
 
85
	/**
86
	 * Tokens
87
	 *
88
	 * @var PHPExcel_Calculation_FormulaToken[]
89
	 */
90
	private $_tokens = array();
91
 
92
    /**
93
     * Create a new PHPExcel_Calculation_FormulaParser
94
     *
95
     * @param 	string		$pFormula	Formula to parse
96
     * @throws 	PHPExcel_Calculation_Exception
97
     */
98
    public function __construct($pFormula = '')
99
    {
100
    	// Check parameters
101
    	if (is_null($pFormula)) {
102
    		throw new PHPExcel_Calculation_Exception("Invalid parameter passed: formula");
103
    	}
104
 
105
    	// Initialise values
106
    	$this->_formula = trim($pFormula);
107
    	// Parse!
108
    	$this->_parseToTokens();
109
    }
110
 
111
    /**
112
     * Get Formula
113
     *
114
     * @return string
115
     */
116
    public function getFormula() {
117
    	return $this->_formula;
118
    }
119
 
120
    /**
121
     * Get Token
122
     *
123
     * @param 	int		$pId	Token id
124
     * @return	string
125
     * @throws  PHPExcel_Calculation_Exception
126
     */
127
    public function getToken($pId = 0) {
128
    	if (isset($this->_tokens[$pId])) {
129
    		return $this->_tokens[$pId];
130
    	} else {
131
    		throw new PHPExcel_Calculation_Exception("Token with id $pId does not exist.");
132
    	}
133
    }
134
 
135
    /**
136
     * Get Token count
137
     *
138
     * @return string
139
     */
140
    public function getTokenCount() {
141
    	return count($this->_tokens);
142
    }
143
 
144
    /**
145
     * Get Tokens
146
     *
147
     * @return PHPExcel_Calculation_FormulaToken[]
148
     */
149
    public function getTokens() {
150
    	return $this->_tokens;
151
    }
152
 
153
    /**
154
     * Parse to tokens
155
     */
156
    private function _parseToTokens() {
157
		// No attempt is made to verify formulas; assumes formulas are derived from Excel, where
158
		// they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions.
159
 
160
		// Check if the formula has a valid starting =
161
		$formulaLength = strlen($this->_formula);
162
		if ($formulaLength < 2 || $this->_formula{0} != '=') return;
163
 
164
		// Helper variables
165
		$tokens1	= $tokens2 	= $stack = array();
166
		$inString	= $inPath 	= $inRange 	= $inError = false;
167
		$token		= $previousToken	= $nextToken	= null;
168
 
169
		$index	= 1;
170
		$value	= '';
171
 
172
		$ERRORS 			= array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A");
173
		$COMPARATORS_MULTI 	= array(">=", "<=", "<>");
174
 
175
		while ($index < $formulaLength) {
176
			// state-dependent character evaluation (order is important)
177
 
178
			// double-quoted strings
179
			// embeds are doubled
180
			// end marks token
181
			if ($inString) {
182
				if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
183
					if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) {
184
						$value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE;
185
						++$index;
186
					} else {
187
						$inString = false;
188
						$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT);
189
						$value = "";
190
					}
191
				} else {
192
					$value .= $this->_formula{$index};
193
				}
194
				++$index;
195
				continue;
196
			}
197
 
198
			// single-quoted strings (links)
199
			// embeds are double
200
			// end does not mark a token
201
			if ($inPath) {
202
				if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
203
					if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) {
204
						$value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE;
205
						++$index;
206
					} else {
207
						$inPath = false;
208
					}
209
				} else {
210
					$value .= $this->_formula{$index};
211
				}
212
				++$index;
213
				continue;
214
			}
215
 
216
			// bracked strings (R1C1 range index or linked workbook name)
217
			// no embeds (changed to "()" by Excel)
218
			// end does not mark a token
219
			if ($inRange) {
220
				if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) {
221
					$inRange = false;
222
				}
223
				$value .= $this->_formula{$index};
224
				++$index;
225
				continue;
226
			}
227
 
228
			// error values
229
			// end marks a token, determined from absolute list of values
230
			if ($inError) {
231
				$value .= $this->_formula{$index};
232
				++$index;
233
				if (in_array($value, $ERRORS)) {
234
					$inError = false;
235
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR);
236
					$value = "";
237
				}
238
				continue;
239
			}
240
 
241
			// scientific notation check
242
			if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->_formula{$index}) !== false) {
243
				if (strlen($value) > 1) {
244
					if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->_formula{$index}) != 0) {
245
						$value .= $this->_formula{$index};
246
						++$index;
247
						continue;
248
					}
249
				}
250
			}
251
 
252
			// independent character evaluation (order not important)
253
 
254
			// establish state-dependent character evaluations
255
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
256
				if (strlen($value > 0)) {  // unexpected
257
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
258
					$value = "";
259
				}
260
				$inString = true;
261
				++$index;
262
				continue;
263
 			}
264
 
265
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
266
				if (strlen($value) > 0) { // unexpected
267
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
268
					$value = "";
269
				}
270
				$inPath = true;
271
				++$index;
272
				continue;
273
			}
274
 
275
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) {
276
				$inRange = true;
277
				$value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN;
278
				++$index;
279
				continue;
280
			}
281
 
282
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::ERROR_START) {
283
				if (strlen($value) > 0) { // unexpected
284
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
285
					$value = "";
286
				}
287
				$inError = true;
288
				$value .= PHPExcel_Calculation_FormulaParser::ERROR_START;
289
				++$index;
290
				continue;
291
			}
292
 
293
			// mark start and end of arrays and array rows
294
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) {
295
				if (strlen($value) > 0) { // unexpected
296
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
297
					$value = "";
298
				}
299
 
300
				$tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
301
				$tokens1[] = $tmp;
302
				$stack[] = clone $tmp;
303
 
304
				$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
305
				$tokens1[] = $tmp;
306
				$stack[] = clone $tmp;
307
 
308
				++$index;
309
				continue;
310
			}
311
 
312
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::SEMICOLON) {
313
				if (strlen($value) > 0) {
314
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
315
					$value = "";
316
				}
317
 
318
				$tmp = array_pop($stack);
319
				$tmp->setValue("");
320
				$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
321
				$tokens1[] = $tmp;
322
 
323
				$tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
324
				$tokens1[] = $tmp;
325
 
326
				$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
327
				$tokens1[] = $tmp;
328
				$stack[] = clone $tmp;
329
 
330
				++$index;
331
				continue;
332
			}
333
 
334
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) {
335
				if (strlen($value) > 0) {
336
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
337
					$value = "";
338
				}
339
 
340
				$tmp = array_pop($stack);
341
				$tmp->setValue("");
342
				$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
343
				$tokens1[] = $tmp;
344
 
345
				$tmp = array_pop($stack);
346
				$tmp->setValue("");
347
				$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
348
				$tokens1[] = $tmp;
349
 
350
				++$index;
351
				continue;
352
			}
353
 
354
			// trim white-space
355
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) {
356
				if (strlen($value) > 0) {
357
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
358
					$value = "";
359
				}
360
				$tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE);
361
				++$index;
362
				while (($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) {
363
					++$index;
364
				}
365
				continue;
366
			}
367
 
368
			// multi-character comparators
369
			if (($index + 2) <= $formulaLength) {
370
				if (in_array(substr($this->_formula, $index, 2), $COMPARATORS_MULTI)) {
371
					if (strlen($value) > 0) {
372
						$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
373
						$value = "";
374
					}
375
					$tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->_formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
376
					$index += 2;
377
					continue;
378
				}
379
			}
380
 
381
			// standard infix operators
382
			if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->_formula{$index}) !== false) {
383
				if (strlen($value) > 0) {
384
					$tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
385
					$value = "";
386
				}
387
				$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX);
388
				++$index;
389
				continue;
390
			}
391
 
392
			// standard postfix operators (only one)
393
			if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->_formula{$index}) !== false) {
394
				if (strlen($value) > 0) {
395
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
396
					$value = "";
397
				}
398
				$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX);
399
				++$index;
400
				continue;
401
			}
402
 
403
			// start subexpression or function
404
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) {
405
				if (strlen($value) > 0) {
406
					$tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
407
					$tokens1[] = $tmp;
408
					$stack[] = clone $tmp;
409
					$value = "";
410
				} else {
411
					$tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
412
					$tokens1[] = $tmp;
413
					$stack[] = clone $tmp;
414
				}
415
				++$index;
416
				continue;
417
			}
418
 
419
			// function, subexpression, or array parameters, or operand unions
420
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::COMMA) {
421
				if (strlen($value) > 0) {
422
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
423
					$value = "";
424
				}
425
 
426
				$tmp = array_pop($stack);
427
				$tmp->setValue("");
428
				$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
429
				$stack[] = $tmp;
430
 
431
				if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
432
					$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION);
433
				} else {
434
					$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
435
				}
436
				++$index;
437
				continue;
438
			}
439
 
440
			// stop subexpression
441
			if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) {
442
				if (strlen($value) > 0) {
443
					$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
444
					$value = "";
445
				}
446
 
447
				$tmp = array_pop($stack);
448
				$tmp->setValue("");
449
				$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
450
				$tokens1[] = $tmp;
451
 
452
				++$index;
453
				continue;
454
			}
455
 
456
        	// token accumulation
457
			$value .= $this->_formula{$index};
458
			++$index;
459
		}
460
 
461
		// dump remaining accumulation
462
		if (strlen($value) > 0) {
463
			$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
464
		}
465
 
466
		// move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections
467
		$tokenCount = count($tokens1);
468
		for ($i = 0; $i < $tokenCount; ++$i) {
469
			$token = $tokens1[$i];
470
			if (isset($tokens1[$i - 1])) {
471
				$previousToken = $tokens1[$i - 1];
472
			} else {
473
				$previousToken = null;
474
			}
475
			if (isset($tokens1[$i + 1])) {
476
				$nextToken = $tokens1[$i + 1];
477
			} else {
478
				$nextToken = null;
479
			}
480
 
481
			if (is_null($token)) {
482
				continue;
483
			}
484
 
485
			if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) {
486
				$tokens2[] = $token;
487
				continue;
488
			}
489
 
490
			if (is_null($previousToken)) {
491
				continue;
492
			}
493
 
494
			if (! (
495
					(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
496
					(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
497
					($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
498
				  ) ) {
499
				continue;
500
			}
501
 
502
			if (is_null($nextToken)) {
503
				continue;
504
			}
505
 
506
			if (! (
507
					(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
508
					(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
509
					($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
510
				  ) ) {
511
				continue;
512
			}
513
 
514
			$tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION);
515
		}
516
 
517
		// move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators
518
		// to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names
519
		$this->_tokens = array();
520
 
521
		$tokenCount = count($tokens2);
522
		for ($i = 0; $i < $tokenCount; ++$i) {
523
			$token = $tokens2[$i];
524
			if (isset($tokens2[$i - 1])) {
525
				$previousToken = $tokens2[$i - 1];
526
			} else {
527
				$previousToken = null;
528
			}
529
			if (isset($tokens2[$i + 1])) {
530
				$nextToken = $tokens2[$i + 1];
531
			} else {
532
				$nextToken = null;
533
			}
534
 
535
			if (is_null($token)) {
536
				continue;
537
			}
538
 
539
			if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") {
540
				if ($i == 0) {
541
					$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
542
				} else if (
543
							(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
544
							(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
545
							($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
546
							($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
547
						) {
548
					$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
549
				} else {
550
					$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
551
				}
552
 
553
				$this->_tokens[] = $token;
554
				continue;
555
			}
556
 
557
			if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") {
558
				if ($i == 0) {
559
					continue;
560
				} else if (
561
							(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
562
							(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
563
							($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
564
							($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
565
						) {
566
					$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
567
				} else {
568
					continue;
569
				}
570
 
571
				$this->_tokens[] = $token;
572
				continue;
573
			}
574
 
575
			if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
576
				if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) {
577
					$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
578
				} else if ($token->getValue() == "&") {
579
					$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION);
580
				} else {
581
					$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
582
				}
583
 
584
				$this->_tokens[] = $token;
585
				continue;
586
			}
587
 
588
			if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
589
				if (!is_numeric($token->getValue())) {
590
					if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) {
591
						$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
592
					} else {
593
						$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE);
594
					}
595
				} else {
596
					$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER);
597
				}
598
 
599
				$this->_tokens[] = $token;
600
				continue;
601
			}
602
 
603
			if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
604
				if (strlen($token->getValue() > 0)) {
605
					if (substr($token->getValue(), 0, 1) == "@") {
606
						$token->setValue(substr($token->getValue(), 1));
607
					}
608
				}
609
			}
610
 
611
        	$this->_tokens[] = $token;
612
		}
613
    }
614
}