2017-05-01 20:05:36 +02:00

131 lines
3.7 KiB
PHP

<?php
/**
* Computes a mathematical equation
* <pre>
* * equation : the equation to compute, it can include normal variables with $foo or special math variables without the dollar sign
* * format : output format, see {@link http://php.net/sprintf} for details
* * assign : if set, the output is assigned into the given variable name instead of being output
* * rest : all math specific variables that you use must be defined, see the example
* </pre>
* Example :
*
* <code>
* {$c=2}
* {math "(a+b)*$c/4" a=3 b=5}
*
* output is : 4 ( = (3+5)*2/4)
* </code>
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://dwoo.org/LICENSE Modified BSD License
* @link http://dwoo.org/
* @version 1.0.0
* @date 2008-10-23
* @package Dwoo
*/
function Dwoo_Plugin_math_compile(Dwoo_Compiler $compiler, $equation, $format='', $assign='', array $rest=array())
{
/**
* Holds the allowed function, characters, operators and constants
*/
$allowed = array
(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'+', '-', '/', '*', '.', ' ', '<<', '>>', '%', '&', '^', '|', '~',
'abs(', 'ceil(', 'floor(', 'exp(', 'log10(',
'cos(', 'sin(', 'sqrt(', 'tan(',
'M_PI', 'INF', 'M_E',
);
/**
* Holds the functions that can accept multiple arguments
*/
$funcs = array
(
'round(', 'log(', 'pow(',
'max(', 'min(', 'rand(',
);
$equation = $equationSrc = str_ireplace(array('pi', 'M_PI()', 'inf', ' e '), array('M_PI', 'M_PI', 'INF', ' M_E '), $equation);
$delim = $equation[0];
$open = $delim.'.';
$close = '.'.$delim;
$equation = substr($equation, 1, -1);
$out = '';
$ptr = 1;
$allowcomma = 0;
while (strlen($equation) > 0) {
$substr = substr($equation, 0, $ptr);
if (array_search($substr, $allowed) !== false) {
// allowed string
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif (array_search($substr, $funcs) !== false) {
// allowed func
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
$allowcomma++;
if ($allowcomma === 1) {
$allowed[] = ',';
}
} elseif (isset($rest[$substr])) {
// variable
$out.=$rest[$substr];
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif ($substr === $open) {
// pre-replaced variable
preg_match('#.*\((?:[^()]*?|(?R))\)'.str_replace('.', '\\.', $close).'#', substr($equation, 2), $m);
if (empty($m)) {
preg_match('#.*?'.str_replace('.', '\\.', $close).'#', substr($equation, 2), $m);
}
$out.=substr($m[0], 0, -2);
$equation = substr($equation, strlen($m[0])+2);
$ptr = 0;
} elseif ($substr==='(') {
// opening parenthesis
if ($allowcomma>0) {
$allowcomma++;
}
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif ($substr===')') {
// closing parenthesis
if ($allowcomma>0) {
$allowcomma--;
if ($allowcomma===0) {
array_pop($allowed);
}
}
$out.=$substr;
$equation = substr($equation, $ptr);
$ptr = 0;
} elseif ($ptr >= strlen($equation)) {
// parse error if we've consumed the entire equation without finding anything valid
throw new Dwoo_Compilation_Exception($compiler, 'Math : Syntax error or variable undefined in equation '.$equationSrc.' at '.$substr);
return;
} else {
// nothing special, advance
$ptr++;
}
}
if ($format !== '\'\'') {
$out = 'sprintf('.$format.', '.$out.')';
}
if ($assign !== '\'\'') {
return '($this->assignInScope('.$out.', '.$assign.'))';
}
return '('.$out.')';
}