1. 程式人生 > >130242014076+陳旭+第2次實驗

130242014076+陳旭+第2次實驗

es2017 體系 空格 實現 -1 sta move more logs

軟件體系結構的第二次實驗(解釋器風格與管道過濾器風格)

一、實驗目的

  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 編譯器模型示意圖

  本實驗,實現的是詞法分析和語法分析兩個部分。

四、實驗步驟:

 代碼如下:

  1 package com.brainstrong.uamis.util;
2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.Scanner; 7 import java.util.StringTokenizer; 8 9 /** 10 * JAVA實現四則運算解釋器 11 * 12 * @author 旭旭 13 * @create 2017-10-27 19:43 14 **/ 15 public class Calc { 16 17 public
static void main(String[] args) { 18 Scanner scanner = new Scanner(System.in); 19 String exp = scanner.nextLine(); 20 System.out.println(calc(exp)); 21 } 22 23 /** 24 * 25 * @param exp 四則表達式 26 * @return 27 */ 28 public static double calc(String exp){ 29 //1.把表示負數的-號換成@號 30 exp = negativeToAtChar(exp); 31 //2.數字的分類 32 List<Double> numbers = splitNumExp(exp); 33 //3.運算符的分離 34 List<Character> ops = splitOpfromExp(exp); 35 //4.先乘除 36 for (int i = 0; i < ops.size(); i++) { 37 //判斷,運算符是否是乘除 38 char op = ops.get(i); 39 //是,取出,運算 40 if (op == ‘*‘ || op == ‘/‘) { 41 //取出來,運算 42 ops.remove(i);//後面的數據往前順序移動 43 //運算 44 //從數字容器中取出對應運算符的兩個數字 45 double d1 = numbers.remove(i); 46 double d2 = numbers.remove(i); 47 48 if (op == ‘*‘) { 49 d1 *= d2; 50 }else { 51 d1 /= d2; 52 } 53 54 //把運算結果放入數字容器中i的位置 55 numbers.add(i, d1);//原來i位置(包括)後面的數據依次往後順移 56 i--; 57 } 58 } 59 //5.後加減 60 while (!ops.isEmpty() ) { 61 char op = ops.remove(0); 62 double d1 = numbers.remove(0); 63 double d2 = numbers.remove(0); 64 //運算 65 if (op == ‘+‘) { 66 d1 += d2; 67 } else { 68 d1 -= d2; 69 } 70 //把運算結果插入到數字容器中0的位置 71 numbers.add(0, d1); 72 } 73 //6.容器中的第一個數據就是結果 74 return numbers.get(0); 75 } 76 77 /** 78 * 從表達式中分離表達式和運算符 79 * @param exp 80 * @return 81 */ 82 private static List<Character> splitOpfromExp(String exp) { 83 List<Character> ops = new ArrayList<Character>(); 84 StringTokenizer st = new StringTokenizer(exp, "1234567890.@"); 85 while (st.hasMoreTokens()) { 86 char c = st.nextElement().toString().trim().charAt(0); 87 ops.add(c); 88 } 89 return ops; 90 } 91 92 /** 93 * 分離出數字 94 * @param exp 95 * @return 96 */ 97 private static List<Double> splitNumExp(String exp) { 98 List<Double> numbers = new ArrayList<Double>(); 99 StringTokenizer st = new StringTokenizer(exp, "+-*/"); 100 while (st.hasMoreTokens()) { 101 String numStr = st.nextElement().toString().trim(); 102 if (numStr.charAt(0) == ‘@‘) { 103 numStr = "-" + numStr.substring(1); 104 } 105 numbers.add(Double.parseDouble(numStr)); 106 } 107 return numbers; 108 } 109 110 /** 111 * 把-號換成@號 112 * @param exp 113 * @return 114 */ 115 private static String negativeToAtChar(String exp) { 116 for (int i = 0; i < exp.length(); i++) { 117 char c = exp.charAt(i); 118 if (c == ‘-‘) { 119 //判斷是否是負數 120 if (i == 0) { 121 //第一個位置肯定是負數 122 exp = "@"+exp.substring(1); 123 }else { 124 //不是第一個位置 125 //判斷前一個位置是否是運算符 126 char cprev = exp.charAt(i - 1); 127 if (cprev == ‘+‘ || cprev == ‘-‘ || cprev == ‘*‘ || cprev == ‘/‘) { 128 exp = exp.substring(0, i)+"@"+exp.substring(i+1); 129 } 130 } 131 } 132 } 133 return exp; 134 } 135 136 }

技術分享

130242014076+陳旭+第2次實驗