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.

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.

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
Base class for ILIAS Exception handling.

References $result.

Referenced by parseMath().

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

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

References $function.

Referenced by calculateFunctions().

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

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

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

Referenced by parse().

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

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 }
sprintf('%.4f', $callTime)

References sprintf.

Referenced by parse().

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

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 }
$i
Definition: disco.tpl.php:19
$index
Definition: metadata.php:60

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

Referenced by calculateFunctions().

+ Here is the caller graph for this function:

◆ getFunctions()

static ilDclExpressionParser::getFunctions ( )
static
Returns
array

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

156 {
157 return self::$functions;
158 }

References $functions.

Referenced by ilDclFormulaFieldRepresentation\buildFieldCreationInput(), and isMathToken().

+ Here is the caller graph for this function:

◆ getOperators()

static ilDclExpressionParser::getOperators ( )
static
Returns
array

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

147 {
148 return self::$operators;
149 }

References $operators.

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

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

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());
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 }

References $functions, $operators, $result, and getFunctions().

Referenced by parse().

+ Here is the call graph for this function:
+ 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.

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 }
calculateFunctions($token)
Execute any math functions inside a token.
parseMath(array $tokens)
Parse a math expression.
isMathToken($token)
Check if a given token is a math expression.
static getMathTokens($math_expression)
Generate tokens for a math expression.
static getTokens($expression)
Split expression by & (ignore escaped &-symbols with backslash)

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

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

321 {
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 }
calculate($operator, $left, $right)
Class ilDclStack.

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

Referenced by parse(), and parseMath().

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

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 }

Referenced by calculateFunctions(), and parse().

+ 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().

◆ $functions

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

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

Referenced by getFunctions(), and isMathToken().

◆ $operators

ilDclExpressionParser::$operators
staticprotected
Initial value:
= array(
'+' => 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 getOperators(), 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: