LCC编译器的源程序分析(14)结构类型的声明

以前都是简单类型的识别和语法分析,现在来分析结构的声明,它是比较复杂的一种数据类型,但结构在编写程序中使用是非常多的。由于程序的方程式就是:
数据结构 算法 程序
现在面向对象的方程式是:
数据结构 算法 对象
对象 对象 程序
由上面的公式,就可以看出程序中的数据结构是非常重要的,无论是面向对象的编程,还是面向过程的编程,有什么样的数据结构,就需要有什么样算法。而在 C 语言里,使用结构类型来描述现实中需要的抽象模型。例子里的结构声明如下:
struct _iobuf {
 char *_ptr;
 int   _cnt;
 char *_base;
 int   _flag;
 int   _file;
 int   _charbuf;
 int   _bufsiz;
 char *_tmpfname;
 };
typedef struct _iobuf FILE;
这是声明一个文件对象结构。现在就来分析一下 LCC 编译器是怎么样进行结构的语法分析的。先用调函数 decl(dclglobal) ,然后调用函数 specifier ,在函数 specifier 就会处理结构的声明,它的代码如下:
#001 static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *))
#002 {
#003  int sclass;
#004  Type ty, ty1;
#074         case STRUCT:
#075         case UNION:   
#076               p = &type;
#077               ty = structdcl(t);
#078               break;
上面结构定义和联合的识别,这也是比较复杂的类型,所以也调用 structdcl 来进一步处理结构体。为了仔细地了解结构的语法分析,就需要分析函数 structdcl 的代码,如下:
#001 // 结构声明处理。
#002 static Type structdcl(int op)
#003 {
#004  char *tag;
#005  Type ty;
#006  Symbol p;
#007  Coordinate pos;
#008 
#009  t = gettok();
#010  pos = src;
#011  if (t == ID)
#012  {
#013         tag = token;
#014         t = gettok();
#015  }
#016  else
#017         tag = "";
#018 
#019  // 结构的定义开始。
#020  if (t == '{')
#021  {
#022         static char stop[] = { IF, ',', 0 };
#023         ty = newstruct(op, tag);
#024         ty->u.sym->src = pos;
#025         ty->u.sym->defined = 1;
#026 
#027         t = gettok();
#028         if (istypename(t, tsym))
#029         {
#030               // 结构成员定义。
#031               fields(ty);
#032         }   
#033         else
#034         {
#035               error("invalid %k field declarations/n", op);
#036         }   
#037 
#038         test('}', stop);
#039  }
#040  else if (*tag && (p = lookup(tag, types)) != NULL
#041         && p->type->op == op)
#042  {
#043         ty = p->type;
#044         if (t == ';' && p->scope < level)
#045               ty = newstruct(op, tag);
#046  }
#047  else
#048  {
#049         if (*tag == 0)
#050               error("missing %k tag/n", op);
#051         ty = newstruct(op, tag);
#052  }
#053 
#054  if (*tag && xref)
#055         use(ty->u.sym, pos);
#056 
#057  return ty;
#058 }
处理 struct 之后,接着就要处理结构的名称,在这个例子里是 _iobuf ,它是在第 9 行里获取到这个记号,然后在第 11 行里保存 _iobuf 到变量 tag 里。 tag 也有可能是空的情况,比如像下面的语法:
typedef struct  { int a; } A;
上面的语法就是在第 17 行里处理这种情况的。
在第 20 行到 39 行里,主要处理结构字段定义。像结构 _iobuf 中的定义,就是处理下面的语句:
{
 char *_ptr;
 int   _cnt;
 char *_base;
 int   _flag;
 int   _file;
 int   _charbuf;
 int   _bufsiz;
 char *_tmpfname;
 }
在第 23 行里创建结构的类型 ty ,然后在第 28 行里判断语句是否类型开始的记号,如果不是就是出错的定义。如果是类型,比如像例子里的 char ,就需要调用函数 fields(ty) 来处理所有的字段定义。
接着下来就需要去分析 fields 的代码,下一次再带你去分析它吧。 

转载于:https://www.cnblogs.com/ajuanabc/archive/2007/05/25/2464356.html

你可能感兴趣的:(数据结构与算法,c/c++)