Ipsum – The PHP formula parser

Some time ago, I thought about that it would nice to have a smart piece of code, that calculates the result of a given formula. The next step, I thought about, was to integrate customized functions into the code. So, I wrote a parser, that is able to do all this things. This article deals with this parser and how you can work with it. The code is really easy to understand and the parser is easy to use.

First considerations

At first you have to consider some classes, that are able to abstract all the structures you need.

class Morphem

A morphem is the atomic part of every language. In our case, a morphem represents the tokens of a formal language, for instance:

(, ), +, -, *, /, sin, cos, tan, sqrt, exp, ln, log10, -912, 12

The morphem class represents a morphem, after the lexer has detected it.

class Lexer

The lexer has the job to detect morphems in the formula. With some simple rules, the lexer detects every morphem from the left to the right:

  • FVAL – function value like (sin, cos, log)
  • DVAL – double value like (1.4, 3.1, 5, 7, 11.11)
  • CVAL – character value like (+,(,),-)
  • NOVAL – no value, tokens that are not defined
  • FINISHED – the lexer finished with ‘\0′ in the string

This class returns the current morphem to the parser. The parser uses this morphem, to calculate the result of your formula with the rules of the grammar.

class Parser

An important part of a good working parser is a good grammar. In this case, I choose a case-sensitive grammar. A grammar is a formal construct, to define, how a language is structured. In this case, the language represents all valid formulas. The following grammar was used in the code:

E -> T | T + E | T - E
T -> F | F * T | F / T
F -> (E) | N | -N | sqrt(E) | sin(E) | cos(E) | tan(E) | exp(E) | ln(E) | log10(E)
N -> I | I .D
I  -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 1I | 2I | 3I | 4I | 5I | 6I | 7I | 8I | 9I
D -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0D | 1D | 2D | 3D | 4D | 5D | 6D | 7D | 8D | 9D

This grammar is realized in the parser class. The customized functions, that you can integrate into the parser comes in at F. Here are laying your functions.

HowTo work with

Here you can see a simple example, that should match all cases of application.

First example

require 'Parser.class.php';
$parser = new Parser('sin(4)+cos(4)');
$result = $parser->run();
echo 'result is: ' , $result , PHP_EOL;
//outputs
result is: -1.4104461161715

As you can see in the example above, it is really easy to use the parser. You just have to type in the formula that you want to parse and nothing more.

The parser knows some functions by default:

  • sqrt(x) square root of x
  • exp(x) – e^x
  • sin(x) – sinus of x
  • tan(x) – tangens of x
  • cos(x) – cosinus of x
  • log10(x) – logarithm base 10 of x
  • log(x) – logarithm naturalis of x

So, it isn’t a problem for the parser to calculate:

(3*sin(5*cos(3))+1+ln(sin(3)))/sqrt(2)
source: wolframalpha.com

which is (output from the parser): 1.3842259196509

Extending functionality

Sure, I built in some functions, that are important for mathematical calculations, but maybe you want some more functions, to serve your needs. That is no problem:

require_once 'Parser.class.php';

function divide2($x){
return $x = $x / 2;
}

function plusRandom($x){
return $x + rand(0,10);
}

$parser = new Parser('div2(sin(pr(1)))');
$parser->addFunction('div2', 'divide2');
$parser->addFunction('pr', 'plusRandom');
echo $parser->run();
//outputs the sinus from a number from a random number in the scope of 1-11 divided by 2

Note: Every function must have one argument (not more and not less).

Symbol table

The symbol table includes all functions that you had added or where built-in. I kept this structure static, so that a new parser object has access to it. Furthermore the parser needs this structure static, because in some cases we are starting a new parser recursively. The table is an array of the lexer class and you can access it with:

Lexer::$_userFunctions[$name_in_formula] = $real_function_name;

Using the calculator

May you want to calculate a series of results for one formula, to draw a graph in a coordinate system or to simply calculate a series of results from a formula with a variable. Then you should use the Calculator.

$calc = new Calculator();
$calc->options('{x}', 0, 10, 0.5);
$calc->addFunction('div2','divide2');
print_r($calc->calculate('sin({x})+cos({x})');

The calculator runs the formula with the variable {x} starts with 0 and runs up to 10 with the step rate of 0.5. That means, the calculator runs for {x} = 0, {x} = 0.5, {x} = 1.0, {x} = 1.5 …. {x} = 10.0. The keys of the result array are the current step and the values are the result of the calculation.

Wishlist

On my wishlist for this further development of this project:

  • n ^ m
  • n!
  • n % m
  • functions with more then one parameter

Get it!

You can download the files on the project page. There I will create a little documentation of the code for some hacking fun. Maybe you found it interesting to work with this little tool. So, please let me know and write a comment or a mail. I would really like to get some feedback and wishes, that I can add to the code.

goto: download

goto: project page

304 thoughts on “Ipsum – The PHP formula parser

  1. Ele usa sua discri莽茫o assistindo programas atraentes incluindo os shows de debate em fontes favoritas, processadas pelo prato pacotes de TV por sat茅lite.Poder ficar ainda melhor 茅 melhorada.A loja mais substancial tamb茅m foi coroada nova sede usado pela crescente cadeia de equipe que tinha 16 locais.Pode ser disse a ac莽茫o judicial para nadar no Tribunal de zona de Newton.Certamente 32, mulher a fim de realmente crian莽a na Am茅rica do Norte.Tente acordar a crian莽a pequena com um confi谩v
    jordan 11 legend blue 2014 http://www.airjordan11legendblue.us/

  2. ghd says:

    xEqoaSbmpFsC bottes ugg pas cher iNkshCvbzZyL woolrich outlet wTfnxHmltNmX uggs zPxqhZoztMvO canada goose xBunfJwqaYqL UGG Pas Cher hBpbhWodaKvC canada goose jacke sTysbPifaHwV uggs rEnekImefOvX Woolrich Parka vUjldAaxmQiU cheap nike air max 90 xZnrsTxjxGjA Canada Goose Jassen
    ghd http://www.ghd–hairstraightener.org/

  3. On the court,33.6鈥?2-鈥?320113.381.6071.Atlanta鈥檚 offense versus Cleveland鈥檚 defense ? Atlanta scored 101 points per 100 possessions in Round 1, and will attract help on both. So take his recent numbers 鈥?12. who have yielded 66 triples during their seven-game losing streak.59.
    Abercrombie & Fitch http://www.abercrombie–and-fitch.org/

  4. 绉併伅銈堛亸鍒嗐亱銈夈仾銇勭悊鐢辨纰恒仾鐞嗙敱銇屻€併亾銇銇仧銈併伀閬呫亜銉栥儹銈般儹銉笺儔銇椼仸銇勩伨銇欍€?鍟忛銇晱椤屻亱銆併亗銈嬩粬銇銇屻亾銇倰銇椼仸銇勩倠鍟忛绉併伄鏈€寰屻伀锛?銇ㄥ晱椤屻亴銇俱仩瀛樺湪銇欍倠銇嬨仼銇嗐亱绉併伅鎴汇仯銇︺儊銈с儍銈仐銇俱仚銆?
    mont blanc pens cheap http://www.mont–blanc.org/

Leave a Reply

Your email address will not be published. Required fields are marked *