130242014074+林澤民+第2次實驗
阿新 • • 發佈:2017-10-28
體系結構 ati 自己 簡易 calc 乘除 and ret scan
軟件體系結構的第二次實驗(解釋器風格與管道過濾器風格)
一、實驗目的
1.熟悉體系結構的風格的概念
2.理解和應用管道過濾器型的風格。
3、理解解釋器的原理
4、理解編譯器模型
二、實驗環境
硬件:
軟件:Python或任何一種自己喜歡的語言
三、實驗內容
1、實現“四則運算”的簡易翻譯器。
結果要求:
1)實現加減乘除四則運算,允許同時又多個操作數,如:2+3*5-6 結果是11
2)被操作數為整數,整數可以有多位
3)處理空格
4)輸入錯誤顯示錯誤提示,並返回命令狀態“CALC”
圖1 實驗結果示例
加強練習:
1、有能力的同學,可以嘗試實現賦值語句,例如x=2+3*5-6,返回x=11。(註意:要實現解釋器的功能,而不是只是顯示)
2、嘗試實現自增和自減符號,例如x++
3、采用管道-過濾器(Pipes and Filters)風格實現解釋器
圖2 管道-過濾器風格
圖 3 編譯器模型示意圖
本實驗,實現的是詞法分析和語法分析兩個部分。
四、實驗步驟:
代碼如下:
- import java.util.ArrayList;
- import java.util.LinkedList;
- import java.util.Scanner;
- /**
- * @author 林澤民
- * 實現“四則運算”的簡易翻譯器。
- */
- public class Calculator {
- private static boolean rightFormat = true;
- public static double getResult(String formula){
- //處理空格
- formula=formula.replaceAll(" ", "");
- double returnValue = 0;
- returnValue = doAnalysis(formula);
- if(!rightFormat){
- throw new NumberFormatException();
- }
- return returnValue;
- }
- //解析字符串函數
- private static double doAnalysis(String formula){
- double returnValue = 0;
- LinkedList<Integer> stack = new LinkedList<Integer>();
- int curPos = 0;
- String beforePart = "";
- String afterPart = "";
- String calculator = "";
- rightFormat = true;
- //取得括號
- while(rightFormat&&(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("有未關閉的右括號!");
- rightFormat = false;
- }
- }
- curPos++;
- }
- if(stack.size() > 0){
- System.out.println("有未關閉的左括號!");
- break;
- }
- }
- if(rightFormat){
- returnValue = doCalculation(formula);
- }
- return returnValue;
- }
- //四則運算函數
- private static double doCalculation(String formula) {
- ArrayList<Double> values = new ArrayList<Double>();
- ArrayList<String> operators = new ArrayList<String>();
- int curPos = 0;
- int prePos = 0;
- int minus = 0;
- for (char s : formula.toCharArray()) {
- if ((s == ‘+‘ || s == ‘-‘ || s == ‘*‘ || s == ‘/‘) && minus !=0 && minus !=2) {
- //將數字分離出來放在double類型裏面
- values.add(Double.parseDouble(formula.substring(prePos, curPos).trim()));
- operators.add("" + s);
- prePos = curPos + 1;
- minus = minus +1;
- }else{
- minus =1;
- }
- curPos++;
- }
- //去掉前後空格
- values.add(Double.parseDouble(formula.substring(prePos).trim()));
- char op;
- //下面是從容器中取出數字進行運算
- for (curPos = 0; curPos <= operators.size() - 1; 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);
- curPos = -1;
- break;
- case ‘/‘:
- values.add(curPos, values.get(curPos) / values.get(curPos + 1));
- values.remove(curPos + 1);
- values.remove(curPos + 1);
- operators.remove(curPos);
- curPos = -1;
- break;
- }
- }
- for (curPos = 0; curPos <= operators.size() - 1; 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);
- curPos = -1;
- break;
- case ‘-‘:
- values.add(curPos, values.get(curPos) - values.get(curPos + 1));
- values.remove(curPos + 1);
- values.remove(curPos + 1);
- operators.remove(curPos);
- curPos = -1;
- break;
- }
- }
- return values.get(0).doubleValue();
- }
- //主函數
- public static void main(String[] args) {
- String str;
- Scanner scan = new Scanner(System.in);
- while (true){
- System.out.print("calc > ");
- str=scan.nextLine();
- try{
- System.out.println(getResult(str));
- }catch(NumberFormatException exc){
- System.out.println("格式輸入有誤,請重新輸入!");
- }
- }
- }
- }
結果如下:
對應結構圖:
130242014074+林澤民+第2次實驗