Package org.nutz.el.arithmetic

Source Code of org.nutz.el.arithmetic.ShuntingYard

package org.nutz.el.arithmetic;

import java.io.IOException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;

import org.nutz.el.Operator;
import org.nutz.el.opt.arithmetic.LBracketOpt;
import org.nutz.el.opt.arithmetic.RBracketOpt;
import org.nutz.el.opt.logic.QuestionOpt;
import org.nutz.el.opt.logic.QuestionSelectOpt;
import org.nutz.el.parse.Converter;

/**
* Shunting yard算法是一个用于将中缀表达式转换为后缀表达式的经典算法,由艾兹格·迪杰斯特拉引入,因其操作类似于火车编组场而得名。<br/>
* 参考:
* <a href='http://zh.wikipedia.org/wiki/Shunting_yard%E7%AE%97%E6%B3%95'>Shunting yard算法</a>
*
* @author juqkai(juqkai@gmail.com)
*
*/
public class ShuntingYard {
  private Deque<Operator> opts;
  private Queue<Object> rpn;
 
  /**
   * 转换操作符.
   * 根据 ShuntingYard 算法进行操作
   * @param current
   */
  private void parseOperator(Operator current){
    //空,直接添加进操作符队列
    if(opts.isEmpty()){
      opts.addFirst(current);
      return;
    }
    //左括号
    if(current instanceof LBracketOpt){
      opts.addFirst(current);
      return;
    }
    //遇到右括号
    if(current instanceof RBracketOpt){
      while(!(opts.peek() instanceof LBracketOpt)){
        rpn.add(opts.poll());
      }
      opts.poll();
      return;
    }
   
    //符号队列top元素优先级大于当前,则直接添加到
    if(!opts.isEmpty() && opts.peek().fetchPriority() > current.fetchPriority()){
      opts.addFirst(current);
      return;
    }
    //一般情况,即优先级小于栈顶,那么直接弹出来,添加到逆波兰表达式中
    while(!opts.isEmpty() && opts.peek().fetchPriority() <= current.fetchPriority()){
      //三元表达式嵌套的特殊处理
      if(opts.peek() instanceof QuestionOpt && current instanceof QuestionOpt){
        break;
      }
      if(opts.peek() instanceof QuestionOpt && current instanceof QuestionSelectOpt){
        rpn.add(opts.poll());
        break;
      }
      rpn.add(opts.poll());
    }
    opts.addFirst(current);
  }
 
  /**
   * 转换成 逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法)
   * @param reader
   * @return
   * @throws IOException
   */
  public Queue<Object> parseToRPN(String val) {
    rpn = new LinkedList<Object>();
    opts = new LinkedList<Operator>();
   
    Converter converter = new Converter(val);
    converter.initItems();
    while(!converter.isEnd()){
      Object item = converter.fetchItem();
      if(item instanceof Operator){
        parseOperator((Operator) item);
        continue;
      }
      rpn.add(item);
    }
    while(!opts.isEmpty()){
      rpn.add(opts.poll());
    }
   
    return rpn;
  }
}
TOP

Related Classes of org.nutz.el.arithmetic.ShuntingYard

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.