当前位置: 首页 > 工具软件 > IKExpression > 使用案例 >

IKexpression解读一

楚和悌
2023-12-01

将字符串解析为单词

代码注释参考github中项目

作者:林良益,卓诗垚


/**
 * 分层前:
 * 1.读取字符,一个指针走,一个指针停
 * 2.读取字符的结果:
 * a.没有问题,mark(),mark指针赶上
 * b.有问题,reset,指针回退
 * 缺点:不能获取有问题的index
 *
 * 基本元素:字符,开始位置和当前位置
 * 组合:开始位置和当前位置的交互
 *
 *
 * 分层后的使用方式
 * 1.读取字符
 * 2.读取字符结果:
 * a.没有问题,mark(mark为本次读取的个数)
 * b.有问题,reset重新读取
 * 优点:可以获取有问题的index
 *
 */
public class LevelReader extends StringReader {

    private static final String IGNORE_CHAR = " \r\n\t";//词元间的忽略字符
    public static final String NUMBER_CHARS = "01234567890.";//表示数值的字符

    private int currentIndex = 0;//当前索引

    //用于记录回退的个数
    private int markIndex = 0;//被标记后索引

    private boolean prefixBlank = false;//与上一个读到的ElementToken之间是否有空格

    /**
     * Creates a new string reader.
     *
     * @param s String providing the character stream.
     */
    public LevelReader(String s) {
        super(s);
    }

    @Override
    public int read() throws IOException {
        int c = super.read();
        if (c != -1){
            currentIndex++;
            markIndex++;
        }
        return c;
    }



    /**
     * 将回退位置清0
     * @param readAheadLimit
     * @throws IOException
     */
    @Override
    public void mark(int readAheadLimit) throws IOException {
        super.mark(readAheadLimit);
        markIndex = 0;
    }

    /**
     * 作用:读错了,重读
     * 回退
     * 回退到该单词开始的位置
     * @throws IOException
     */
    @Override
    public void reset() throws IOException {
        super.reset();
        currentIndex = currentIndex - markIndex;
    }

    @Override
    public void close() {
        super.close();
    }



    public void readToken() throws IOException {
        //递归字符串中字符
        //如果是-1,说明读取结束
        //如果是空格等,跳过
        //如果不是空格,然后重置,获取处理器
        //使用处理器读取
        while (true){
            //开始读取,说明以前读取的都没有问题,mark为0
            mark(0);
            int c = read();
            if (c == -1){
                return ;
            }
            if (IGNORE_CHAR.indexOf(c) >= 0){
                continue;
            }

            //c不是空格
            reset();
            Element element = createElementReader();

            ExpressionToken expressionToken = changeToToken(element);
            //主要用于校验,括号匹配问题
            pushParenthesis(element);
            //list.add(expressionToken);

        }
    }
}

    public Element createElementReader() throws IOException {
        mark(0);
        int b = read();
        reset();
        if (b != -1){
            char c = (char) b;
            if (NUMBER_CHARS.indexOf(c) >= 0){
                Element element = readNumber();
                System.out.println(new Gson().toJson(element));
                return element;
            }
            //如果是操作符,操作符的定义+-*/ > >= < <= == != && || ! 等等
            //OperatorTypeReader 中包含操作符,Operator中也包含操作符,一个是读取element的时候,一个是转化为RPN的时候(要比较优先级)
//            else if (){
//
//            }
        } else {
            System.out.println("流结束了");
        }
        return null;
    }
   /**
     * 1.数字和点依次添加
     * 2.结尾如果是l或者是L,则为long类型
     * 3.结尾如果是f或者是F,则为float类型
     * 4.结尾如果是d或者是D,则为double类型
     * @return
     * @throws IOException
     */
    public Element readNumber() throws IOException {
        int index = currentIndex;
        mark(0);
        StringBuilder sb = new StringBuilder();
        int b = -1;
        while ((b = read()) != -1){
            char c = (char) b;
            if (NUMBER_CHARS.indexOf(c) >= 0){
                sb.append(c);
                mark(0);
            } else {
                reset();
                return new Element(sb.toString(), index, Element.ElementType.INT);
            }
        }
        return null;
    }

/**
 * 表达式词元
 * @@author 林良益,卓诗垚
 * @version 2.0 
 * Sep 23, 2008
 * 
 */
public class Element {
	
	public enum ElementType {
		//NULL类型
		NULL ,
		//字符窜
		STRING ,
		//布尔类
		BOOLEAN ,
		//整数
		INT ,
		//长整数
		LONG ,
		//浮点数
		FLOAT ,
		//双精度浮点
		DOUBLE ,
		//日期时间
		DATE ,
		
		//变量
		VARIABLE ,
		//操作符
		OPERATOR ,
		//函数
		FUNCTION ,
		//分隔符
		SPLITOR
	}
	
	private String text;
	private ElementType type;//类型
	private int index;//元素在表达式中的起始索引号,从0算起
	
	/**
	 * 构造
	 * @param text
	 * @param index
	 * @param type
	 */
	public Element(String text, int index, ElementType type) {
		this.text = text;
		this.index = index;
		this.type = type;
	}
	

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public ElementType getType() {
		return type;
	}

	public void setType(ElementType type) {
		this.type = type;
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}
}

其中element中记录的单词的字符序列,开始索引,单词的类型(整形,long型,字符串,null,函数,分隔符,操作符,变量等等)

    public static void main(String[] args) throws IOException {
        LevelReader lr = new LevelReader("  10 > 20 || 30 < 50 && (70 > 80 || 90 > 70)");
       lr.readToken();
}

 类似资料: