ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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.

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

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 428 of file class.ilDclExpressionParser.php.

References $result.

Referenced by parseMath().

429  {
430  switch ($operator) {
431  case '+':
432  $result = $left + $right;
433  break;
434  case '-':
435  $result = $left - $right;
436  break;
437  case '*':
438  $result = $left * $right;
439  break;
440  case '/':
441  $result = ($right == 0) ? 0 : $left / $right;
442  break;
443  case '^':
444  $result = pow($left, $right);
445  break;
446  default:
447  throw new ilException("Unrecognized operator '$operator'");
448  }
449 
450  return $result;
451  }
$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 401 of file class.ilDclExpressionParser.php.

References $function.

Referenced by calculateFunctions().

402  {
403  switch ($function) {
404  case 'AVERAGE':
405  $count = count($args);
406 
407  return ($count) ? array_sum($args) / $count : 0;
408  case 'SUM':
409  return array_sum($args);
410  case 'MIN':
411  return min($args);
412  case 'MAX':
413  return max($args);
414  default:
415  throw new ilException("Unrecognized function '$function'");
416  }
417  }
$function
Definition: cas.php:28
+ 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 193 of file class.ilDclExpressionParser.php.

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

Referenced by parse().

194  {
195  if (isset(self::$cache_math_function_tokens[$this->field->getId()][$token])) {
196  $result = self::$cache_math_function_tokens[$this->field->getId()][$token];
197  if ($result === false) {
198  return $token;
199  }
200  } else {
201  $pattern = '#';
202  foreach (self::getFunctions() as $function) {
203  $pattern .= "($function)\\(([^)]*)\\)|";
204  }
205  if (!preg_match_all(rtrim($pattern, '|') . '#', $token, $result)) {
206  // No functions found inside token, just return token again
207  self::$cache_math_function_tokens[$this->field->getId()][$token] = false;
208 
209  return $token;
210  }
211  }
212  // Function found inside token, calculate!
213  foreach ($result[0] as $k => $to_replace) {
214  $function_args = $this->getFunctionArgs($k, $result);
215  $function = $function_args['function'];
216  $args = $this->substituteFieldValues($function_args['args']);
217  $token = str_replace($to_replace, $this->calculateFunction($function, $args), $token);
218  }
219 
220  return $token;
221  }
$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...
$function
Definition: cas.php:28
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 127 of file class.ilDclExpressionParser.php.

Referenced by parse().

128  {
129  if (abs($value) >= self::SCIENTIFIC_NOTATION_UPPER) {
130  return sprintf("%e", $value);
131  }
132  if (abs($value) <= self::SCIENTIFIC_NOTATION_LOWER && $value != 0) {
133  return sprintf("%e", $value);
134  }
135  if (is_float($value)) {
136  return $value;
137  }
138 
139  return $value;
140  }
+ 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 232 of file class.ilDclExpressionParser.php.

References $function, $i, $index, and array.

Referenced by calculateFunctions().

233  {
234  $return = array(
235  'function' => '',
236  'args' => array(),
237  );
238  for ($i = 1; $i < count($data); $i++) {
239  $_data = $data[$i];
240  if ($_data[$index]) {
241  $function = $_data[$index];
242  $args = explode(';', $data[$i + 1][$index]);
243  $return['function'] = $function;
244  $return['args'] = $args;
245  break;
246  }
247  }
248 
249  return $return;
250  }
$index
Definition: metadata.php:60
Create styles array
The data for the language used.
$function
Definition: cas.php:28
$i
Definition: disco.tpl.php:19
+ Here is the caller graph for this function:

◆ getFunctions()

static ilDclExpressionParser::getFunctions ( )
static
Returns
array

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

Referenced by ilDclFormulaFieldRepresentation\buildFieldCreationInput().

156  {
157  return self::$functions;
158  }
+ Here is the caller graph for this function:

◆ getOperators()

static ilDclExpressionParser::getOperators ( )
static
Returns
array

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

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

147  {
148  return self::$operators;
149  }
+ 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 168 of file class.ilDclExpressionParser.php.

References $functions, $operators, and $result.

Referenced by parse().

169  {
170  if (isset(self::$cache_math_tokens[$this->field->getId()][$token])) {
171  return self::$cache_math_tokens[$this->field->getId()][$token];
172  } else {
173  if (strpos($token, '"') === 0) {
174  return false;
175  }
176  $operators = array_keys(self::getOperators());
177  $functions = self::getFunctions();
178  $result = (bool) preg_match('#(\\' . implode("|\\", $operators) . '|' . implode('|', $functions) . ')#', $token);
179  self::$cache_math_tokens[$this->field->getId()][$token] = $result;
180 
181  return $result;
182  }
183  }
$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 84 of file class.ilDclExpressionParser.php.

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

85  {
86  if (isset(self::$cache_tokens[$this->field->getId()])) {
87  $tokens = self::$cache_tokens[$this->field->getId()];
88  } else {
89  $tokens = ilDclTokenizer::getTokens($this->expression);
90  self::$cache_tokens[$this->field->getId()] = $tokens;
91  }
92  // ilUtil::sendInfo( "<pre>" . print_r($tokens, 1) . "</pre>");
93  $parsed = '';
94  foreach ($tokens as $token) {
95  if (empty($token)) {
96  continue;
97  }
98  if ($this->isMathToken($token)) {
99  $token = $this->calculateFunctions($token);
100  $math_tokens = ilDclTokenizer::getMathTokens($token);
101  $value = $this->parseMath($this->substituteFieldValues($math_tokens));
102 
103  $value = $this->formatScientific($value);
104 
105  $parsed .= $value;
106  } else {
107  // Token is a string, either a field placeholder [[Field name]] or a string starting with "
108  if (strpos($token, '"') === 0) {
109  $parsed .= strip_tags(trim($token, '"'));
110  } elseif (strpos($token, '[[') === 0) {
111  $parsed .= trim(strip_tags($this->substituteFieldValue($token)));
112  } else {
113  throw new ilException("Unrecognized string token: '$token'");
114  }
115  }
116  }
117 
118  return $parsed;
119  }
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 320 of file class.ilDclExpressionParser.php.

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

Referenced by parse().

321  {
322  $operators = self::$operators;
323  $precedence = 0;
324  $stack = new ilDclStack();
325  $precedences = new ilDclStack();
326  $in_bracket = false;
327  foreach ($tokens as $token) {
328  if (empty($token) or is_null($token)) {
329  $token = 0;
330  }
331  if (is_numeric($token) or $token === '(') {
332  $stack->push($token);
333  if ($token === '(') {
334  $in_bracket = true;
335  }
336  } elseif (in_array($token, array_keys($operators))) {
337  $new_precedence = $operators[$token]['precedence'];
338  if ($new_precedence > $precedence || $in_bracket) {
339  // Precedence of operator is higher, push operator on stack
340  $stack->push($token);
341  $precedences->push($new_precedence);
342  $precedence = $new_precedence;
343  } else {
344  // Precedence is equal or lower, calculate result on stack
345  while ($new_precedence <= $precedence && $stack->count() > 1) {
346  $right = (float) $stack->pop();
347  $operator = $stack->pop();
348  $left = (float) $stack->pop();
349  $result = $this->calculate($operator, $left, $right);
350  $stack->push($result);
351  $precedence = $precedences->pop();
352  }
353  $stack->push($token);
354  $precedence = $new_precedence;
355  $precedences->push($new_precedence);
356  }
357  } elseif ($token === ')') {
358  // Need to calculate stack back to opening bracket
359  $_tokens = array();
360  $elem = $stack->pop();
361  while ($elem !== '(' && !$stack->isEmpty()) {
362  $_tokens[] = $elem;
363  $elem = $stack->pop();
364  }
365  // Get result within brackets recursive and push to stack
366  $stack->push($this->parseMath(array_reverse($_tokens)));
367  $in_bracket = false;
368  } else {
369  throw new ilException("Unrecognized token '$token'");
370  }
371  // $stack->debug();
372  }
373  // If one element is left on stack, we are done. Otherwise calculate
374  if ($stack->count() == 1) {
375  $result = $stack->pop();
376 
377  return (ctype_digit((string) $result)) ? $result : number_format($result, self::N_DECIMALS, '.', "'");
378  } else {
379  while ($stack->count() >= 2) {
380  $right = $stack->pop();
381  $operator = $stack->pop();
382  $left = $stack->count() ? $stack->pop() : 0;
383  $stack->push($this->calculate($operator, $left, $right));
384  }
385  $result = $stack->pop();
386 
387  return $result;
388  }
389  }
$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 260 of file class.ilDclExpressionParser.php.

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

Referenced by calculateFunctions(), and parse().

261  {
262  $replaced = array();
263  foreach ($tokens as $token) {
264  if (strpos($token, '[[') === 0) {
265  $replaced[] = $this->substituteFieldValue($token);
266  } else {
267  $replaced[] = $token;
268  }
269  }
270 
271  return $replaced;
272  }
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: