PHP Classes

File: test.php

Recommend this page to a friend!
  Classes of Gonzalo Chumillas   Ses Parser   test.php   Download  
File: test.php
Role: Example script
Content type: text/plain
Description: parsing a mathematical expression
Class: Ses Parser
Parse a string with an expression of any type
Author: By
Last change: Updating
Date: 10 years ago
Size: 6,403 bytes
 

Contents

Class file image Download
<?php
/**
 * This file contains a class to parse and calculate a mathematical expression.
 * Allowed functions are: sin, cos, tan, sqrt, abs and ln (natural logarithm)
 * Allowed constans are: PI and E
 */
 
dirname(__FILE__) . "/classes/parser/parser.php";

require_once
"classes/parser/parser.php";

class
MathParser extends Parser {
    private
$constants;
    private
$operators;
    private
$functions;
    private
$stack;
   
    public function
__construct($string, $flags = 0) {
       
parent::__construct($string, $flags);
       
       
$this->constants = array(
           
"pi" => M_PI,
           
"e" => M_E
       
);
       
       
$this->operators = array(
           
"+" => array("priority" => 0, "func" => create_function('$x,$y', 'return $x + $y;')),
           
"-" => array("priority" => 0, "func" => create_function('$x,$y', 'return $x - $y;')),
           
"*" => array("priority" => 1, "func" => create_function('$x,$y', 'return $x * $y;')),
           
"/" => array("priority" => 1, "func" => create_function('$x,$y', 'return $x / $y;')),
           
"^" => array("priority" => 2, "func" => create_function('$x,$y', 'return pow($x, $y);'))
        );
       
       
$this->functions = array(
           
'sin' => create_function('$x', 'return sin($x);'),
           
'cos' => create_function('$x', 'return cos($x);'),
           
'tan' => create_function('$x', 'return tan($x);'),
           
'sqrt' => create_function('$x', 'return sqrt($x);'),
           
'abs' => create_function('$x', 'return abs($x);'),
           
"ln" => create_function('$x', 'return log($x);')
        );
       
       
$this->stack = array();
    }
   
    private function
compute($number, $operator = "+") {
       
$level = count($this->stack) - 1;
       
array_unshift($this->stack[$level], array("number" => $number, "operator" => $operator));
       
        while (
count($this->stack[$level]) > 1) {
           
$op0 = $this->stack[$level][0]["operator"];
           
$op1 = $this->stack[$level][1]["operator"];
           
$priority0 = $this->operators[$op0]["priority"];
           
$priority1 = $this->operators[$op1]["priority"];
           
            if (
$priority0 <= $priority1) {
               
$func = $this->operators[$op1]["func"];
               
$n0 = $this->stack[$level][0]["number"];
               
$n1 = $this->stack[$level][1]["number"];
               
$this->stack[$level][1]["number"] = $func($n1, $n0);
               
$this->stack[$level][1]["operator"] = $op0;
               
array_shift($this->stack[$level]);
            } else {
                break;
            }
        }
       
        return
$this->stack[$level][0]["number"];
    }
   
    protected function
constant() {
        return
$this->in(array_keys($this->constants));
    }
   
    protected function
operator() {
        return
$this->in(array_keys($this->operators));
    }
   
    protected function
func() {
       
$functions = array_keys($this->functions);
       
        if (list(
$func) = $this->in(array_keys($this->functions))) {
           
$f = $this->functions[$func];
           
            if (!list(
$number) = $this->is("term")) {
                throw new
ParserException($this, "Unrecognized term");
            }
           
            return array(
$f($number));
        }
       
        return
FALSE;
    }
   
    protected function
term() {
       
$ret = FALSE;
       
        if (
$this->eq("(")) {
            if (list(
$number) = $this->is("expression")) {
               
$ret = array($number);
            }
            if (!
$this->eq(")")) {
                throw new
ParserException($this, "Missing ')'");
            }
        } else
        if (
$this->eq("-")) {
            if (!list(
$number) = $this->is("term")) {
                throw new
ParserException($this, "Unrecognized term");
            }
           
           
$ret = array(-$number);
        } else
        if (list(
$const) = $this->is("constant")) {
           
$ret = array($this->constants[$const]);
        } else
        if ( (list(
$number) = $this->number()) || (list($number) = $this->is("func")) ) {
           
$ret = array($number);
        }
       
        return
$ret;
    }
   
    protected function
expression() {
       
array_push($this->stack, array());
       
$result = 0;
       
$op = "+";
       
        do {
           
$this->compute($result, $op);
            if (!list(
$result) = $this->is("term")) {
                throw new
ParserException($this, "Unrecognized term");
            }
        } while (list(
$op) = $this->is("operator"));
       
       
$result = $this->compute($result);
       
array_pop($this->stack);
        return array(
$result);
    }
   
    protected function
_parse() {
        return
$this->is("expression");
    }
}

$error = "";
$result = 0;
$expression = isset($_REQUEST["expression"])? $_REQUEST["expression"] : "-25 + 48 * (32^2 - ln E) + sin(PI/2) - 5^2";

// calculates the expression
$p = new MathParser($expression);

try {
    list(
$result) = $p->parse();
} catch (
ParserException $e) {
   
$error = $e->getPrintableMessage();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Math Parser</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>

<body>
    <form action="<?php echo $_SERVER["PHP_SELF"] ?>" method="post">
        <div>
            <label for="expression">Enter a mathematical expression:</label><br />
            <input type="text" name="expression" id="expression" value="<?php echo htmlentities($expression) ?>" size="80" />
            <input type="submit" value="Calculate!" />
        </div>
       
        <?php if ($error): ?>
<pre style="color: brown; "><strong><?php echo $error ?></strong></pre>
        <?php else: ?>
<p><strong>Result is</strong>: <?php echo htmlentities($result) ?></p>
        <?php endif ?>

        <p style="color: gray; ">
            Allowed functions: sin, cos, tan, sqrt, abs, ln<br />
            Allowed constants: PI, E
        </p>
    </form>
</body>
</html>