验证递归字符串结构

时间:2015-06-14 14:44:10

标签: c# regex

我想验证一个表示表达式树的序列化形式的字符串。以下是我要验证的一些示例:

  • Ex 1:(6+2)
  • Ex 2:(6*(4+2))
  • Ex 3:(9*(4-(7*3)))
  • Ex 4:((5+2)/(9+2))
  • Ex 5:(((2-1)+2)/(9+()7*2))

从Ex 1中可以看出,简单的情况是我有两个数字,其中一个操作被括号括起来。但是,任何一个数字也可以表达。这些表达式可以根据需要进行深入处理。

我在.NET中工作并希望编写一个正则表达式来验证字符串的格式是否符合我在示例中显示的内容。我无法弄清楚如何编写.NET正则表达式来执行此验证。

可以通过以下方式验证简单案例:

string testCase = "(6+2)";
string baseExpression = "([(][0-9][+-/*][0-9][)])";
Regex rgx = new Regex(baseExpression );
bool returnValue = rgx.IsMatch(testCase);

但是,我不知道如何引入一个数字可以被另一个baseExpression替换的递归;

示例显示数字的整数。最终,我希望能够将这些数值表示为具有(或不包含)小数点的浮点数。

有人有什么想法吗?

3 个答案:

答案 0 :(得分:1)

通常,正则表达式不足以验证表达式中的括号。但是,.NET支持balancing groups,可用于验证表达式,如下所示:

^[^()]*(?>(?>(?'open'\()[^()]*)+(?>(?'-open'\))[^()]*)+)+(?(open)(?!))$

'open''-open'是平衡组。该表达式的工作在链接的文章中进行了解释。

尽管.NET允许你在正则表达式中执行此操作,但它并不是解决此问题的最佳方法,因为任何基于正则表达式的解决方案都变得脆弱,而且“只写一次且永不触摸”再次"解。为这项任务编写一个简单的recursive descent parser会更好,因为以这种方式编写的解决方案易于阅读且可维护性更强。

答案 1 :(得分:1)

正则表达式不是解析任务的好工具。对于这个特定的,您可以使用DataTable来评估您的公式:

static bool evaluateFormula(String formula)
{
    DataTable dt = new DataTable();
    try
    {
        var v = dt.Compute(formula, "");//if you need the result return this
        return true;
    }
    catch(SyntaxErrorException)
    {
        return false;
    }            
}

在你的例子中,最后一个公式是无效的,因为9 +()7 * 2实际上没有意义:

static void Main(String[] args)
{
    Console.WriteLine(evaluateFormula("(6+2)"));
    Console.WriteLine(evaluateFormula("(6*(4+2))"));
    Console.WriteLine(evaluateFormula("(9*(4-(7*3)))"));
    Console.WriteLine(evaluateFormula("((5+2)/(9+2))"));
    Console.WriteLine(evaluateFormula("(((2-1)+2)/(9+()7*2))"));
}

输出:

True
True
True
True
False

答案 2 :(得分:0)

我认为您应该使用堆栈结构来堆叠字符串输入中的字符。 System.Collections.Stack

这里不需要递归。只需将您的角色一次放入堆叠中并按照您的意愿控制它。

ps:我在java中创建了一个可能以某种方式提供帮助的verifyXML方法VerifyXML Java