130242014039-刘鑫-第2次实验
一、实验目的
1.熟悉体系结构的风格的概念
2.理解和应用管道过滤器型的风格。
3、理解解释器的原理
4、理解编译器模型
二、实验环境
硬件:
软件:Python或任何一种自己喜欢的语言
三、实验内容
1、实现“四则运算”的简易翻译器。
结果要求:
1)实现加减乘除四则运算,允许同时又多个操作数,如:2+3*5-6 结果是11
2)被操作数为整数,整数可以有多位
3)处理空格
4)输入错误显示错误提示,并返回命令状态“CALC”
加强练习:
1、有能力的同学,可以尝试实现赋值语句,例如x=2+3*5-6,返回x=11。(注意:要实现解释器的功能,而不是只是显示)
2、尝试实现自增和自减符号,例如x++
2、采用管道-过滤器(Pipes and Filters)风格实现解释器
图2 管道-过滤器风格
图 3 编译器模型示意图
本实验,实现的是词法分析和语法分析两个部分。
package fjnu.test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
public class ExpressionToDouble {
private boolean isRightFormat = true;
public double getResult(String formula) {
double returnValue = 0;
try {
returnValue = doAnalysis(formula);
} catch (NumberFormatException nfe) {
System.out.println("公式格式有误,请检查:" + formula);
} catch (Exception e) {
e.printStackTrace();
}
if (!isRightFormat) {
System.out.println("公式格式有误,请检查:" + formula);
}
return returnValue;
}
private double doAnalysis(String formula) {
double returnValue = 0;
LinkedList<Integer> stack = new LinkedList<Integer>();
int curPos = 0;
String beforePart = "";
String afterPart = "";
String calculator = "";
isRightFormat = true;
while (isRightFormat
&& (formula.indexOf('(') >= 0 || formula.indexOf(')') >= 0)) {
curPos = 0;
for (char s : formula.toCharArray()) {
if (s == '(') {
stack.add(curPos);
} else if (s == ')') {
if (stack.size() > 0) {
beforePart = formula.substring(0, stack.getLast());
afterPart = formula.substring(curPos + 1);
calculator = formula.substring(stack.getLast() + 1,
curPos);
formula = beforePart + doCalculation(calculator)
+ afterPart;
stack.clear();
break;
} else {
System.out.println("有未关闭的右括号!");
isRightFormat = false;
}
}
curPos++;
}
if (stack.size() > 0) {
System.out.println("有未关闭的左括号!");
break;
}
}
if (isRightFormat) {
returnValue = doCalculation(formula);
}
return returnValue;
}
private double doCalculation(String formula) {
ArrayList<Double> values = new ArrayList<Double>();
ArrayList<String> operators = new ArrayList<String>();
int curPos = 0;
int prePos = 0;
for (char s : formula.toCharArray()) {
if (s == '+' || s == '-' || s == '*' || s == '/') {
values.add(Double.parseDouble(formula.substring(prePos, curPos)
.trim()));
operators.add("" + s);
prePos = curPos + 1;
}
curPos++;
}
values.add(Double.parseDouble(formula.substring(prePos).trim()));
char op;
for (curPos = operators.size() - 1; curPos >= 0; curPos--) {
op = operators.get(curPos).charAt(0);
switch (op) {
case '*':
values.add(curPos, values.get(curPos) * values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
case '/':
values.add(curPos, values.get(curPos) / values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
}
}
for (curPos = operators.size() - 1; curPos >= 0; curPos--) {
op = operators.get(curPos).charAt(0);
switch (op) {
case '+':
values.add(curPos, values.get(curPos) + values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
case '-':
values.add(curPos, values.get(curPos) - values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
}
}
return values.get(0).doubleValue();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str;
while (true) {
System.out.print("calc > ");
str = scanner.nextLine();
System.out.println(new ExpressionToDouble().getResult(str));
}
}
}