ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
ilDclExpressionParser Class Reference

Class ilDclExpressionParser. More...

+ Collaboration diagram for ilDclExpressionParser:

Public Member Functions

 __construct ($expression, ilDclBaseRecordModel $record, ilDclBaseFieldModel $field)
 
 parse ()
 Parse expression and return result. More...
 

Static Public Member Functions

static getOperators ()
 
static getFunctions ()
 

Data Fields

const N_DECIMALS = 1
 
const SCIENTIFIC_NOTATION_UPPER = 1000000000000
 
const SCIENTIFIC_NOTATION_LOWER = 0.000000001
 

Protected Member Functions

 formatScientific ($value)
 
 isMathToken ($token)
 Check if a given token is a math expression. More...
 
 calculateFunctions ($token)
 Execute any math functions inside a token. More...
 
 getFunctionArgs ($index, array $data)
 Helper method to return the function and its arguments from a preg_replace_all $result array. More...
 
 substituteFieldValues (array $tokens)
 Given an array of tokens, replace each token that is a placeholder (e.g. More...
 
 parseMath (array $tokens)
 Parse a math expression. More...
 
 calculateFunction ($function, array $args=array())
 Calculate a function with its arguments. More...
 
 calculate ($operator, $left, $right)
 

Protected Attributes

 $record
 
 $field
 
 $expression
 

Static Protected Attributes

static $operators
 
static $cache_tokens = array()
 
static $cache_fields = array()
 
static $cache_math_tokens = array()
 
static $cache_math_function_tokens = array()
 
static $functions
 

Detailed Description

Constructor & Destructor Documentation

◆ __construct()

ilDclExpressionParser::__construct (   $expression,
ilDclBaseRecordModel  $record,
ilDclBaseFieldModel  $field 
)
Parameters
string$expression
ilDclBaseRecordModel$record
ilDclBaseFieldModel$field

Definition at line 68 of file class.ilDclExpressionParser.php.

References $expression, $field, and $record.

68  {
69  $this->expression = $expression;
70  $this->record = $record;
71  $this->field = $field;
72  }

Member Function Documentation

◆ calculate()

ilDclExpressionParser::calculate (   $operator,
  $left,
  $right 
)
protected
Parameters
string$operator
float$left
float$right
Returns
float|number
Exceptions
ilException

Definition at line 417 of file class.ilDclExpressionParser.php.

References $result.

Referenced by parseMath().

417  {
418  switch ($operator) {
419  case '+':
420  $result = $left + $right;
421  break;
422  case '-':
423  $result = $left - $right;
424  break;
425  case '*':
426  $result = $left * $right;
427  break;
428  case '/':
429  $result = ($right == 0) ? 0 : $left / $right;
430  break;
431  case '^':
432  $result = pow($left, $right);
433  break;
434  default:
435  throw new ilException("Unrecognized operator '$operator'");
436  }
437 
438  return $result;
439  }
Base class for ILIAS Exception handling.
$result
+ Here is the caller graph for this function:

◆ calculateFunction()

ilDclExpressionParser::calculateFunction (   $function,
array  $args = array() 
)
protected

Calculate a function with its arguments.

Parameters
$functionFunction name to calculate
array$argsArguments of function
Returns
float|int|number
Exceptions
ilException

Definition at line 391 of file class.ilDclExpressionParser.php.

Referenced by calculateFunctions().

391  {
392  switch ($function) {
393  case 'AVERAGE':
394  $count = count($args);
395 
396  return ($count) ? array_sum($args) / $count : 0;
397  case 'SUM':
398  return array_sum($args);
399  case 'MIN':
400  return min($args);
401  case 'MAX':
402  return max($args);
403  default:
404  throw new ilException("Unrecognized function '$function'");
405  }
406  }
Base class for ILIAS Exception handling.
+ Here is the caller graph for this function:

◆ calculateFunctions()

ilDclExpressionParser::calculateFunctions (   $token)
protected

Execute any math functions inside a token.

Parameters
string$token
Returns
string

Definition at line 187 of file class.ilDclExpressionParser.php.

References $result, calculateFunction(), getFunctionArgs(), and substituteFieldValues().

Referenced by parse().

187  {
188  if (isset(self::$cache_math_function_tokens[$this->field->getId()][$token])) {
189  $result = self::$cache_math_function_tokens[$this->field->getId()][$token];
190  if ($result === false) {
191  return $token;
192  }
193  } else {
194  $pattern = '#';
195  foreach (self::getFunctions() as $function) {
196  $pattern .= "($function)\\(([^)]*)\\)|";
197  }
198  if (!preg_match_all(rtrim($pattern, '|') . '#', $token, $result)) {
199  // No functions found inside token, just return token again
200  self::$cache_math_function_tokens[$this->field->getId()][$token] = false;
201 
202  return $token;
203  }
204  }
205  // Function found inside token, calculate!
206  foreach ($result[0] as $k => $to_replace) {
207  $function_args = $this->getFunctionArgs($k, $result);
208  $function = $function_args['function'];
209  $args = $this->substituteFieldValues($function_args['args']);
210  $token = str_replace($to_replace, $this->calculateFunction($function, $args), $token);
211  }
212 
213  return $token;
214  }
$result
substituteFieldValues(array $tokens)
Given an array of tokens, replace each token that is a placeholder (e.g.
getFunctionArgs($index, array $data)
Helper method to return the function and its arguments from a preg_replace_all $result array...
calculateFunction($function, array $args=array())
Calculate a function with its arguments.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ formatScientific()

ilDclExpressionParser::formatScientific (   $value)
protected
Parameters
$value
Returns
string

Definition at line 125 of file class.ilDclExpressionParser.php.

Referenced by parse().

125  {
126  if (abs($value) >= self::SCIENTIFIC_NOTATION_UPPER) {
127  return sprintf("%e", $value);
128  }
129  if (abs($value) <= self::SCIENTIFIC_NOTATION_LOWER && $value != 0 ) {
130  return sprintf("%e", $value);
131  }
132  if (is_float($value)) {
133  return $value;
134  }
135 
136  return $value;
137  }
+ Here is the caller graph for this function:

◆ getFunctionArgs()

ilDclExpressionParser::getFunctionArgs (   $index,
array  $data 
)
protected

Helper method to return the function and its arguments from a preg_replace_all $result array.

Parameters
$index
array$data
Returns
array

Definition at line 225 of file class.ilDclExpressionParser.php.

References array.

Referenced by calculateFunctions().

225  {
226  $return = array(
227  'function' => '',
228  'args' => array(),
229  );
230  for ($i = 1; $i < count($data); $i ++) {
231  $_data = $data[$i];
232  if ($_data[$index]) {
233  $function = $_data[$index];
234  $args = explode(';', $data[$i + 1][$index]);
235  $return['function'] = $function;
236  $return['args'] = $args;
237  break;
238  }
239  }
240 
241  return $return;
242  }
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ getFunctions()

static ilDclExpressionParser::getFunctions ( )
static
Returns
array

Definition at line 151 of file class.ilDclExpressionParser.php.

Referenced by ilDclFormulaFieldRepresentation\buildFieldCreationInput().

151  {
152  return self::$functions;
153  }
+ Here is the caller graph for this function:

◆ getOperators()

static ilDclExpressionParser::getOperators ( )
static
Returns
array

Definition at line 143 of file class.ilDclExpressionParser.php.

Referenced by ilDclFormulaFieldRepresentation\buildFieldCreationInput(), and ilDclTokenizer\getMathTokens().

143  {
144  return self::$operators;
145  }
+ Here is the caller graph for this function:

◆ isMathToken()

ilDclExpressionParser::isMathToken (   $token)
protected

Check if a given token is a math expression.

Parameters
string$token
Returns
bool

Definition at line 163 of file class.ilDclExpressionParser.php.

References $functions, $operators, and $result.

Referenced by parse().

163  {
164  if (isset(self::$cache_math_tokens[$this->field->getId()][$token])) {
165  return self::$cache_math_tokens[$this->field->getId()][$token];
166  } else {
167  if (strpos($token, '"') === 0) {
168  return false;
169  }
170  $operators = array_keys(self::getOperators());
171  $functions = self::getFunctions();
172  $result = (bool)preg_match('#(\\' . implode("|\\", $operators) . '|' . implode('|', $functions) . ')#', $token);
173  self::$cache_math_tokens[$this->field->getId()][$token] = $result;
174 
175  return $result;
176  }
177  }
$result
+ Here is the caller graph for this function:

◆ parse()

ilDclExpressionParser::parse ( )

Parse expression and return result.

This method loops the tokens and checks if Token is of type string or math. Concatenates results to produce resulting string of parsed expression.

Exceptions
ilException
Returns
string

Definition at line 83 of file class.ilDclExpressionParser.php.

References calculateFunctions(), formatScientific(), ilDclTokenizer\getMathTokens(), ilDclTokenizer\getTokens(), isMathToken(), parseMath(), and substituteFieldValues().

83  {
84  if (isset(self::$cache_tokens[$this->field->getId()])) {
85  $tokens = self::$cache_tokens[$this->field->getId()];
86  } else {
87  $tokens = ilDclTokenizer::getTokens($this->expression);
88  self::$cache_tokens[$this->field->getId()] = $tokens;
89  }
90  // ilUtil::sendInfo( "<pre>" . print_r($tokens, 1) . "</pre>");
91  $parsed = '';
92  foreach ($tokens as $token) {
93  if (empty($token)) {
94  continue;
95  }
96  if ($this->isMathToken($token)) {
97  $token = $this->calculateFunctions($token);
98  $math_tokens = ilDclTokenizer::getMathTokens($token);
99  $value = $this->parseMath($this->substituteFieldValues($math_tokens));
100 
101  $value = $this->formatScientific($value);
102 
103  $parsed .= $value;
104  } else {
105  // Token is a string, either a field placeholder [[Field name]] or a string starting with "
106  if (strpos($token, '"') === 0) {
107  $parsed .= strip_tags(trim($token, '"'));
108  } elseif (strpos($token, '[[') === 0) {
109  $parsed .= trim(strip_tags($this->substituteFieldValue($token)));
110  } else {
111  throw new ilException("Unrecognized string token: '$token'");
112  }
113  }
114  }
115 
116  return $parsed;
117  }
Base class for ILIAS Exception handling.
substituteFieldValues(array $tokens)
Given an array of tokens, replace each token that is a placeholder (e.g.
parseMath(array $tokens)
Parse a math expression.
isMathToken($token)
Check if a given token is a math expression.
calculateFunctions($token)
Execute any math functions inside a token.
static getTokens($expression)
Split expression by & (ignore escaped &-symbols with backslash)
static getMathTokens($math_expression)
Generate tokens for a math expression.
+ Here is the call graph for this function:

◆ parseMath()

ilDclExpressionParser::parseMath ( array  $tokens)
protected

Parse a math expression.

Parameters
array$tokens
Returns
null
Exceptions
Exception

Definition at line 310 of file class.ilDclExpressionParser.php.

References $operators, $result, array, and calculate().

Referenced by parse().

310  {
311  $operators = self::$operators;
312  $precedence = 0;
313  $stack = new ilDclStack();
314  $precedences = new ilDclStack();
315  $in_bracket = false;
316  foreach ($tokens as $token) {
317  if (empty($token) OR is_null($token)) {
318  $token = 0;
319  }
320  if (is_numeric($token) OR $token === '(') {
321  $stack->push($token);
322  if ($token === '(') {
323  $in_bracket = true;
324  }
325  } elseif (in_array($token, array_keys($operators))) {
326  $new_precedence = $operators[$token]['precedence'];
327  if ($new_precedence > $precedence || $in_bracket) {
328  // Precedence of operator is higher, push operator on stack
329  $stack->push($token);
330  $precedences->push($new_precedence);
331  $precedence = $new_precedence;
332  } else {
333  // Precedence is equal or lower, calculate result on stack
334  while ($new_precedence <= $precedence && $stack->count() > 1) {
335  $right = (float)$stack->pop();
336  $operator = $stack->pop();
337  $left = (float)$stack->pop();
338  $result = $this->calculate($operator, $left, $right);
339  $stack->push($result);
340  $precedence = $precedences->pop();
341  }
342  $stack->push($token);
343  $precedence = $new_precedence;
344  $precedences->push($new_precedence);
345  }
346  } elseif ($token === ')') {
347  // Need to calculate stack back to opening bracket
348  $_tokens = array();
349  $elem = $stack->pop();
350  while ($elem !== '(' && !$stack->isEmpty()) {
351  $_tokens[] = $elem;
352  $elem = $stack->pop();
353  }
354  // Get result within brackets recursive and push to stack
355  $stack->push($this->parseMath(array_reverse($_tokens)));
356  $in_bracket = false;
357  } else {
358  throw new ilException("Unrecognized token '$token'");
359  }
360  // $stack->debug();
361  }
362  // If one element is left on stack, we are done. Otherwise calculate
363  if ($stack->count() == 1) {
364  $result = $stack->pop();
365 
366  return (ctype_digit((string)$result)) ? $result : number_format($result, self::N_DECIMALS, '.', "'");
367  } else {
368 
369  while ($stack->count() >= 2) {
370  $right = $stack->pop();
371  $operator = $stack->pop();
372  $left = $stack->count() ? $stack->pop() : 0;
373  $stack->push($this->calculate($operator, $left, $right));
374  }
375  $result = $stack->pop();
376 
377  return $result;
378  }
379  }
Base class for ILIAS Exception handling.
$result
calculate($operator, $left, $right)
Class ilDclStack.
parseMath(array $tokens)
Parse a math expression.
Create styles array
The data for the language used.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ substituteFieldValues()

ilDclExpressionParser::substituteFieldValues ( array  $tokens)
protected

Given an array of tokens, replace each token that is a placeholder (e.g.

[[Field name]]) with it's value

Parameters
array$tokens
Returns
array

Definition at line 252 of file class.ilDclExpressionParser.php.

References $DIC, $field, $lng, array, and ilDclCache\getTableCache().

Referenced by calculateFunctions(), and parse().

252  {
253  $replaced = array();
254  foreach ($tokens as $token) {
255  if (strpos($token, '[[') === 0) {
256  $replaced[] = $this->substituteFieldValue($token);
257  } else {
258  $replaced[] = $token;
259  }
260  }
261 
262  return $replaced;
263  }
Create styles array
The data for the language used.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $cache_fields

ilDclExpressionParser::$cache_fields = array()
staticprotected

Definition at line 43 of file class.ilDclExpressionParser.php.

◆ $cache_math_function_tokens

ilDclExpressionParser::$cache_math_function_tokens = array()
staticprotected

Definition at line 51 of file class.ilDclExpressionParser.php.

◆ $cache_math_tokens

ilDclExpressionParser::$cache_math_tokens = array()
staticprotected

Definition at line 47 of file class.ilDclExpressionParser.php.

◆ $cache_tokens

ilDclExpressionParser::$cache_tokens = array()
staticprotected

Definition at line 39 of file class.ilDclExpressionParser.php.

◆ $expression

ilDclExpressionParser::$expression
protected

Definition at line 25 of file class.ilDclExpressionParser.php.

Referenced by __construct().

◆ $field

ilDclExpressionParser::$field
protected

Definition at line 21 of file class.ilDclExpressionParser.php.

Referenced by __construct(), and substituteFieldValues().

◆ $functions

ilDclExpressionParser::$functions
staticprotected
Initial value:
'SUM',
'AVERAGE',
'MIN',
'MAX',
)

Definition at line 55 of file class.ilDclExpressionParser.php.

Referenced by isMathToken().

◆ $operators

ilDclExpressionParser::$operators
staticprotected
Initial value:
'+' => array( 'precedence' => 1 ),
'-' => array( 'precedence' => 1 ),
'*' => array( 'precedence' => 2 ),
'/' => array( 'precedence' => 2 ),
'^' => array( 'precedence' => 3 ),
)

Definition at line 29 of file class.ilDclExpressionParser.php.

Referenced by isMathToken(), and parseMath().

◆ $record

ilDclExpressionParser::$record
protected

Definition at line 17 of file class.ilDclExpressionParser.php.

Referenced by __construct().

◆ N_DECIMALS

const ilDclExpressionParser::N_DECIMALS = 1

Definition at line 11 of file class.ilDclExpressionParser.php.

◆ SCIENTIFIC_NOTATION_LOWER

const ilDclExpressionParser::SCIENTIFIC_NOTATION_LOWER = 0.000000001

Definition at line 13 of file class.ilDclExpressionParser.php.

◆ SCIENTIFIC_NOTATION_UPPER

const ilDclExpressionParser::SCIENTIFIC_NOTATION_UPPER = 1000000000000

Definition at line 12 of file class.ilDclExpressionParser.php.


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