返回介绍

筛子-- Name

发布于 2025-02-24 22:44:39 字数 1820 浏览 0 评论 0 收藏 0

赋值具有如下语法:

stmt : sum
   | LET VAR = sum

LET 是关键字的一个例子。在构建筛子的过程中我们仍然可以决定什么标识符将标示 LET: scan() 从输入行提取一个标识符并传递给 screen() ,是它在符号表中查找并返回 token 的适当值,至少一个变量,一个节点在 symbol 中。

识别器丢弃 LET 但是插入变量作为叶子节点在树中。对于另一个符号,例如一个算数函数的名称,我们可能想要适用 new()screener 返回的符号来获取一个新的节点。因此,我们的符号表入口应当对与大部分具有相同的函数动态绑定与我们树节点。

对于一个关键字,一个 Name 需要包含输入字符串和 token 值。稍后我们想要继承 Name ;因此,我们定义结构在 Name.r 中:

struct Name {      /* base structure */
  const void * type;  /* for dynamic linkage */
  const char * name;  /* may be malloc-ed */
  int token;
};

我们的符号从不死亡:他们的名字是预定义的常量字符串还是存储的用户自定义变量动态字符串是没有关系的--我们将不会回收他们。

在我们可以定义一个符号之前,我们需要输入它到符号表。这不能通过调用 new(Name, ...) 来处理,因为我们想要支持更多比 Name 复杂的符号,并且我们想要隐藏符号表的实现。相反的,我们提供一个函数 install() ,它需要一个 Name 对象并把它插入到符号表中。这里给出符号表接口文件 Name.h

extern void * symbol;  /* -> last Name found by screen() */
void install (const void * symbol);
int screen (const char * name);

识别器必须插入像 LET 的关键字到符号表中,在他们被 screener 发现之前。这些关键字可以被定义进一个常量表结构中--它对 install() 没有影响。下面的函数被用来初始化识别:

#include "Name.h"
#include "Name.r"

static void initName (void) {
  static const struct Name names [] = {
    { 0, "let", LET },
    0
  };
  const struct Name * np;

  for (np = names; np->name; ++np)
    install(np);
}

注意 names[] ,关键字表,不需要被存储。我们适用 Name 的标示来定义 names[] ,也就是说,我们包含 Name.r 。由于关键字 LET 被丢弃,我们不提供动态绑定的方法。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文