ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
PHPExcel_Calculation_FormulaParser Class Reference
+ Collaboration diagram for PHPExcel_Calculation_FormulaParser:

Public Member Functions

 __construct ($pFormula='')
 Create a new PHPExcel_Calculation_FormulaParser. More...
 
 getFormula ()
 Get Formula. More...
 
 getToken ($pId=0)
 Get Token. More...
 
 getTokenCount ()
 Get Token count. More...
 
 getTokens ()
 Get Tokens. More...
 

Data Fields

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 = "%"
 

Private Member Functions

 _parseToTokens ()
 Parse to tokens. More...
 

Private Attributes

 $_formula
 
 $_tokens = array()
 

Detailed Description

Definition at line 59 of file FormulaParser.php.

Constructor & Destructor Documentation

◆ __construct()

PHPExcel_Calculation_FormulaParser::__construct (   $pFormula = '')

Create a new PHPExcel_Calculation_FormulaParser.

Parameters
string$pFormulaFormula to parse
Exceptions
PHPExcel_Calculation_Exception

Definition at line 98 of file FormulaParser.php.

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 }

References _parseToTokens().

+ Here is the call graph for this function:

Member Function Documentation

◆ _parseToTokens()

PHPExcel_Calculation_FormulaParser::_parseToTokens ( )
private

Parse to tokens.

Definition at line 156 of file FormulaParser.php.

156 {
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)) {
185 ++$index;
186 } else {
187 $inString = false;
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)) {
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;
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
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
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;
278 ++$index;
279 continue;
280 }
281
282 if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::ERROR_START) {
283 if (strlen($value) > 0) { // unexpected
285 $value = "";
286 }
287 $inError = true;
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
297 $value = "";
298 }
299
301 $tokens1[] = $tmp;
302 $stack[] = clone $tmp;
303
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) {
315 $value = "";
316 }
317
318 $tmp = array_pop($stack);
319 $tmp->setValue("");
321 $tokens1[] = $tmp;
322
324 $tokens1[] = $tmp;
325
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) {
337 $value = "";
338 }
339
340 $tmp = array_pop($stack);
341 $tmp->setValue("");
343 $tokens1[] = $tmp;
344
345 $tmp = array_pop($stack);
346 $tmp->setValue("");
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) {
358 $value = "";
359 }
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) {
373 $value = "";
374 }
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) {
385 $value = "";
386 }
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) {
396 $value = "";
397 }
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) {
407 $tokens1[] = $tmp;
408 $stack[] = clone $tmp;
409 $value = "";
410 } else {
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) {
423 $value = "";
424 }
425
426 $tmp = array_pop($stack);
427 $tmp->setValue("");
429 $stack[] = $tmp;
430
431 if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
433 } else {
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) {
444 $value = "";
445 }
446
447 $tmp = array_pop($stack);
448 $tmp->setValue("");
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) {
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
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) {
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 ) {
549 } else {
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 ) {
567 } else {
568 continue;
569 }
570
571 $this->_tokens[] = $token;
572 continue;
573 }
574
576 if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) {
578 } else if ($token->getValue() == "&") {
580 } else {
582 }
583
584 $this->_tokens[] = $token;
585 continue;
586 }
587
589 if (!is_numeric($token->getValue())) {
590 if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) {
592 } else {
594 }
595 } else {
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 }

References BRACE_CLOSE, BRACE_OPEN, BRACKET_CLOSE, BRACKET_OPEN, COMMA, ERROR_START, OPERATORS_INFIX, OPERATORS_POSTFIX, OPERATORS_SN, PAREN_CLOSE, PAREN_OPEN, QUOTE_DOUBLE, QUOTE_SINGLE, SEMICOLON, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_CONCATENATION, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_ERROR, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_INTERSECTION, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_LOGICAL, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_MATH, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_NOTHING, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_NUMBER, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_RANGE, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_START, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_STOP, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_TEXT, PHPExcel_Calculation_FormulaToken\TOKEN_SUBTYPE_UNION, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_ARGUMENT, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_OPERATORPOSTFIX, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_OPERATORPREFIX, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_UNKNOWN, PHPExcel_Calculation_FormulaToken\TOKEN_TYPE_WHITESPACE, and WHITESPACE.

Referenced by __construct().

+ Here is the caller graph for this function:

◆ getFormula()

PHPExcel_Calculation_FormulaParser::getFormula ( )

Get Formula.

Returns
string

Definition at line 116 of file FormulaParser.php.

References $_formula.

◆ getToken()

PHPExcel_Calculation_FormulaParser::getToken (   $pId = 0)

Get Token.

Parameters
int$pIdToken id
Returns
string
Exceptions
PHPExcel_Calculation_Exception

Definition at line 127 of file FormulaParser.php.

127 {
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 }

◆ getTokenCount()

PHPExcel_Calculation_FormulaParser::getTokenCount ( )

Get Token count.

Returns
string

Definition at line 140 of file FormulaParser.php.

140 {
141 return count($this->_tokens);
142 }

◆ getTokens()

PHPExcel_Calculation_FormulaParser::getTokens ( )

Get Tokens.

Returns
PHPExcel_Calculation_FormulaToken[]

Definition at line 149 of file FormulaParser.php.

References $_tokens.

Field Documentation

◆ $_formula

PHPExcel_Calculation_FormulaParser::$_formula
private

Definition at line 83 of file FormulaParser.php.

Referenced by getFormula().

◆ $_tokens

PHPExcel_Calculation_FormulaParser::$_tokens = array()
private

Definition at line 90 of file FormulaParser.php.

Referenced by getTokens().

◆ BRACE_CLOSE

const PHPExcel_Calculation_FormulaParser::BRACE_CLOSE = '}'

Definition at line 66 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ BRACE_OPEN

const PHPExcel_Calculation_FormulaParser::BRACE_OPEN = '{'

Definition at line 65 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ BRACKET_CLOSE

const PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE = ']'

Definition at line 63 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ BRACKET_OPEN

const PHPExcel_Calculation_FormulaParser::BRACKET_OPEN = '['

Definition at line 64 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ COMMA

const PHPExcel_Calculation_FormulaParser::COMMA = ','

Definition at line 71 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ ERROR_START

const PHPExcel_Calculation_FormulaParser::ERROR_START = '#'

Definition at line 72 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ OPERATORS_INFIX

const PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX = "+-*/^&=><"

Definition at line 75 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ OPERATORS_POSTFIX

const PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX = "%"

Definition at line 76 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ OPERATORS_SN

const PHPExcel_Calculation_FormulaParser::OPERATORS_SN = "+-"

Definition at line 74 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ PAREN_CLOSE

const PHPExcel_Calculation_FormulaParser::PAREN_CLOSE = ')'

Definition at line 68 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ PAREN_OPEN

const PHPExcel_Calculation_FormulaParser::PAREN_OPEN = '('

Definition at line 67 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ QUOTE_DOUBLE

const PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE = '"'

Definition at line 61 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ QUOTE_SINGLE

const PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE = '\''

Definition at line 62 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ SEMICOLON

const PHPExcel_Calculation_FormulaParser::SEMICOLON = ';'

Definition at line 69 of file FormulaParser.php.

Referenced by _parseToTokens().

◆ WHITESPACE

const PHPExcel_Calculation_FormulaParser::WHITESPACE = ' '

Definition at line 70 of file FormulaParser.php.

Referenced by _parseToTokens().


The documentation for this class was generated from the following file: