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.

References _parseToTokens().

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  }
+ 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.

References array, 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().

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 
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")) {
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  }
Create styles array
The data for the language used.
+ 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.

116  {
117  return $this->_formula;
118  }

◆ 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.

149  {
150  return $this->_tokens;
151  }

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: