词法分析——输入缓冲

目录

综述

正文

1 缓冲区对

2 哨兵标记

       


综述

        在讨论如何识别输入流中的词素之前,我们首先讨论几种可以加快源程序读入速度的方法。源程序读入虽然简单,却很重要。由于我们常常需要查看一个词素之后的若干字符才能够确定是否找到了正确的词素,因此这个任务变得有些困难。在“识别词法单元时的棘手问题”中给出了一个极端的例子。但是在实践中,很多情况下我们的确需要至少向前看一个字符。比如,我们只有读取到一个非字母或数字的字符之后才能确定我们已经达到一个标识符的末尾,因此这个字符不是 id 的词素的一部分。在C语言中,像 - 、= 或 < 这样的单字符运算符也有可能是 ->、== 或 <= 这样的双字符运算符的开始字符。因此,我们将介绍一种双缓存区方案,这种方案能够安全地处理向前看多个符号的问题。然后,我们考虑一种改进方法。这种方法使用“哨兵标记”来节约用于检查缓冲器末端的时间。

正文

1 缓冲区对

         我们考虑一种改进方法。这种方法使用“哨兵标记”来节约用于检查缓冲器末端的时间。由于在编译一个大型源程序时需要处理大量的字符 ,处理这些字符需要很多的时间,因此开发了一些特殊的缓冲技术来减少用于处理单个输入字符的时间开销。一种重要的机制就是利用两个交替读入的缓冲区,如图1-1所示。

图1-1 使用一对输入缓冲区

         每个缓冲区的容量都是N个字符,通常N是一个磁盘块的大小,如4096字节。我们可以使用系统读取命令一次将N个字符读入到缓冲区中,而不是每读入一个字符调用一次系统读取命令。如果输入文件中的剩余字符不足N个,那么就会有一个特殊字符(用 eof 表示)来标记源文件的结束。这个特殊字符不同于任何可能出现在源程序中的字符。

        程序为输入维护了两个指针:

        1)lexemeBegin指针:该指针指向当前词素的开始处。当前我们正视试图确定这个词素的结尾。

        2)forward指针:他一直向前扫描,直到发现某个模式被匹配为止。做出这个决定所依据的策略在以后来讨论。

        一旦确定了下一个词素,forward指针将指向该词素结尾的字符。词法分析器将这个词素作为某个返回给语法分析器的词法单元的属性值记录下来。然后使lexemeBegin指针指向刚刚找到的词素之后的第一个字符。在图1-1中,我们看到,forward指针已经越过下一个词素 * * (Fortran的指数运算符)。在处理完这个词素后,它将会被左移一个位置。

        将forward指针前移要求我们首先检查是否已经到达某个缓冲区的末尾。如果是,我们必须将N个新字符读到另一个缓冲区中,且将forward指针指向这个新载入字符的缓冲区的头部。只要我们从不需要越过实际的词素向前看很远,以至于这个词素的长度加上我们向前看的距离大于N,我们就绝不会在识别这个词素之前覆盖掉这个尚在缓冲区中的词素。

2 哨兵标记

        如果我们采用上一届节中描述的方案,那么在每次向前移动forward指针时,我们都必须检查是否到达了缓冲区的末尾。若是,那么我们必须加载另一个缓冲区。因此,每读入一个字符,我们需要做两次测试:一次是检查是否到达缓冲区的末尾,另一次是确定读入的字符是什么(后者肯是一个多路分支选择语句)。如果我们扩展每个缓冲区,使他们在末尾包含一个“哨兵”(sentinel) 字符,我们就可以把对缓冲区末端的测试和对当前字符的测试合二为一。这个哨兵字符必须是一个不会在源程序中出现的特殊字符,一个自然地选择就是字符 eof

        图1-2显示的缓冲区安排与图1-1一致,只是加入了“哨兵标志”字符。请注意, eof 仍然可以用来标记整个输入的结尾。任何不是出现在某个缓冲区末尾的 eof 都表示到达了输入的结尾。代码段部分总结了前移forward所指向的字符完成多路分支跳转。只有当我们确实处于缓冲区末尾或输入末尾时,才需要进行更多的测试。

图1-2 各个缓冲区末端的“哨兵标记”

/*     Author: John Rothan
*     Title:带有哨兵标记的forward指针移动算法
*/     Date: 2022-3-3


switch ( *forward ++ ) {
    case eof:
        if (forward在第一个缓冲区末尾) {
            装载第二个缓冲区;
            forward=第二个缓冲区的开头;
        }
        else if (forward在第二个缓冲区末尾) {
            装载第一个缓冲区;
            forward=第一个缓冲区的开头:
        }
        else /*缓冲区内部的eof标记输入结束*/
            终止词法分析
        其他字符的情况
}

        

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈士奇谭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值