词法分析器实现——缓存流迭代器

缓存流迭代器PeekIterator是词法分析器的基础。我们是将源代码转换成“Stream流”来处理的,通过这个迭代器,就可以对代码的流进行一系列的操作了,包括正则校验、类型判断等。换句话说,这个迭代器就是把代码包含的字符一个一个地取出来,然后进行观察并操作。

peek和next函数默认先从栈顶取值,如果栈中无元素,再从流的下一个位置取元素,并将该元素放到队列尾。

代码如下,内含详细注释:

import java.util.Iterator;
import java.util.LinkedList;
import java.util.stream.Stream;
/**
 * @description : 需要一个队列和一个栈配合操作,putBack是从队列尾拿出元素,放入栈顶,而next是从 
 *                栈顶取出元素,再依次放回队列尾。
 * @date : 2024-05-03 17:24
 */
public class PeekIterator<T> implements Iterator<T> {
    // 队列
    private LinkedList<T> queueCache = new LinkedList<>();
    // 栈
    private LinkedList<T> stackPutBacks = new LinkedList<>();
    private Iterator<T> it;
    private final static int CACHE_SIZE = 10;
    private T _endToken = null;
    public PeekIterator(Stream<T> stream) {
        it = stream.iterator();
    }
    public PeekIterator(Stream<T> stream, T endToken) {
        it = stream.iterator();
        _endToken = endToken;
    }

    /**
     * 与next不同之处在于,多次执行next函数,会将流中的元素依次取出来,这会改变取元素的位置。
     * 而peek方法执行后,只会获取当前位置的下一位置的元素,并且不改变取元素的位置。
     * 可以一直拿到同一个数据节点。
     */
    public T peek() {
        if (this.stackPutBacks.size() > 0) {
            // 获取栈顶第一个元素
            return this.stackPutBacks.getFirst();
        }
        if (!it.hasNext()) {
            return _endToken;
        }
        T val = next();
       // 取完下一个元素,就放入栈中,因此下次再执行peek方法,则从栈顶取值,依然返回相同的结果。
        this.putBack();
        return val;
    }

    /**
     * putBack执行压栈操作,
     * 有了putBack,就可以做到调用了多次next后,还可以取到之前数据,
     * 相当于按了ctrl+v的回退操作,
     * 期间产生的所有元素都放在stackPutBacks中,但是回退的次数不能超过CACHE_SIZE。
     */
    public void putBack() {
        if (this.queueCache.size() > 0) {
            // stackPutBacks是栈,push方法实现先压栈,pop方法实现先进后出
            this.stackPutBacks.push(this.queueCache.pollLast());
        }
    }
    /**
     * next方法取出流中的下一个元素。
     */
    @Override
    public T next() {
        T val = null;
        if (this.stackPutBacks.size() > 0) {
            // putBack方法是:从队列尾拿出元素,放入栈顶。
            // 而这里是从栈顶取出,下面再add进队列末尾。相当于恢复了队列中的数据。
            val = this.stackPutBacks.pop();
        } else {
            if (!it.hasNext()) {
                T tmp = _endToken;
                _endToken = null;
                return tmp;
            }
            val = it.next();
        }
        // 处理缓存
        while (queueCache.size() > CACHE_SIZE - 1) {
            queueCache.poll();
        }
        // queueCache是队列,poll方法实现先进先出
        queueCache.add(val);
        return val;
    }

    @Override
    public boolean hasNext() {
        return _endToken != null || this.stackPutBacks.size() > 0 || it.hasNext();
    }
}

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值