Expresión regular para una expresión matemática

I needed a regular expression for a mathematical expression, which should satisfy the following conditions explained in this SO pregunta which was asked by me.

It worked fine with this expression

But now I need to add the support for opening and closing parenthesis along with previous conditions. So that my regular expression should validate the expressions of these patterns

p.ej. *6+(7-9) or /6.25*(7-9.2) or +6 or *6/(7.5-9)

I tried to make modifications to the existing regular expression but was not successful in achieving. It also accepts these patterns *6+(7-9 y *6+7-9) which are not valid, as single parenthesis can be present in a mathematical expression.

Aquí está el enlace RegExr . Por favor ayuda.

preguntado el 04 de julio de 12 a las 07:07

No, you can't use regex for this. Write a small parser. -

Which regex engine are you using? This can only be done with a regex engine that supports recursion like .NET or Perl, and even then, it's going to be a very hairy regex. -

A real parser will be a montón more maintainable. -

@Tim Pietzcke - I am using the regular expression to validate the text for a textbox, in my asp.net application. What you suggest in such a case. -

3 Respuestas

@Bibhu, since mathematical expressions can be nested arbitrarily, you need an actual parser to validate them. A regular expression won't work. Regular expressions are not powerful enough to deal with arbitrarily deep recursive nesting.

If you limit the nesting to a maximum level, you could write a (very big and ugly) regexp which could validate the expressions. But fundamentally, regexps are the wrong tool for the job.

If you have a parser generator which you already know how to use, that would be the easiest way to build a parser for mathematical expressions. If you don't, writing a simple top-down recursive-descent parser by hand is still quite easy.

Respondido 04 Jul 12, 07:07

This is not entirely true. Hardly any current "regex" engine is restricted to actually "regular" expressions. Many do support recursion. Apart from this fact, this is more of a comment than an answer. - Tim Pietzcker

@TimPietzcker, thanks for pointing that out. I am actually aware that some regex engines support recursion, and have posted answers on SO before which mention that fact. In this case, I think a recursive-descent parser is the best solution, and don't want to confuse the issue. If you want to post an answer demonstrating how to solve the problem using "non-regular regular expressions", please do so. You'll need to find out what language the OP is using to get the correct syntax. - Alex D

That's why I wrote my comment to Bibhu's question. RegExr, at least, doesn't seem to support recursive regexes... - Tim Pietzcker

@Alex D - I am using the regular expression to validate the text for a textbox, in my asp.net application. What you suggest in such a case. - bibhu

(by amusing your text can be more complicated) best way is a text recognizer like ANTLR.

Respondido 04 Jul 12, 07:07

I'm wondering if you're offering a bounty.

Simple recursion in regex is a gosub with a pass/fail return that happens to be stackable.

Below is a Perl routine that passes Perl's own parsing algol for the simple operators and simple syntax rules you specified. It's done in a single regex because your needs are extremely simple.

It looks fancy but resolves to the simple balanced text of '()'. It looks like Dot Net
can do this. It should be real easy to just do the substitution's (ie; (?&var) ), do
the balanced grouping Dot Net requires... instant validation.

I'm posting this because, nesting is not the problem. The problem is that as simple as
parsing seems, the devil is in the details.

^
(?:
     ^ (?&sign)? (?&number)
  |
     (?&operator) 
     (?<! ^ (?:\/|\*) )
     (?<! ^ [*]{2} )
     (?&sign)? (?&number)
  |
     (?: (?&operator)
         (?<! ^ (?:\/|\*) )
         (?<! ^ [*]{2} )
         (?<! [(] (?:\/|\*) )
         (?<! [(] [*]{2} )
         (?&sign)?
       |
         (?<= [(] )
       |
         ^ (?&sign)?
     )

     (?<term>
        \(
           (?:
                (?>  (?&sign)?
                     (?&number)
                     (?: (?&operator) (?&sign)? (?&number) )*
                )
             |
                (?>
                    (?: (?<= [(] ) | (?&operator) )
                    (?<! [(] (?:\/|\*) )
                    (?<! [(] [*]{2} )
                    (?&sign)?
                    (?&term)
                )
           )*
        \)
        (?! [(] )
        (?> (?&operator) (?&sign)? (?&number) )*
     )
)*
$

(?(DEFINE)
  (?<number>    \d+(?:\.\d+)?   )
  (?<sign>      [+-]            )
  (?<operator>
        (?:  [*]{2}
          |  [\/*]
          |  (?<pm>[-+]) (?! \k<pm>) )
         )
  )

Salida

passed  ''
passed  '(6**-2**3)'
passed  '6-+2'
passed  '-(-(8*((2)/3)))'
passed  '-((8*((2)/3)))'
passed  '-((8*((2**4)/3)))'
passed  '-((8*((2**4)/3)))**((-1)*(8*((2**4/99)/3)))'
passed  '-((8*((2**4)/3)))**((-1)*(8*((2**-4/99)/3)))'
passed  '-((8*((2**4)/3)))**-((-1)*(8*((2**-4/99)/3)))'
passed  '((8*((2)/3)))'
passed  '((8*((2)/3)))'
passed  '+((8*((-2)/-3)))'
passed  '8-6*2'
passed  '-8-6*2'
passed  '((8*((2-(8*(8+6)/2))/3))-7*2/234)+8/2*1'
passed  '-(8*(8+6)/2)'
passed  '(9*9/9)'
passed  '(9*(9)/9*(9*(9)/9)*1)'
passed  '(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'

failed  '(6--2)'
failed  '-(/(8*((2)/3)))'
failed  '-((8*((2(6))/3)))'
failed  '+((8*((+2)/--3)))'
failed  '+((8*((+2)/--3+)))'
failed  '+((8*((*2)/--3)))'
failed  '+((8*((*2)/-3)))'
failed  '-((8*((-2)/+-3)))'
failed  '+8/2(1)'
failed  '-(8)*(8/('
failed  '-(8)*(8/()'
failed  '*(9*9/9)'
failed  '*(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'
failed  '/(9*(9)/9*(9*(9)/9))*(9*(9)/9*(9*(9)/9))'

Respondido 13 ago 12, 01:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.