Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex challenge: changing formats of negative numbers

First of all, I think I have to apologize for not having that much knowledge of regular expressions (yet). I have searched and searched, but haven't found a solution that matches my specific challenge here.

Now here comes the question:

I am currently experimenting with the development of a parser (meaning to write it myself). I would like to do this while taking regular expressions into account. Thus far, I have managed to do quite a lot, however, I am running into a small problem. The unary minus sign and the binary minus sign.

What I've learned on University about a decade ago, is that this should be based upon context. However, there is also a simple trick which I use when doing it by hand and that is writing every unary minus in to a different format:

-3 = (0 - 3) 

or

5 * -3 = 5 * (0 - 3)

A bit more tricky:

(5--5)-3 = (5 - (0 - 5)) - 3

Now, here is my question, is there a possibility to write a regular expression that translates a unary minus expression to a binary minus expression by adding parenthesis and a 0, like in the examples provided above?

Perhaps there might be another way too, but I am getting a little bit biased here...

Comment: First I started off with replacing all minus signs with the word MINUS like:

expressionBuffer = "-(1-2)-3";
expressionBuffer = Regex.Replace(expressionBuffer, "-", "MINUS");

This yields to a new expressionBuffer that looks like:

MINUS ( 1 MINUS 2 ) MINUS 3

Now, I try to capture the binary '-' operators with applying the following regex:

expressionBuffer = Regex.Replace(
                     expressionBuffer, 
                     @"(?<number>((\d+(\.\d+)?)))\s+MINUS", 
                     "${number} -"
                   );

And this yields:

MINUS ( 1 - 2 ) MINUS 3

The first MINUS is clearly a unary operator (but the second is clearly not!) so I am now looking on a way to rewrite that one to the following (first) format:

( 0 - ( 1 - 2) ) MINUS 3

But here I am stuck to treat the first unary minus to a binary minus so that:

( 0 - ( 1 - 2) ) - 3

Any ideas on how to use a regex for this?

like image 409
RvdV79 Avatar asked Feb 10 '17 15:02

RvdV79


People also ask

Does decimal allow negative number?

If UNSIGNED is used with DECIMAL , negative values are not allowed. MySQL stores numbers in DECIMAL columns as strings. Therefore, numbers outside the maximum numeric range for this data type may be stored in a DECIMAL column.


1 Answers

Yes you can do that but you've to call the replacement operation as long as there are changes because the following regex will only replace a single unary operator:

private static Regex _regex = new Regex(@"(?<=^|[-(+*/])-(?<value>\d+|\((?:[^\(\)]|(?<open>\()|(?<-open>\)))+?(?(open)(?!))\))", RegexOptions.Compiled);

private static string RemoveUnaryOperators(string input)
{
    var result = Regex.Replace(input ?? string.Empty, @"\s+", string.Empty);
    string tmp;
    do
    {
        tmp = result;
        result = _regex.Replace(result, @"(0-${value})");
    }
    while (result != tmp);

   return result;
}

DEMO

Output:

5*-3  ->  5*(0-3)
(5--5)-3  ->  (5-(0-5))-3
(5-------5)-3  ->  (5-(0-(0-(0-(0-(0-(0-5)))))))-3
-(1-2)-3  ->  (0-(1-2))-3
like image 176
Sebastian Schumann Avatar answered Oct 16 '22 06:10

Sebastian Schumann