前言
在工作中,由于需要,想在前端页面上实现一些逻辑,为了功能更强大一些,所以想着自己开发一个简单的编程语言,前端在文本框中即可实现自己的逻辑。
思路
使用字符串接收代码块,通过,正则表达式,实现拆分。
将代码分为4个部分:
- 操作数:
- 变量:以下划线开头,支持大小写,例:“_age”。
- 数据:目前仅支持整型和布尔数据,例:“12”、“true”、“false”。
- 操作符:支持+ - * / = > < 操作符,赋值用“~”表示。
- 分句符:使用“;”分割语句。
- 控制语句:目前支持IF语句,用“if 变量 then 操作”表示。
具体实现
依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
操作数和操作符实体
// 操作数
@Data
public class Operand {
private int index;
private String variable; // 变量名
private boolean isVar; // 是否为变量
private String value; // 值
}
// 操作符
@Data
public class Operator {
private Operand previous; // 前一个操作数
private Operand next; // 后一个操作数
private int index; //
private String var; // 操作符
private int priority; // 优先级
}
核心处理
public class Core {
// 自定义参数
static Map<String, String> map = new HashMap<>();
static String varStr = "[^+\\-*/?:~=><]+";
static String varOperator = "[+\\-*/?:~=><]";
// 新语言计算入口
public static void total(String text){
// 清除空字符
text = text.replaceAll("\\s","");
String[] split = text.split(";");
for (String SingleStatement : split) {
if (SingleStatement.contains("if")){
ifThen(SingleStatement);
}else {
simpleCompile(SingleStatement);
}
}
System.out.println(map);
map.clear();
}
// 分离操作数
private static List<Operand> separateOperand(String text) {
List<Operand> list = new ArrayList<>();
Pattern pattern = Pattern.compile(varStr);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
Operand operand = new Operand();
String str = matcher.group();
operand.setVariable(str);
boolean isVar = str.contains("_");
operand.setVar(isVar);
// 将变量放入map中管理
if (isVar){
String value = map.get(str);
if (value == null) {
map.put(str,null);
}else {
operand.setValue(value);
}
}else {
operand.setValue(str);
}
list.add(operand);
}
return list;
}
// 分离操作符
private static List<Operator> separateOperator(String text, List<Operand> operandList) {
List<Operator> list = new ArrayList<>();
Pattern pattern = Pattern.compile(varOperator);
Matcher matcher = pattern.matcher(text);
int i = 0;
while (matcher.find()) {
Operator operator = new Operator();
operator.setPrevious(operandList.get(i));
operator.setNext(operandList.get(i + 1));
operator.setIndex(i);
operator.setVar(matcher.group());
operator.setPriority(getPriority(matcher.group()));
list.add(operator);
i++;
}
return list;
}
// 获得优先级
private static int getPriority(String operator) {
if (operator.matches("[*/]")) {
return 1;
} else if (operator.matches("[+\\-]")) {
return 2;
} else if (operator.matches("[=><]")) {
return 3;
} else if (operator.matches("[~]")) {
return 4;
} else {
return 9999;
}
}
// 单个操作符计算
private static String doSome(Operator operator) {
String var = operator.getVar();
String previous = operator.getPrevious().getValue();
String next = operator.getNext().getValue();
String result = "";
if ("*".equals(var)) {
result = String.valueOf(Integer.valueOf(previous) * Integer.valueOf(next));
} else if ("/".equals(var)) {
result = String.valueOf(Integer.valueOf(previous) / Integer.valueOf(next));
} else if ("+".equals(var)) {
result = String.valueOf(Integer.valueOf(previous) + Integer.valueOf(next));
} else if ("-".equals(var)) {
result = String.valueOf(Integer.valueOf(previous) - Integer.valueOf(next));
}else if ("~".equals(var)){
// 将后一个操作数的值赋予前一个操作数
operator.getPrevious().setValue(operator.getNext().getValue());
// 更新map
map.put(operator.getPrevious().getVariable(),operator.getPrevious().getValue());
}else if ("=".equals(var)){
result = previous.equals(next)?"true":"false";
}else if (">".equals(var)){
result = Integer.valueOf(previous) > Integer.valueOf(next)?"true":"false";
}else if ("<".equals(var)){
result = Integer.valueOf(previous) < Integer.valueOf(next)?"true":"false";
}
return result;
}
// 操作符计算
private static String compute(List<Operator> list) {
// 根据优先级计算
for (int i = 1; i <= 4; i++) {
Iterator<Operator> iterator = list.iterator();
while (iterator.hasNext()) {
Operator operator = iterator.next();
if (operator.getPriority() == i) {
// 计算该操作符计算后的值
String value = doSome(operator);
// 获得前后index注意0和last
int index = list.indexOf(operator);
// 将该操作符的值赋予前后操作符
if (index > 0){
list.get(index-1).getNext().setValue(value);
}
if (index<list.size()-1){
list.get(index+1).getPrevious().setValue(value);
}
iterator.remove();
if (list.size() == 0) {
return value;
}
}
}
}
return null;
}
// 简单计算,不包含if语句
private static String simpleCompile(String text){
List<Operand> operandList = separateOperand(text);
List<Operator> operatorList = separateOperator(text, operandList);
// 当只有一个值时
if (operatorList.size()==0){
return operandList.get(0).getValue();
}
String result = compute(operatorList);
return result;
}
// if then 处理
private static void ifThen(String text){
Pattern pattern = Pattern.compile("[^(if|then)]+");
Matcher matcher = pattern.matcher(text);
int i = 0;
String result = null;
while (matcher.find()){
if (i == 0){
result = simpleCompile(matcher.group());
}else {
if ("true".equals(result)){
simpleCompile(matcher.group());
}
}
i++;
}
}
}
测试
public class Test {
public static void main(String[] args) {
Core.total("_a~2*3<10;if _a then _b~10");
// {_a=true, _b=10}
}
}