94 var
$v = array(
'e'=>2.71,
'pi'=>3.14);
96 var
$vb = array(
'e',
'pi');
98 'sin',
'sinh',
'arcsin',
'asin',
'arcsinh',
'asinh',
99 'cos',
'cosh',
'arccos',
'acos',
'arccosh',
'acosh',
100 'tan',
'tanh',
'arctan',
'atan',
'arctanh',
'atanh',
101 'sqrt',
'abs',
'ln',
'log');
105 $this->
v[
'pi'] = pi();
106 $this->
v[
'exp'] = exp(1);
108 $this->
v[
'e'] = exp(1);
119 $expr = preg_replace_callback(
120 "/(\\d{0,1})e(-{0,1}\\d+)/is",
122 return $hit[1].((strlen($hit[1])) ?
'*' :
'').
'10^('.$hit[2].
')';
127 $this->last_error = null;
129 if (substr($expr, -1, 1) ==
';') $expr = substr($expr, 0, strlen($expr)-1);
132 if (preg_match(
'/^\s*([a-z]\w*)\s*=\s*(.+)$/', $expr, $matches)) {
133 if (in_array($matches[1], $this->vb)) {
134 return $this->
trigger(
"cannot assign to constant '$matches[1]'");
136 if (($tmp = $this->
pfx($this->
nfx($matches[2]))) ===
false)
return false;
137 $this->
v[$matches[1]] = $tmp;
138 return $this->
v[$matches[1]];
141 } elseif (preg_match(
'/^\s*([a-z]\w*)\s*\(\s*([a-z]\w*(?:\s*,\s*[a-z]\w*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches)) {
143 if (in_array($matches[1], $this->fb)) {
144 return $this->
trigger(
"cannot redefine built-in function '$matches[1]()'");
146 $args = explode(
",", preg_replace(
"/\s+/",
"", $matches[2]));
147 if (($stack = $this->
nfx($matches[3])) ===
false)
return false;
148 for ($i = 0; $i<count($stack); $i++) {
150 if (preg_match(
'/^[a-z]\w*$/', $token) and !in_array($token, $args)) {
151 if (array_key_exists($token, $this->
v)) {
152 $stack[$i] = $this->
v[$token];
154 return $this->
trigger(
"undefined variable '$token' in function definition");
158 $this->f[$fnn] = array(
'args'=>$args,
'func'=>$stack);
162 return $this->
pfx($this->
nfx($expr));
168 unset($output[
'pi']);
175 foreach ($this->f as $fnn=>$dat)
176 $output[] = $fnn .
'(' . implode(
',', $dat[
'args']) .
')';
188 $expr = trim(strtolower($expr));
190 $ops = array(
'+',
'-',
'*',
'/',
'^',
'_');
191 $ops_r = array(
'+'=>0,
'-'=>0,
'*'=>0,
'/'=>0,
'^'=>1);
192 $ops_p = array(
'+'=>0,
'-'=>0,
'*'=>1,
'/'=>1,
'_'=>1,
'^'=>2);
194 $expecting_op =
false;
197 if (preg_match(
"/[^\w\s+*^\/()\.,-]/", $expr, $matches)) {
198 return $this->
trigger(
"illegal character '{$matches[0]}'");
202 $op = substr($expr, $index, 1);
204 $ex = preg_match(
'/^([01]+[bB]|[\da-fA-F]+[hH]|[a-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr($expr, $index), $match);
206 if ($op ==
'-' and !$expecting_op) {
209 } elseif ($op ==
'_') {
210 return $this->
trigger(
"illegal character '_'");
212 } elseif ((in_array($op, $ops) or $ex) and $expecting_op) {
217 while($stack->count > 0 and ($o2 = $stack->last()) and in_array($o2, $ops) and ($ops_r[$op] ? $ops_p[$op] < $ops_p[$o2] : $ops_p[$op] <= $ops_p[$o2])) {
218 $output[] = $stack->pop();
223 $expecting_op =
false;
225 } elseif ($op ==
')' and $expecting_op) {
226 while (($o2 = $stack->pop()) !=
'(') {
227 if (is_null($o2))
return $this->
trigger(
"unexpected ')'");
228 else $output[] = $o2;
230 if (preg_match(
"/^([a-z]\w*)\($/", $stack->last(2), $matches)) {
232 $arg_count = $stack->pop();
233 $output[] = $stack->pop();
234 if (in_array($fnn, $this->fb)) {
236 return $this->
trigger(
"too many arguments ($arg_count given, 1 expected)");
237 } elseif (array_key_exists($fnn, $this->f)) {
238 if ($arg_count != count($this->f[$fnn][
'args']))
239 return $this->
trigger(
"wrong number of arguments ($arg_count given, " . count($this->f[$fnn][
'args']) .
" expected)");
241 return $this->
trigger(
"internal error");
246 } elseif ($op ==
',' and $expecting_op) {
247 while (($o2 = $stack->pop()) !=
'(') {
248 if (is_null($o2))
return $this->
trigger(
"unexpected ','");
249 else $output[] = $o2;
252 if (!preg_match(
"/^([a-z]\w*)\($/", $stack->last(2), $matches))
253 return $this->
trigger(
"unexpected ','");
254 $stack->push($stack->pop()+1);
257 $expecting_op =
false;
259 } elseif ($op ==
'(' and !$expecting_op) {
264 } elseif ($ex and !$expecting_op) {
265 $expecting_op =
true;
267 if (preg_match(
"/^([a-z]\w*)\($/", $val, $matches)) {
268 if (in_array($matches[1], $this->fb) or array_key_exists($matches[1], $this->f)) {
272 $expecting_op =
false;
280 $index += strlen($val);
282 } elseif ($op ==
')') {
283 return $this->
trigger(
"unexpected ')'");
284 } elseif (in_array($op, $ops) and !$expecting_op) {
285 return $this->
trigger(
"unexpected operator '$op'");
287 return $this->
trigger(
"an unexpected error occured");
289 if ($index == strlen($expr)) {
290 if (in_array($op, $ops)) {
291 return $this->
trigger(
"operator '$op' lacks operand");
296 while (substr($expr, $index, 1) ==
' ') {
301 while (!is_null($op = $stack->pop())) {
302 if ($op ==
'(')
return $this->
trigger(
"expecting ')'");
309 function pfx($tokens, $vars = array()) {
311 if ($tokens ==
false)
return false;
315 foreach ($tokens as $token) {
317 if (in_array($token, array(
'+',
'-',
'*',
'/',
'^'))) {
318 if (is_null($op2 = $stack->pop()))
return $this->
trigger(
"internal error");
319 if (is_null($op1 = $stack->pop()))
return $this->
trigger(
"internal error");
320 include_once
"class.ilMath.php";
329 if ($op2 == 0)
return $this->
trigger(
"division by zero");
335 } elseif ($token ==
"_") {
336 $stack->push(-1*$stack->pop());
338 } elseif (preg_match(
"/^([a-z]\w*)\($/", $token, $matches)) {
340 if (in_array($fnn, $this->fb)) {
341 if (is_null($op1 = $stack->pop()))
return $this->
trigger(
"internal error");
342 $fnn = preg_replace(
"/^arc/",
"a", $fnn);
345 } elseif ($fnn ==
'ln') {
349 $stack->push($fnn($op1));
350 } elseif (array_key_exists($fnn, $this->f)) {
353 for ($i = count($this->f[$fnn][
'args'])-1; $i >= 0; $i--) {
354 if (is_null($args[$this->f[$fnn][
'args'][$i]] = $stack->pop()))
return $this->
trigger(
"internal error");
356 $stack->push($this->
pfx($this->f[$fnn][
'func'], $args));
360 if (is_numeric($token)) {
361 $stack->push($token);
362 } elseif (($hex=$this->
from_hexbin($token))!==FALSE) {
364 } elseif (array_key_exists($token, $this->
v)) {
365 $stack->push($this->
v[$token]);
366 } elseif (array_key_exists($token, $vars)) {
367 $stack->push($vars[$token]);
369 return $this->
trigger(
"undefined variable '$token'");
374 if ($stack->count != 1)
return $this->
trigger(
"internal error");
375 return $stack->pop();
380 $this->last_error = $msg;
381 if (!$this->suppress_errors) trigger_error($msg, E_USER_WARNING);
388 if (strtoupper(substr($token, -1, 1))==
'H')
return hexdec($token);
389 if (strtoupper(substr($token, -1, 1))==
'B')
return bindec($token);
397 var $stack = array();
401 $this->stack[$this->count] = $val;
406 if ($this->count > 0) {
408 return $this->stack[$this->count];
414 return $this->stack[$this->count-
$n];
static _div($left_operand, $right_operand, $scale=50)
static _pow($left_operand, $right_operand, $scale=50)
static _add($left_operand, $right_operand, $scale=50)
pfx($tokens, $vars=array())
static _mul($left_operand, $right_operand, $scale=50)
static _sub($left_operand, $right_operand, $scale=50)