分词
public class ExpressionTokenizer {
static Pattern pattern = null;
static String regex = "\\d+(\\.\\d+)?|[+\\-*/()]";
public ExpressionTokenizer() {
// 定义一个正则表达式来匹配操作数、运算符和括号
pattern = Pattern.compile(regex);
}
public List<String> tokenize(String expression) {
Matcher matcher = pattern.matcher(expression);
List<String> tokens = new ArrayList<>();
while (matcher.find()) {
tokens.add(matcher.group());
}
return tokens;
}
}
语义检查,取中缀,后缀表达式转换,计算结果
import java.util.*;
public class ExpressionHandler {
// 定义运算符的优先级
private static final Map<String, Integer> PRECEDENCE_MAP = new HashMap<>();
static {
PRECEDENCE_MAP.put("+", 1);
PRECEDENCE_MAP.put("-", 1);
PRECEDENCE_MAP.put("*", 2);
PRECEDENCE_MAP.put("/", 2);
}
// 语法检查方法
public boolean validateSyntax(List<String> tokens) {
Stack<String> operators = new Stack<>();
Stack<String> operands = new Stack<>();
for (String token : tokens) {
if (isNumber(token)) {
operands.push(token);
} else if (isOperator(token)) {
while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(token)) {
if (operands.size() < 2) {
return false;
}
operands.pop();
operators.pop();
}
operators.push(token);
} else if (token.equals("(")) {
operators.push(token);
} else if (token.equals(")")) {
while (!operators.isEmpty() && !operators.peek().equals("(")) {
if (operands.size() < 2) {
return false;
}
operands.pop();
operators.pop();
}
if (operators.isEmpty() || !operators.peek().equals("(")) {
return false;
}
operators.pop(); // Pop the '(' from stack
} else {
return false; // Invalid token
}
}
while (!operators.isEmpty()) {
if (operands.size() < 2) {
return false;
}
operands.pop();
operators.pop();
}
return operands.size() == 1;
}
// 检查是否是数字
private boolean isNumber(String token) {
return token.matches("\\d+(\\.\\d+)?");
}
// 检查是否是运算符
private boolean isOperator(String token) {
return PRECEDENCE_MAP.containsKey(token);
}
// 获取运算符优先级
private int precedence(String operator) {
return PRECEDENCE_MAP.getOrDefault(operator, -1);
}
// 将分词列表转为中缀表达式字符串
public String tokensToInfix(List<String> tokens) {
StringBuilder infix = new StringBuilder();
for (String token : tokens) {
infix.append(token).append(" ");
}
return infix.toString().trim();
}
// 将中缀表达式转换为后缀表达式
public List<String> infixToPostfix(List<String> tokens) {
Stack<String> operators = new Stack<>();
List<String> postfix = new ArrayList<>();
for (String token : tokens) {
if (isNumber(token)) {
postfix.add(token);
} else if (isOperator(token)) {
while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(token)) {
postfix.add(operators.pop());
}
operators.push(token);
} else if (token.equals("(")) {
operators.push(token);
} else if (token.equals(")")) {
while (!operators.isEmpty() && !operators.peek().equals("(")) {
postfix.add(operators.pop());
}
if (!operators.isEmpty() && operators.peek().equals("(")) {
operators.pop();
}
}
}
while (!operators.isEmpty()) {
postfix.add(operators.pop());
}
return postfix;
}
// 计算后缀表达式的值
public double evaluatePostfix(List<String> tokens) {
Stack<Double> stack = new Stack<>();
for (String token : tokens) {
if (isNumber(token)) {
stack.push(Double.parseDouble(token));
} else if (isOperator(token)) {
double b = stack.pop();
double a = stack.pop();
switch (token) {
case "+":
stack.push(a + b);
break;
case "-":
stack.push(a - b);
break;
case "*":
stack.push(a * b);
break;
case "/":
stack.push(a / b);
break;
}
}
}
return stack.pop();
}
}
验证
public static void main(String[] args) {
String expression = "3.5 + 4 * (2 - 1.5) / 2";
ExpressionTokenizer expressionTokenizer = new ExpressionTokenizer();
List<String> tokens = expressionTokenizer.tokenize(expression);
ExpressionHandler expressionHandler = new ExpressionHandler();
if (expressionHandler.validateSyntax(tokens)) {
System.out.println("The expression is syntactically correct.");
} else {
System.out.println("The expression is syntactically incorrect.");
}
System.out.println(expressionHandler.tokensToInfix(tokens));
List<String> postfixTokens = expressionHandler.infixToPostfix(tokens);
System.out.println("Postfix tokens: " + postfixTokens);
double v = expressionHandler.evaluatePostfix(postfixTokens);
System.out.println("result=" + v);
}