龙书阅读笔记

星期二, 十月 10, 2006

2.7 INCORPORATING A SYMBOL TABLE

一个叫做符号表的数据结构通常用来保存各种语言构造的信息。信息被编译器的分析阶段收集,并且被合成阶段用来生成目标代码。例如,在词法分析阶段,字符串,或者lexeme,形成的标识符被保存为符号表的一个条目。编译器的后面阶段可能向这个条目增加信息,例如标识符的类型,他的用法(例如,procedure,variable或者label),以及它在存储中的位置。代码生成阶段将使用这些信息生成合适的代码来保存和存取这个变量。在7.6中,我们将详细讨论符号表的实现和使用。在本节中,显示词法分析器如何和一个符号表交互。

The Symbol-Table Interface

符号表例程主要和保存和获取lexeme相关。当一个lexeme被保存的时候,我们也保存和lexeme相关的token。下面的操作将在符号表上被执行。


insert(s,t): 返回字符串s相关的新条目的索引,token t
lookup(s): 返回字符串s的条目的索引,返回0如果没有找到。

词法分析器使用lookup操作判断符号表中是否存在一个lexeme的对应条目。如果不存在,那么它使用insert操作去创建一个。我们应该讨论一个实现,其中词法分析器和解析器都知道符号表条目的格式。

Handling Reserved Keywords

上面的符号表例程能够处理任意的保留关键字集合。例如,考虑div和mod这两个token分别具有lexme div和mod。我们可以使用下面的调用初始化符号表
insert("div", div);
insert("mod", mod);
任何后面对lookup("div")的调用都将返回token div,因此div不能用作一个标识符。

任何保留关键字的集合都可以这样处理,通过适当地初始化符号表。


A Symbol-Table Implementation

一个特定符号表的一个特定实现的数据结构勾勒在Fig. 2.29中。



我们不希望设置一个固定的空间来保存lexemes形成的标识符,固定数量的空间可能不够大以容纳一个非常长的标识符,而对比较短的标识符可能太浪费了,例如i。在Fig. 2.29中,一个单独的数组lexemes用来保存形成一个标识符的那些字符串。字符串以字符结束字符结束,即EOS,不会出现在任何标识符中。符号表数组symtable中的每一个条目是一个包含两个字段的记录,lexptr,指向一个lexeme的开始,以及token。额外的字段可以容纳属性值,虽然我们这里不需要这样做。

在Fig. 2.29中,第0个条目保留为空,因为lookup返回0表示没有一个字符串对应的条目。第1和第2条目分别对应关键字div和mod。而第3和第4条分别对应标识符count和i.

处理标识符的一个词法分析器的伪代码如Fig. 2.30所示;一个C实现在Section 2.9中。空白和整数常量被词法分析器用上一节Fig. 2.28一样的方式处理。


function lexan:integer;
var lexbuf: array[0..100] of char;
c: char;
begin
read a character into c;
if c is a blank or a tab then
do nothing
else if c is a newline then
lineno := lineno + 1
else if c is a digit then begin
set tokenval to the value of this and following digits;
return NUM
end
else if c is a letter then begin
place c and successive letters and digits into lexbuf;
p := lookup(lexbuf);
if p = 0 then
p := insert(lexbuf, ID);
tokenval := p;
return the token field of table entry p
end
else begin /* token is a single character */
set tokenval to NONE;
return integer encoding of character c
end
end

当我们的词法分析器读到一个字母时,它开始在一个缓冲区lexbuf中保存字母和数字。在lexbuf中搜集好的字符串在符号表中进行lookup。因为符号表中已经初始化了关键字div和mod,因此如果lexbuf中是div或者mod,那么就会返回相应的条目。如果找补到,那么lexbuf包含一个新标识符的新lexme。使用insert插入一个新条目,p是这个新条目在符号表中的索引。该索引通过设置tokenval=p和解析器通讯,该条目的token字段被返回。
缺省的动作是返回字符的整数编码。既然单个字符的token在这里没有属性,tokenval设置为NONE。

没有评论: