1. 程式人生 > >130242014074+林澤民+第2次實驗

130242014074+林澤民+第2次實驗

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

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

四、實驗步驟:

 代碼如下:

  1. import java.util.ArrayList;
  2. import java.util.LinkedList;
  3. import java.util.Scanner;
  4. /**
  5. * @author 林澤民
  6. * 實現“四則運算”的簡易翻譯器。
  7. */
  8. public class Calculator {
  9. private static boolean rightFormat = true;
  10. public static double getResult(String formula){
  11. //處理空格
  12. formula=formula.replaceAll(" ", "");
  13. double returnValue = 0;
  14. returnValue = doAnalysis(formula);
  15. if(!rightFormat){
  16. throw new NumberFormatException();
  17. }
  18. return returnValue;
  19. }
  20. //解析字符串函數
  21. private static double doAnalysis(String formula){
  22. double returnValue = 0;
  23. LinkedList<Integer> stack = new LinkedList<Integer>();
  24. int curPos = 0;
  25. String beforePart = "";
  26. String afterPart = "";
  27. String calculator = "";
  28. rightFormat = true;
  29. //取得括號
  30. while(rightFormat&&(formula.indexOf(‘(‘) >= 0||formula.indexOf(‘)‘) >= 0)){
  31. curPos = 0;
  32. for(char s : formula.toCharArray()){
  33. if(s == ‘(‘){
  34. stack.add(curPos);
  35. }else if(s == ‘)‘){
  36. if(stack.size() > 0){
  37. beforePart = formula.substring(0, stack.getLast());
  38. afterPart = formula.substring(curPos + 1);
  39. calculator = formula.substring(stack.getLast() + 1, curPos);
  40. formula = beforePart + doCalculation(calculator) + afterPart;
  41. stack.clear();
  42. break;
  43. }else{
  44. System.out.println("有未關閉的右括號!");
  45. rightFormat = false;
  46. }
  47. }
  48. curPos++;
  49. }
  50. if(stack.size() > 0){
  51. System.out.println("有未關閉的左括號!");
  52. break;
  53. }
  54. }
  55. if(rightFormat){
  56. returnValue = doCalculation(formula);
  57. }
  58. return returnValue;
  59. }
  60. //四則運算函數
  61. private static double doCalculation(String formula) {
  62. ArrayList<Double> values = new ArrayList<Double>();
  63. ArrayList<String> operators = new ArrayList<String>();
  64. int curPos = 0;
  65. int prePos = 0;
  66. int minus = 0;
  67. for (char s : formula.toCharArray()) {
  68. if ((s == ‘+‘ || s == ‘-‘ || s == ‘*‘ || s == ‘/‘) && minus !=0 && minus !=2) {
  69. //將數字分離出來放在double類型裏面
  70. values.add(Double.parseDouble(formula.substring(prePos, curPos).trim()));
  71. operators.add("" + s);
  72. prePos = curPos + 1;
  73. minus = minus +1;
  74. }else{
  75. minus =1;
  76. }
  77. curPos++;
  78. }
  79. //去掉前後空格
  80. values.add(Double.parseDouble(formula.substring(prePos).trim()));
  81. char op;
  82. //下面是從容器中取出數字進行運算
  83. for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
  84. op = operators.get(curPos).charAt(0);
  85. switch (op) {
  86. case ‘*‘:
  87. values.add(curPos, values.get(curPos) * values.get(curPos + 1));
  88. values.remove(curPos + 1);
  89. values.remove(curPos + 1);
  90. operators.remove(curPos);
  91. curPos = -1;
  92. break;
  93. case ‘/‘:
  94. values.add(curPos, values.get(curPos) / values.get(curPos + 1));
  95. values.remove(curPos + 1);
  96. values.remove(curPos + 1);
  97. operators.remove(curPos);
  98. curPos = -1;
  99. break;
  100. }
  101. }
  102. for (curPos = 0; curPos <= operators.size() - 1; curPos++) {
  103. op = operators.get(curPos).charAt(0);
  104. switch (op) {
  105. case ‘+‘:
  106. values.add(curPos, values.get(curPos) + values.get(curPos + 1));
  107. values.remove(curPos + 1);
  108. values.remove(curPos + 1);
  109. operators.remove(curPos);
  110. curPos = -1;
  111. break;
  112. case ‘-‘:
  113. values.add(curPos, values.get(curPos) - values.get(curPos + 1));
  114. values.remove(curPos + 1);
  115. values.remove(curPos + 1);
  116. operators.remove(curPos);
  117. curPos = -1;
  118. break;
  119. }
  120. }
  121. return values.get(0).doubleValue();
  122. }
  123. //主函數
  124. public static void main(String[] args) {
  125. String str;
  126. Scanner scan = new Scanner(System.in);
  127. while (true){
  128. System.out.print("calc > ");
  129. str=scan.nextLine();
  130. try{
  131. System.out.println(getResult(str));
  132. }catch(NumberFormatException exc){
  133. System.out.println("格式輸入有誤,請重新輸入!");
  134. }
  135. }
  136. }
  137. }

結果如下:

技術分享

對應結構圖:

技術分享

130242014074+林澤民+第2次實驗