最简单却又极具扩展性的Java表达式引擎,自创编程语言必备

这个表达式引擎只有短短的100多行,却能实现包括加减乘除、括号优先级在内的运算,可以在“处理表达式”函数中自行扩展想要处理的算法。这里面算法的难点主要在于如何实现在多级括号存在的情况下,能取出最外层的一对括号,“成对处理”函数可以广泛的应用在爬虫、数据抓取的软件中。


不多说,先上源码

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Calculate {
	private Hashtable<String, Object> 堆栈值 = new Hashtable<>();
	private int 表达式游标 = 0;

	public static List<String> 成对处理(String code, String start, String end) {
		List<String> subResult = new ArrayList<>();

		String temp = "";
		String nextLevelCode = "";
		int level = 0;
		for (char codeChar : code.toCharArray()) {
			temp += codeChar;

			if (temp.endsWith(end)) {
				level--;
				if (level == 0) {
					subResult.add(nextLevelCode.toString());
					nextLevelCode = "";
				}
			}

			if (level != 0) {
				nextLevelCode += codeChar;
			}

			if (temp.endsWith(start)) {
				level++;
			}
		}

		return subResult;
	}

	public static List<String> 前置处理(String code, String front) {
		front = front.replace("+", "\\+").replace("-", "\\-");
		return getMatchList(code, front + "[_a-zA-Z\\u4E00-\\u9FA5]+[0-9]*");
	}

	public static List<String> 后置处理(String code, String back) {
		back = back.replace("+", "\\+").replace("-", "\\-");
		return getMatchList(code, "[_a-zA-Z\\u4E00-\\u9FA5]+[0-9]*" + back);
	}

	public static List<String> 运算处理(String code, String calc) {
		calc = calc.replace("+", "\\+").replace("*", "\\*").replace("-", "\\-");
		return getMatchList(code,
				"[_a-zA-Z0-9\\u4E00-\\u9FA5]+[\\.]*[0-9]*" + calc + "[_a-zA-Z\\u4E00-\\u9FA5]*[0-9]*[\\.]*[0-9]*");
	}

	public Object 处理表达式(String 表达式) throws Exception {

		List<String> 子表达式列表 = new ArrayList();

		// 先运算括号中的内容
		子表达式列表 = 成对处理(表达式, "(", ")");
		if (子表达式列表.size() != 0) {
			for (String 子表达式 : 子表达式列表) {
				Object 子表达式值 = 处理表达式(子表达式);
				String 游标键 = "_V" + (表达式游标++);
				堆栈值.put(游标键, 子表达式值);
				表达式 = 表达式.replace("(" + 子表达式 + ")", 游标键);
			}
			return 处理表达式(表达式);
		}

		表达式 = 表达式.replace(" ", "");

		// 运算乘法
		if (表达式.contains("*"))
			子表达式列表 = 运算处理(表达式, "*");
		if (子表达式列表.size() != 0) {
			for (String 子表达式 : 子表达式列表) {
				String 乘数 = 子表达式.split("\\*")[0];
				String 被乘数 = 子表达式.split("\\*")[1];
				if (乘数.startsWith("_V"))
					乘数 = 堆栈值.get(乘数).toString();
				if (被乘数.startsWith("_V"))
					被乘数 = 堆栈值.get(被乘数).toString();
				Object 子表达式值 = Double.parseDouble(乘数) * Double.parseDouble(被乘数);
				String 游标键 = "_V" + (表达式游标++);
				堆栈值.put(游标键, 子表达式值);
				表达式 = 表达式.replace(子表达式, 游标键);
			}
			return 处理表达式(表达式);
		}

		// 运算除法
		if (表达式.contains("/"))
			子表达式列表 = 运算处理(表达式, "/");
		if (子表达式列表.size() != 0) {
			for (String 子表达式 : 子表达式列表) {
				String 乘数 = 子表达式.split("/")[0];
				String 被乘数 = 子表达式.split("/")[1];
				if (乘数.startsWith("_V"))
					乘数 = 堆栈值.get(乘数).toString();
				if (被乘数.startsWith("_V"))
					被乘数 = 堆栈值.get(被乘数).toString();
				Object 子表达式值 = Double.parseDouble(乘数) / Double.parseDouble(被乘数);
				String 游标键 = "_V" + (表达式游标++);
				堆栈值.put(游标键, 子表达式值);
				表达式 = 表达式.replace(子表达式, 游标键);
			}
			return 处理表达式(表达式);
		}

		// 运算加法
		if (表达式.contains("+"))
			子表达式列表 = 运算处理(表达式, "+");
		if (子表达式列表.size() != 0) {
			for (String 子表达式 : 子表达式列表) {
				String 乘数 = 子表达式.split("\\+")[0];
				String 被乘数 = 子表达式.split("\\+")[1];
				if (乘数.startsWith("_V"))
					乘数 = 堆栈值.get(乘数).toString();
				if (被乘数.startsWith("_V"))
					被乘数 = 堆栈值.get(被乘数).toString();
				Object 子表达式值 = Double.parseDouble(乘数) + Double.parseDouble(被乘数);
				String 游标键 = "_V" + (表达式游标++);
				堆栈值.put(游标键, 子表达式值);
				表达式 = 表达式.replace(子表达式, 游标键);
			}
			return 处理表达式(表达式);
		}

		// 运算加法
		if (表达式.contains("-"))
			子表达式列表 = 运算处理(表达式, "-");
		if (子表达式列表.size() != 0) {
			for (String 子表达式 : 子表达式列表) {
				String 乘数 = 子表达式.split("\\-")[0];
				String 被乘数 = 子表达式.split("\\-")[1];
				if (乘数.startsWith("_V"))
					乘数 = 堆栈值.get(乘数).toString();
				if (被乘数.startsWith("_V"))
					被乘数 = 堆栈值.get(被乘数).toString();
				Object 子表达式值 = Double.parseDouble(乘数) - Double.parseDouble(被乘数);
				String 游标键 = "_V" + (表达式游标++);
				堆栈值.put(游标键, 子表达式值);
				表达式 = 表达式.replace(子表达式, 游标键);
			}
			return 处理表达式(表达式);
		}

		// 如果到最后是一个变量,则直接返回变量值
		if (表达式.matches("_V[0-9]+")) {
			return 堆栈值.get(表达式).toString();
		}

		throw new Exception("无法处理的表达式:" + 表达式);
	}

	public static List<String> getMatchList(String managers, String match) {
		List<String> ls = new ArrayList<String>();
		Pattern pattern = Pattern.compile(match);
		Matcher matcher = pattern.matcher(managers);
		while (matcher.find())
			ls.add(matcher.group());
		return ls;
	}
}

测试程序:

public class Test {
	public static void main(String args[]) throws Exception{
		String 表达式="100.25+ (100 /( 25+ 12.5*2))+50/(23+(1+1))";
		System.out.println(new Calculate().处理表达式(表达式));
	}
}

输出结果:104.25

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值