更高效的解决方案来检查表达式语法

时间:2013-12-02 08:59:35

标签: java

问题:表达式语法是否正确?

规则:从左到右的数字左右括号应该是相同的,并且按照良好惯例打开 - 关闭,第一个左边,例如:

(xxx(xx)())          - OK
((()))               - OK
(x(x(x(x(x))X)x)x)   - OK
(()()                - WRONG
)()                  - WRONG

我的解决方案:

private boolean syntaxValidator(String str) {
    if (StringUtils.isBlank(str)) {
        return false;
    } else {
        int counter = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == '(') {
                counter++;
            } else if (str.charAt(i) == ')') {
                counter--;
                if (counter < 0) {
                    return false;
                }
            }
        }
        if (counter == 0) {
            return true;
        } else {
            return false;
        }
    }
}

有效吗?可以通过使用正则表达式来解决吗?怎么样?

3 个答案:

答案 0 :(得分:4)

  

有效吗?

是的,在我看来,只要你将建议纳入另一个答案。通常,如何通过使用堆栈来验证多种类型的括号。如果字符是一个开括号类型的字符(([{之一),请按字符顶部的字符。遇到一种结束类型的字符()}])时,弹出堆栈并比较当前字符和弹出字符。如果不相等,则表示语法错误。

  

可以使用正则表达式解决吗?

这不是正则表达式的工作。支架验证通常需要您进行某种计数(就像您现在所做的那样)。正则表达式本质上不保留任何计数。虽然,我认为,通过使用PCRE可以实现这一点,但我现在还不记得了。

答案 1 :(得分:3)

正则表达式不会削减它,你的解决方案似乎没问题。为了提高效率,请执行此操作(这不是整个代码,只是一个代码段):

int strLength = str.length(); // so you don't have to call this method every time

for (int i = 0; i < strLength; i++) {
    char ch = str.charAt(i); // so you won't have to call this twice
    if (ch == '(') {
        counter++;
    } else if (ch == ')') {
        counter--;
        if (counter < 0) {
            return false;
        }
    }
}

上述评论中的建议return counter == 0;也很棒。

答案 2 :(得分:2)

您无法使用正则表达式解决此问题。您至少需要无上下文解析器来完成它。

在上下文无关语法中你可以写

N = '(' M ')'

在正则表达式中,这是不允许的。与无上下文语法相比,此限制允许更快的匹配。

详情请见:http://en.wikipedia.org/wiki/Regular_grammar