130242014053+吴帮莉+第二次实验

软件体系结构的第二次实验(解释器风格与管道过滤器风格)

一、实验目的

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++ 

2、采用管道-过滤器(Pipes and Filters)风格实现解释器

                        图2  管道-过滤器风格

                     图 3  编译器模型示意图

本实验,实现的是词法分析和语法分析两个部分。

四、实验步骤:

代码示例:

import java.math.BigDecimal;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* @author wubangli
*
*/
public class CalculatorUtil {

  /**
  * @param args
  */
  @SuppressWarnings("finally")
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    CalculatorUtil calt = new CalculatorUtil();
    Scanner reader = new Scanner(System.in);
    int i = 1;
    while (i == 1) {
      int sum = 0;
      System.out.print("calt> ");
      String str = reader.nextLine();
      str = str.replaceAll(" ", "");
      try{
        sum = calt.arithmetic(str);
        System.out.println(sum);
      }finally{
        if(sum==0)
          System.out.println("输入异常,请重新输入!");
        continue;
      }
    }

  }

  public static Integer arithmetic(String exp) {
    if (!exp.matches("\\d+")) {
      String result = parseExp(exp).replaceAll("[\\[\\]]", "");
      return new Integer(result);
    } else {
      return new Integer(exp);
    }
  }

  // 最小计数单位
  private static String minExp = "^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$";

  // 不带括号的运算
  private static String noParentheses = "^[^\\(\\)]+$";

  // 匹配乘法或者除法
  private static String priorOperatorExp = "(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))";

  // 匹配加法和减法
  private static String operatorExp = "(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))";

  // 匹配只带一个括号的
  private static String minParentheses = "\\([^\\(\\)]+\\)";

  /**
  * @param expression
  * @return
  */
  private static String parseExp(String expression) {
    // 方法进入 先替换空格,在去除运算两边的()号
    expression = expression.replaceAll("\\s+", "").replaceAll("^\\(([^\\(\\)]+)\\)$", "$1");

    // 最小表达式计算
    if (expression.matches(minExp)) {
      String result = calculate(expression);
      return Double.parseDouble(result) >= 0 ? result : "[" + result+ "]";
    }

    // 计算不带括号的四则运算
    if (expression.matches(noParentheses)) {
      Pattern patt = Pattern.compile(priorOperatorExp);
      Matcher mat = patt.matcher(expression);

      if (mat.find()) {
        String tempMinExp = mat.group();
        expression = expression.replaceFirst(priorOperatorExp,parseExp(tempMinExp));
      } else {
        patt = Pattern.compile(operatorExp);
        mat = patt.matcher(expression);

        if (mat.find()) {
          String tempMinExp = mat.group();
          expression = expression.replaceFirst(operatorExp,parseExp(tempMinExp));
        }
      }
      return parseExp(expression);
    }

    // 计算带括号的四则运算
    Pattern patt = Pattern.compile(minParentheses);
    Matcher mat = patt.matcher(expression);
    if (mat.find()) {
      String tempMinExp = mat.group();
      expression = expression.replaceFirst(minParentheses,parseExp(tempMinExp));
    }
    return parseExp(expression);
   }

  /**
  * 计算最小单位四则运算表达式(两个数字)
  *
  * @param exp
  * @return
  */
  private static String calculate(String exp) {
    exp = exp.replaceAll("[\\[\\]]", "");
    String number[] = exp.replaceFirst("(\\d)[\\+\\-\\*\\/]", "$1,").split(",");
    BigDecimal number1 = new BigDecimal(number[0]);
    BigDecimal number2 = new BigDecimal(number[1]);
    BigDecimal result = null;

    String operator = exp.replaceFirst("^.*\\d([\\+\\-\\*\\/]).+$", "$1");
    if ("+".equals(operator)) {
      result = number1.add(number2);
    } else if ("-".equals(operator)) {
      result = number1.subtract(number2);
    } else if ("*".equals(operator)) {
      result = number1.multiply(number2);
    } else if ("/".equals(operator)) {
      // 第二个参数为精度,第三个为四色五入的模式
      result = number1.divide(number2, 5, BigDecimal.ROUND_CEILING);
    }

    return result != null ? result.toString() : null;
  }

}

 

 

五、实验总结

       通过实际编写解释器,我对体系结构模式的应用有了初步的了解。软件体系结构在软件开发的各个阶段都起到了十分重要的作用。它不但可以控制软件的复杂性和提供高层次的复用,而且作为工程计划的前期工作软件体系结构可以使开发者更早的从全局考虑关键性设计问题从而保持整个整个软件系统的一致性。

 

参考资料:http://www.doc88.com/p-993974142440.html

                http://www.jb51.net/article/71487.htm

posted @ 2017-10-28 23:15  鼹鼠的故事  阅读(193)  评论(0编辑  收藏  举报