筛子-- Name
赋值具有如下语法:
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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论