zl程序教程

您现在的位置是:首页 >  后端

当前栏目

LCC编译器的源程序分析(17)参数变量的声明

变量编译器 分析 参数 17 声明 源程序 LCC
2023-09-14 09:10:39 时间
 
函数里的参数变量个数不固定,因此也需要检查这些参数的名称是否相同,还需要检查类型的合法性。现在就来分析上次提到的函数 dclparam ,它的代码如下:
#001 // 参数类型声明处理
#002 static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos)
#003 {
#004  Symbol p;
#005 
#006  if (isfunc(ty))
#007         ty = ptr(ty);
#008  else if (isarray(ty))
#009         ty = atop(ty);
#010 
6 行判断这个参数变量是否声明为函数类型,如果是就需要创建新类型。
8 行判断这个参数变量是否声明为数据类型。
 
#011  if (sclass == 0)
#012         sclass = AUTO;
#013  else if (sclass != REGISTER)
#014  {
#015         error("invalid storage class `%k' for `%t%s/n",
#016               sclass, ty, stringf(id ? " %s'" : "' parameter", id));
#017         sclass = AUTO;
#018  }
#019  else if (isvolatile(ty) || isstruct(ty))
#020  {
#021         warning("register declaration ignored for `%t%s/n",
#022               ty, stringf(id ? " %s'" : "' parameter", id));
#023         sclass = AUTO;
#024  }
#025 
11 行到第 24 行都是判断存储类型。如果没有声明存储类型,缺省为 AUTO 类型。其它几个识别为寄存器类型 REGISTER 、不可删除属性、结构类型。
 
#026  p = lookup(id, identifiers);
#027  if (p && p->scope == level)
#028         error("duplicate declaration for `%s' previously declared at %w/n", id, &p->src);
#029  else
#030         p = install(id, &identifiers, level, FUNC);
#031 
26 行是查找这个参数变量是否已经在其它地方声明过,如果声明过就从 lookup 返回给 p ,如果作用域一样的声明肯定就是重复声明,这是出错的,在第 28 行里提示出错信息。如果没有这个参数变量是合法的,就把它保存到声明表格 identifiers 里。
 
 
#032  p->sclass = sclass;
#033  p->src = *pos;
#034  p->type = ty;
#035  p->defined = 1;
#036  
上面几行是保存参数的属性到 p 符号里。
 
#037  if (t == '=')
#038  {
#039         error("illegal initialization for parameter `%s'/n", id);
#040         t = gettok();
#041         (void)expr1(0);
#042  }
#043 
由于在标准 C 里是不允许参数变量初始化的,所以在第 37 行就处理这样的出错,如果在 C ++里应是允许的。
 
#044  return p;
#045 }
在第 44 行里就是返回分析出来的一个参数变量返回添加到参数列表里。
 
到这里就把所有的函数声明分析完成了,把 hello.i 文件里的声明已经分析大部份,自定义类型、指针类型、结构类型、函数声明等部分,下面就开始进入到 main 函数的分析了,这次分析到这里,下次再会。