1

Is it possible to write a regex which would take input like 'sqrt(2 * (2+2)) + sin(pi/6)' and transform it into '\sqrt{2 \cdot (2+2)} + \sin(\pi/6)'?

The problem is the 'sqrt' and parentheses in it. It is obvious I can't simply use something like this:

/sqrt\((.?)\)/ -> \\sqrt{$1}

because this code would create something like this '\sqrt{2 \cdot (2+2)) + \sin(\pi/6}'.

sukovanej
  • 658
  • 2
  • 8
  • 18

3 Answers3

1

My solution: it simply go throw the string converted to char array and tests if a current substring starts with $latex, if it does second for-cycle go from this point in different direction and by parentheses decides where the function starts and ends. (startsWith function)

Code:

public static function formatFunction($function, $latex, $input) {
    $input = preg_replace("/" . $function . "\(/", $latex . "{", $input);
    $arr = str_split($input);

    $inGap = false;
    $gap = 0;

    for ($i = count($arr) - 1; $i >= 0; $i--) {
        if (startsWith(substr($input, $i), $latex)) {
            for ($x = $i; $x < count($arr); $x++) {
                if ($arr[$x] == "(" || $arr[$x] == "{") { $gap++; $inGap = true; } 
                else if ($arr[$x] == ")" || $arr[$x] == "}") {  $gap--; }

                if ($inGap && $gap == 0) {
                    $arr[$x] = "}";
                    $inGap = false;
                    break;
                }
            }
        }
        $gap = 0;
    }

    return implode($arr);
}

Use:

self::formatFunction("sqrt", "\\sqrt", 
"sqrt(25 + sqrt(16 - sqrt(49)) + (7 + 1)) + sin(pi/2)");

Output:

\sqrt{25+\sqrt{16-\sqrt{49}}+(7+1)}+\sin (\pi/2)

Note: sin and pi aren't formated by this code, it's only str_replace function...

Community
  • 1
  • 1
sukovanej
  • 658
  • 2
  • 8
  • 18
0

In general, no regular expression can effectively handle nested parentheses. Sorry to be the bearer of bad news! The MathJAX parser library can interpret LaTeX equations and you could probably add a custom output routine to do what you want.

For TeX questions, you can also try http://tex.stackexchange.com .

Community
  • 1
  • 1
cxw
  • 16,685
  • 2
  • 45
  • 81
  • Thanks, I use MathJax in my project, but I don't believe it could do this job (at least I can't imagine how), because it would have to somehow solve the problem i've ask about. Is there any other option how to do this in PHP? – sukovanej Jul 26 '15 at 11:12
0

Some time ago i soved a similar problem in such way. Maybe it will be helpful for you

$str = 'sqrt((2 * (2+2)) + sin(pi/(6+7)))';
$from = [];     // parentheses content
$to = [];       // patterns for replace #<number> 
$brackets = [['(', ')'], ['{', '}'], ['[', ']']]; // new parentheses for every level
$level = 0;
$count = 1;  // count or replace made
while($count) {
  $str = preg_replace_callback('(\(([^()]+)\))', 
           function ($m) use (&$to, &$from, $brackets, $level) {
             array_unshift($to, $brackets[$level][0] . $m[1] . $brackets[$level][1]);
             $i = '#' . (count($to)-1); // pattern for future replace. 
                                        // here it '#1', '#2'. 
                                        // Make it so they will be unique
             array_unshift($from, $i); 
             return $i; }, $str, -1, $count); 
  $level++;
  }

echo str_replace($from, $to, $str); // return content back
// sqrt[{2 * (2+2)} + sin{pi/(6+7)}]

I forgot all details, but it, seems, works

splash58
  • 26,043
  • 3
  • 22
  • 34