我一直在与这个问题作斗争,但还没有找到解决方案。我必须验证布尔字符串表达式的语法,这样我才能使用它来查找文档中的单词或句子。例如,(football football!|basket((应该是不正确的,因为football和football是分开的,应该在"之间,也因为括号不正确和!|没有意义。这是一个简单的布尔表达式,所以我可以使用&,!,|,((。。。知道吗?
我试着对字符串进行迭代,试图验证每个字符,但我无法找到最终的解决方案。
这可能不是一个整体解决方案,但它可能会让您朝着这个目标迈出一步。下面的方法将尝试解析和验证您在文章中描述的提供的自定义表达式。如果提供的表达式有效,则该提供的表达式的组件将在String[]数组中返回。如果返回的String[]数组为null,则会发现提供的表达式无效。Invalid表达式还会在控制台窗口中显示一条错误消息,解释该表达式无效的原因。请务必阅读代码中的注释:
/**
* Custom Expression Parser/Validator:
*
* If the supplied expression is valid whereas it meets the guidelines within
* the code, then return a String[] Array containing the components of that
* expression. If the expression is found to be invalid then a warning message
* is displayed to the Console Window explaining the problem and null is returned.
*
* @param expressionString (String) The expression to validate.<br>
*
* @return (String[] Array) Returns null if the expression is found invalid
* otherwise the returned String Array will contain the components of the
* expression. Process these returned expression components as you see fit.
*/
public String[] isExpressionValid(String expressionString) {
// List to hold expression components.
List<String> expressionList = new ArrayList<>();
// If the expression string is null or empty then return null.
if (expressionString == null || expressionString.isEmpty()) {
return null;
}
// Are the brackets proper in the expression?
Map<Character, Character> openClosePair = new HashMap<>();
openClosePair.put(')', '(');
Stack<Character> stack = new Stack<>();
for (char ch : expressionString.toCharArray()) {
if (openClosePair.containsKey(ch)) {
if (stack.isEmpty() || !Objects.equals(stack.pop(), openClosePair.get(ch))) {
break;
}
}
else if (openClosePair.values().contains(ch)) {
stack.push(ch);
}
}
if (!stack.isEmpty()) {
System.err.println("Invalid Expression! [" + expressionString + "] - Parentheses Mismatch!");
return null;
}
/* Parentheses are valid so now remove them to validate
the data within the parentheses. */
expressionString = expressionString.replaceAll("[\(\)]", "");
/* Is &, !, or | within the expression? If so, is it proper?
If there are consecutive `same` operators (ie: "&&&") then
convert them to a single operator (ie: "&"). */
expressionString = expressionString.replaceAll("[&]{2,}", "&")
.replaceAll("[|]{2,}", "|"). replaceAll("[!]{2,}", "!");
// Add whatever you feel would be invalid...
String[] invalidOperators = {"&|", "|&", "!|", "!&", "!&|", "!|&",
"&!|", "&|!", "|!&", "|&!"};
// Make sure of valid operator use.
for (String op : invalidOperators) {
if (expressionString.contains(op)) {
System.err.println("Invalid Logical Operator Configuruation [" +
op + "] Within Expression!");
return null;
}
}
/* Split the expression on delimiters '&' or '|' but
also add the delimiter to the generated array: */
String regEx = "((?<=\Q&\E)|(?=\Q&\E))|"
+ "((?<=\Q|\E)|(?=\Q|\E))";
String[] expParts = expressionString.split(regEx);
String exp;
for (int i = 0; i < expParts.length; i++) {
exp = expParts[i].trim(); // Remove leading/trailing whitespaces.
// Is the element a non-numerical value?
if (!exp.matches("-?\d+(\.\d+)?") && !exp.matches("[!\|&]")) {
// This element must be alpha or alphanumeric.
/* Is there a whitespace in it? If so, is it wrapped in quote marks?
If not then this is invalid. */
if (exp.contains(" ") && ((!exp.startsWith("!"") || !exp.startsWith(""")) && !exp.endsWith("""))) {
System.err.println("Invalid String [" + exp + "] Within Expression!"
+ System.lineSeparator() + "Because this portion of the expression "
+ "contains at least one whitespace," + System.lineSeparator()
+ "it should be wrapped within quotation marks excluding any Logical Operator"
+ System.lineSeparator() + "located at the beginning.");
return null;
}
}
/* Does the expression start with or end with a Logical Operator '&' or '|'?
This is considered invalid. */
if ((i == 0 || i == expParts.length - 1) && (exp.equals("&") || exp.equals("|"))) {
System.err.println("Invalid Logical Operator Location! [" + expressionString + "]"
+ System.lineSeparator() + "The expression can not start with or end "
+ "with a '&' or '|' operator!");
return null;
}
// Add the expresion component to the List
expressionList.add(exp);
}
// Convert the List to a String[] Array and return.
return expressionList.toArray(new String[expressionList.size()]);
}
你可以如何使用上面的方法是这样的:
String expression = "(footballer football !| basket)(";
String[] expressionParts = isExpressionValid(expression);
if (expressionParts != null) {
// Display the components of the supplied expression:
System.out.println(Arrays.toString(expressionParts));
}