Validate user inputted PHP code before passing it to eval()

php

Solution

As far as validation is concerned, the following character tokens are valid:

operator: [/*+-]
funcs:    (a\(|b\()
brackets: [()]
numbers:  \d+(\.\d+)?
space:    [ ]

A simple validation could then check if the input string matches any combination of these patterns. Because the `funcs` token is pretty precise and it does not clash much with other tokens, this validation should be quite stable w/o the need implementing any syntax/grammar already:

$tokens = array(
    'operator' => '[/*+-]',
    'funcs' => '(a\(|b\()',
    'brackets' => '[()]', 
    'numbers' => '\d+(\.\d+)?',
    'space' => '[ ]',
);

$pattern = '';
foreach($tokens as $token)
{
    $pattern .= sprintf('|(?:%s)', $token);
}
$pattern = sprintf('~^(%s)*$~', ltrim($pattern, '|'));

echo $pattern;

Only if the whole input string matches against the token based pattern, it validates. It still might be syntactically wrong PHP, put you can ensure it only is build upon the specified tokens:

~^((?:[/*+-])|(?:(a\(|b\())|(?:[()])|(?:\d+(\.\d+)?)|(?:[ ]))*$~

If you build the pattern dynamically - as in the example - you're able to modify your language tokens later on more easily.

Additionally this can be the first step to your own tokenizer / lexer. The token stream can then passed on to a parser which can syntactically validate and interpret it. That's the part user187291 wrote about.

Alternatively to writing a full lexer+parser, and you need to validate the syntax, you can formulate your grammar based on tokens as well and then do a regex based token grammar on the token representation of the input.

The tokens are the words you use in your grammar. You will need to describe parenthesis and function definition more precisely then in tokens, and the tokenizer should follow more clear rules which token supersedes another token. The concept is outlined in another question of mine. It uses regex as well for grammar formulation and syntax validation, but it still does not parse. In your case `eval` would be the parser you're making use of.

Problem

Before passing a string to eval() I would like to make sure the syntax is correct and allow: - Two functions: a() and b() - Four operators: /*-+ - Brackets: () - Numbers: 1.2, -1, 1 How can I do this, maybe it has something to do with PHP Tokenizer? I'm actually trying to make a simple formula interpreter so a() and b() will be replaced by ln() and exp(). I don't want to write a tokenizer and parser from scratch.

Original source

Related problems