0

我正在考虑验证一个中缀表示法,它由作为操作数的字母和+-*/$作为运算符 [例如:A+B-(C/D)$(E+F)] 在 Java 中使用正则表达式组成。有没有更好的办法?我可以使用任何正则表达式模式吗?

4

3 回答 3

0

可能有点矫枉过正,但您可以考虑使用成熟的解析器生成器,例如 ANTLR (http://www.antlr.org/)。使用 ANTLR,您可以创建自动为您生成 java 代码的规则。假设您在输入中只有有效字符,这是一个语法分析问题,否则您需要先通过词法分析来验证字符流。

对于语法分析,您可能有如下规则:

PLUS : '+' ;
etc...

expression:
         term ( ( PLUS | MINUS | MULTIPLY | DIVIDE )^ term )*
      ;
term:
    constant
  | OPENPAREN! expression CLOSEPAREN!
  ;

常数是整数/实数。如果 ANTLR 生成的解析器代码无法将输入与您的解析器规则匹配,它将引发异常,以便您确定代码是否有效。

于 2011-04-27T13:41:33.503 回答
0

您可能可以使用递归 PCRE 来做到这一点。但这可能是一个 PITA。

因为你只想验证它,你可以很简单地做到这一点。只需使用堆栈,将所有元素一一推入并删除有效表达式。

定义一些规则,例如:

  • 仅当堆栈顶部有字母时才允许使用运算符
  • 仅当堆栈顶部有运算符时才允许使用字母或括号
  • 如果堆栈为空,则一切都被允许

然后:

  • 如果遇到右括号,请删除左括号之前的所有内容。
  • 如果遇到字母,请删除表达式

每次删除表达式后,添加一个虚拟字母表。重复前面的步骤。如果结果是字母表,则表达式有效。

或类似的东西..

于 2011-04-27T13:44:54.567 回答
0

我不熟悉 的语言语法infix,但您当然可以进行第一次验证检查,它只是验证字符串中的所有字符是否有效(即可接受的字符 = 、A-Z+-*/$)。这是一个检查有效字符的 Java 程序,还包括一个检查不平衡(可能嵌套)括号的函数:()

import java.util.regex.*;
public class TEST {
    public static void main(String[] args) {
        String s = "A+B-(C/D)$(E+F)";
        Pattern regex = Pattern.compile(
            "# Verify that a string contains only specified characters.\n" +
            "^                # Anchor to start of string\n" +
            "[A-Z+\\-*/$()]+  # Match one or more valid characters\n" +
            "$                # Anchor to end of string\n",
            Pattern.COMMENTS);
        Matcher m = regex.matcher(s);
        if (m.find()) {
            System.out.print("OK: String has only valid characters.\n");
        } else {
            System.out.print("ERROR: String has invalid characters.\n");
        }
        // Verify the string contains only balanced parentheses.
        if (checkParens(s)) {
            System.out.print("OK: String has no unbalanced parentheses.\n");
        } else {
            System.out.print("ERROR: String has unbalanced parentheses.\n");
        }
    }
    // Function checks is string contains any unbalanced parentheses.
    public static Boolean checkParens(String s) {
        Pattern regex = Pattern.compile("\\(([^()]*)\\)");
        Matcher m = regex.matcher(s);
        // Loop removes matching nested parentheses from inside out.
        while (m.find()) {
            s = m.replaceFirst(m.group(1));
            m.reset(s);
        }
        regex = Pattern.compile("[()]");
        m = regex.matcher(s);
        // Check if there are any erroneous parentheses left over.
        if (m.find()) {
            return false;   // String has unbalanced parens.
        }
        return true;        // String has balanced parens.
    }
}

这不会验证语法,但作为第一个测试过滤明显错误的字符串可能很有用。

于 2011-04-27T15:07:10.077 回答