2012-07-04 47 views
0

我需要一个数学表达式的正则表达式,该数学表达式应满足我在本文提出的SO Question中解释的以下条件。数学表达式的正则表达式

它好工作与此表达

但现在我需要添加与以前的条件一起开启和关闭括号支持。所以我的正则表达式应该验证这些模式的表达式

例如。 *6+(7-9)/6.25*(7-9.2)+6*6/(7.5-9)

我试图让修改现有的正则表达式,但没有成功地实现。它也接受这些模式*6+(7-9*6+7-9),这是无效的,因为单括号可以出现在数学表达式中。

以下是链接RegExr。请帮忙。

+0

不,你不能使用正则表达式这一点。写一个小解析器。 – leppie

+0

您正在使用哪种正则表达式引擎?这只能用支持递归的正则表达式来完成。NET或Perl,即使如此,这将是一个非常毛茸茸的正则表达式。 –

+1

真正的解析器将会更加可维护。 – Ashe

回答

4

@Bibhu,因为数学表达式可以任意嵌套,你需要一个实际的解析器来验证它们。正则表达式不起作用。正则表达式不足以处理任意深度的递归嵌套。

如果您将嵌套限制到最大级别,可以编写一个(非常大且丑陋的)正则表达式来验证表达式。但从根本上来说,正则表达式是这项工作的错误工具。

如果您有一个您已经知道如何使用的解析器生成器,那将是构建数学表达式解析器的最简单方法。如果你不这样做,手工编写简单的自顶向下递归下降解析器仍然非常简单。

+0

这不完全正确。几乎没有任何当前的“正则表达式”引擎仅限于实际的“常规”表达式。许多人都支持递归。除了这个事实,这更多的是评论而不是回答。 –

+0

@TimPietzcker,谢谢你指出。我实际上知道一些正则表达式引擎支持递归,并且在SO之前发布了提及这个事实的答案。在这种情况下,我认为递归下降解析器是最好的解决方案,不想混淆问题。如果您想发布一个答案,说明如何使用“非常规正则表达式”解决问题,请这样做。你需要找出OP使用什么语言来获得正确的语法。 –

+0

这就是为什么我写了我的评论Bibhu的问题。至少,RegExr似乎不支持递归正则表达式... –

0

(通过逗你的文字可以更复杂)最好的方式是文本识别器,如ANTLR

0

我想知道你是否提供赏金。

正则表达式中的简单递归是一个带有合格/不合格返回的gosub,它恰好是可堆叠的。

下面是一个Perl例程,它为您指定的简单操作符和简单语法规则传递Perl自己的解析algol。这是在一个正则表达式中完成的,因为你的需求非常简单。

它看起来很花哨,但解决了'()'的简单平衡文本。它看起来像Dot Net
可以做到这一点。它应该是真正容易的只是做替代的(即;(?& var)),做
平衡分组DotNet需要...即时验证。

我发布这个,因为,嵌套不是问题。问题是,像
解析似乎简单,魔鬼是在细节。

^ 
(?: 
    ^(?&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>)) 
     ) 
) 

输出

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))'