1.意图
              给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用
               该表示来解释语言中的句子。
          2.参与者
          Abstract -(抽象表达式)声明一个抽象的解释操作,这个接口为
                                                                抽象语法树中所有节点所共享
          Termind  (终结符表达式) -实现与文法中的终结符相关联的解释操作
          Nonterminal (非终结符)-文法中的每一条规则都需要一个Nonterminal 类         
                                           -为文法中的非终结符实现解释操作
           Context - 包含解释器之外的一些全局信息
           Client  - 构建抽象语法树 -调用解释操作

   3.结构

\"\"

4.代码结构

public interface Abstract  {
	Termind  Evaluate();//执行表达式
	void add (Abstract   );//添加子表达式
	void addSymbol(String str);//添加符号
	String getSymbol();//获取符号
	void setFather(Abstract   );//设置父节点
	Abstract  getFather();//获取父节点
	int getLevel();//获取优先级
	Abstract  remove();//移除一个子表达式
}

public class Nonterminal KH implements Abstract  {
	private String symbol = \"\";
    private Termind  value;
    private Abstract   ;
    private Abstract  f ;
	@Override
	public Termind  Evaluate() {
		if(\"()\".equals(symbol) ||   != null){
			value =  .Evaluate();
		}
		if(\"(\".equals(symbol)){
			throw new RuntimeException(\"括号不匹配\");
		}
		return value;
	}	
	public Termind  getValue() {
		return value;
	}

	public void setValue(Termind  value) {
		this.value = value;
	}

	@Override
	public void add (Abstract   ) {
		this.  =  ;		
	}

	@Override
	public void setFather(Abstract   ) {
		this.f  =  ;
		
	}

	@Override
	public Abstract  getFather() {
		return f ;
	}

	@Override
	public int getLevel() {
		// TODO Auto-generated method stub
		return -1;
	}

	@Override
	public void addSymbol(String str) {
		symbol += str;

	}

	@Override
	public String getSymbol() {
		return symbol;
	}
	@Override
	public Abstract  remove() {
		Abstract    = this. ;
		this.  = null;
		return  ;
	}

}

public class Nonterminal One implements Abstract  {
	private String symbol = \"\";
	private int level;
	private Termind  value;
	private Abstract   ;
	private Abstract  f ;
	Nonterminal One(String symbol,int level){
		this.level = level;
		this.symbol = symbol;
	}
	@Override
	public Termind  Evaluate() {
		if (  != null) {
			value =  .Evaluate();
		}else{
			throw new RuntimeException(\"一元表达式没有数值\");
		}
		
		return Calculate.One(symbol, value);
	}

	public Termind  getValue() {
		return value;
	}

	public void setValue(Termind  value) {
		this.value = value;
	}

	@Override
	public void add (Abstract   ) {
		this.  =  ;
	}

	@Override
	public void setFather(Abstract   ) {
		this.f  =  ;

	}

	@Override
	public Abstract  getFather() {
		return f ;
	}

	@Override
	public int getLevel() {
		// TODO Auto-generated method stub
		return level;
	}

	@Override
	public void addSymbol(String str) {
		symbol += str;

	}

	@Override
	public String getSymbol() {
		return symbol;
	}
	@Override
	public Abstract  remove() {
		Abstract    = this. ;
		this.  = null;
		return  ;
	}

}

public class Nonterminal Two implements Abstract  {
	private String symbol;
	private Termind  value1;
	private Termind  value2;
	private List<Abstract >  List;
	private Abstract  f ;
	private int level ;
	Nonterminal Two(String symbol,int level){
		this.level = level;
		this.symbol = symbol;
	}
	@Override
	public Termind  Evaluate() {
		if ( List != null &&  List.size() > 0) {
			if (value1 == null) {
				value1 =  List.get(0).Evaluate();
			}
			if (value2 == null) {
				value2 =  List.get(1).Evaluate();
			}
		}
		return Calculate.two(symbol, value1, value2);
	}
	public Termind  getValue1() {
		return value1;
	}

	public void setValue1(Termind  value1) {
		this.value1 = value1;
	}

	public Termind  getValue2() {
		return value2;
	}

	public void setValue2(Termind  value2) {
		this.value2 = value2;
	}

	@Override
	public void add (Abstract   ) {
		if ( List == null) {
			 List = new ArrayList<Abstract >(2);
		}
		 List.add( );

	}

	@Override
	public void setFather(Abstract   ) {
		this.f  =  ;
		
	}

	@Override
	public Abstract  getFather() {
		return f ;
	}

	@Override
	public int getLevel() {
		return level;
	}
	@Override
	public void addSymbol(String str) {
		symbol += str;

	}

	@Override
	public String getSymbol() {
		return symbol;
	}
	@Override
	public Abstract  remove() {
		Abstract     =  List.get( List.size()-1);
		 List.remove( );
		return  ;
	}
}

public class Termind  implements Abstract  {
	private Abstract  f ;
	private double value;
	private int level ;
	Termind (double value) {
		this.value = value;
	}
	@Override
	public Termind  Evaluate() {
		return this;
	}
    
	public double getValue() {
		return value;
	}

	public void setValue(double value) {
		this.value = value;
	}

	@Override
	public void add (Abstract   ) {
		throw new RuntimeException(\"终结符没子表达式\");
	}

	public void setFather(Abstract   ) {
		this.f  =  ;
		
	}

	@Override
	public Abstract  getFather() {
		return f ;
	}

	@Override
	public int getLevel() {
		return 0;
	}

	@Override
	public void addSymbol(String str) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String getSymbol() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Abstract  remove() {
		// TODO Auto-generated method stub
		return null;
	}

}

public class Context {
	private Pattern pattern = Pattern.compile(\"-?[0-9]+.?[0-9]*\");// 数字定义为零元表达式可以直接获取结果
	private String One = \"sin cos tan !\";// 一元表达式
	private String left = \"!\";
	private String Two = \"+ - * / ^\";// 二元表达式
	private String khbegain = \"(\";// 双符号表达式的开始符号只指向一个表达式定义为一个表达式的开始
	private String khEnd = \")\";// 双符号表达式结束符号
	private final static Context context = new Context();

	private Context() {
	}

	public static Context Instance() {
		return context;
	}

	public boolean getCompass(String str) {
		if (left.contains(str)) {
			return true;
		}
		return false;
	}

	/**
	 * 获取符号的类别
	 * 
	 * @param str
	 *            符号
	 * @return
	 */
	public int getClass(String str) {
		if (str == null) {
			return -1;
		}
		if (pattern.matcher(str).matches()) {
			return 0;
		}
		if (One.contains(str)) {
			return 1;
		}
		if (Two.contains(str)) {
			return 2;
		}
		if (khbegain.contains(str)) {
			return 3;
		}
		if (khEnd.contains(str)) {
			return 4;
		}
		return -1;
	}

	private String fiveLevel = \"sin cos tan \";
	private String fourLevel = \"^\";
	private String threeLevel = \"!\";
	private String TwoLevel = \"* /\";
	private String OneLevel = \"+ -\";

	/**
	 * 获取优先级 数字越大优先级越大
	 * 
	 * @param str
	 *            符号
	 * @return
	 */
	public int getLevel(String str) {
		if (OneLevel.contains(str)) {
			return 1;
		}
		if (TwoLevel.contains(str)) {
			return 2;
		}
		if (threeLevel.contains(str)) {
			return 3;
		}
		if (fourLevel.contains(str)) {
			return 4;
		}
		if (fiveLevel.contains(str)) {
			return 5;
		}
		return 0;
	}
}

public class Calculate {
	private Calculate() {
		throw new RuntimeException();
	}
    /**
     * 一元表达式计算
     * @param symbol
     * @param T
     * @return
     */
	public static Termind  One(String symbol, Termind  T) {
		Termind  result = null;
		double k = 0;
		if (\"sin\".equals(symbol)) {
             k = Math.sin(T.getValue());
             result = new Termind (k);
		} else if (\"cos\".equals(symbol)) {
			 k = Math.cos(T.getValue());
             result = new Termind (k);
		} else if (\"tan\".equals(symbol)) {
			 k = Math.tan(T.getValue());
             result = new Termind (k);
		}if (\"!\".equals(symbol)) {
			try{
			 k = factorial(new Double(T.getValue()).intValue());
			 }catch(NumberFormatException e){
				 throw new NumberFormatException(\"阶乘只针对整数\");
			 }
             result = new Termind (k);
		}
		return result;
	}
	public static double factorial(int n){
		double result = 1;
		for(;n>1;n--){
			result = result * n;
		}
		return result;
	}
    /**
     * 二元表达式计算
     * @param symbol
     * @param T1
     * @param T2
     * @return
     */
	public static Termind  two(String symbol, Termind  T1,
			Termind  T2) {
		Termind  result = null;
		double k ;
		if (\"+\".equals(symbol)) {
			 k = T1.getValue() + T2.getValue();
			result = new Termind (k);
		} else if (\"-\".equals(symbol)) {
			 k = T1.getValue() - T2.getValue();
			result = new Termind (k);
		} else if (\"*\".equals(symbol)) {
			 k = T1.getValue() * T2.getValue();
			result = new Termind (k);
		} else if (\"/\".equals(symbol)) {
			 k = T1.getValue() / T2.getValue();
			result = new Termind (k);
		}else if (\"^\".equals(symbol)) {
			 k = Math.pow(T1.getValue(), T2.getValue());
			result = new Termind (k);
		}
		return result;
	}
}

public class Client {
	public static void main(String[] args) {
		String   = \"8 + ( 7 - 4 ! ) * ( 5 - 2 ) + ( 2.5 - 3 ) * 4\";
		// 切割表达式
		String[] elements =  .split(\" \");
		// 一次扫描构建语法树
		Abstract  Begin  = new Nonterminal KH();
		Abstract  pre  = Begin ;
		Abstract  next ;
		for (String str : elements) {
			int flag = Context.Instance().getClass(str);
			int level = Context.Instance().getLevel(str);
			switch (flag) {
			case 0:// 零元表达式的构建动作
				next  = new Termind (Double.valueOf(str));
				pre .add (next );
				next .setFather(pre );
				pre  = next ;
				next  = null;
				break;
			case 1:// 一元表达式的构建动作
				next  = new Nonterminal One(str, level);
				if (Context.Instance().getCompass(str)) {
					while (pre .getSymbol() == null) {
						pre  = pre .getFather();
					}
					Abstract  move = pre .remove();
					pre .add (next );
					next .setFather(pre );
					next .add (move);
					move.setFather(next );
					pre  = next ;
					next  = null;
				} else {

					pre .add (next );
					next .setFather(pre );
					pre  = next ;
					next  = null;
				}
				break;
			case 2:// 二元表达式的构建动作
				next  = new Nonterminal Two(str, level);
				while (pre .getSymbol() == null) {
					pre  = pre .getFather();
				}
				if (level <= pre .getLevel()) {
					if (pre .getFather() != null
							&& pre .getFather().getLevel() == level) {
						/***
						 * ( + * - )同级运算从左向右计算,调整构造数先算 * 再算+最后算-
						 * 当-的优先级低于*时,查看*的父节点+的优先级,因为+的优先级和-一样所以 +的表达式成为 -
						 * 的左表达式并且 - 替代 +表达式
						 */
						pre  = pre .getFather().getFather();
					} else {
						pre  = pre .getFather();

					}
				}
				Abstract  move = pre .remove();
				pre .add (next );
				next .setFather(pre );
				next .add (move);
				move.setFather(next );
				pre  = next ;
				next  = null;
				break;
			case 3:// 双符号元表达式的开始构建动作
				next  = new Nonterminal KH();
				next .addSymbol(str);
				pre .add (next );
				next .setFather(pre );
				pre  = next ;
				next  = null;
				break;
			case 4:// 双符号表达式的结束动作
				while (Context.Instance().getClass(pre .getSymbol()) != 3) {
					pre  = pre .getFather();
				}
				pre .addSymbol(str);
				pre  = pre .getFather();
				next  = null;
				break;
			default:
				throw new RuntimeException(\"运算符识别错误\");
			}
		}
		System.out.println(Begin .Evaluate().getValue());
	}
}

5.解释代码

收藏 打印