package org.nutz.el.arithmetic;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import org.nutz.el.ElCache;
import org.nutz.el.Operator;
import org.nutz.el.obj.IdentifierObj;
import org.nutz.lang.util.Context;
/**
* 逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。<br/>
* 参考:<a href="http://zh.wikipedia.org/wiki/%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E7%A4%BA%E6%B3%95">逆波兰表达式</a>
*
* @author juqkai(juqkai@gmail.com)
*
*/
public class RPN {
//存放context
private final ElCache ec = new ElCache();
//预编译后的对象
private Deque<Object> el;
public RPN() {}
/**
* 进行EL的预编译
*/
public RPN(Queue<Object> rpn) {
compile(rpn);
}
/**
* 执行已经预编译的EL
*/
public Object calculate(Context context){
ec.setContext(context);
return calculate(el);
}
/**
* 根据逆波兰表达式进行计算
*/
public Object calculate(Context context, Queue<Object> rpn) {
ec.setContext(context);
Deque<Object> operand = OperatorTree(rpn);
return calculate(operand);
}
/**
* 计算
*/
private Object calculate(Deque<Object> el2){
if(el2.peek() instanceof Operator){
Operator obj = (Operator) el2.peek();
return obj.calculate();
}
if(el2.peek() instanceof IdentifierObj){
return ((IdentifierObj) el2.peek()).fetchVal();
}
return el2.peek();
}
/**
* 预先编译
*/
public void compile(Queue<Object> rpn){
el = OperatorTree(rpn);
}
/**
* 转换成操作树
*/
private Deque<Object> OperatorTree(Queue<Object> rpn){
Deque<Object> operand = new LinkedList<Object>();
while(!rpn.isEmpty()){
if(rpn.peek() instanceof Operator){
Operator opt = (Operator) rpn.poll();
opt.wrap(operand);
operand.addFirst(opt);
continue;
}
if(rpn.peek() instanceof IdentifierObj){
((IdentifierObj) rpn.peek()).setEc(ec);
}
operand.addFirst(rpn.poll());
}
return operand;
}
}