analyze.c
上传用户:wqdrylgs
上传日期:2007-02-09
资源大小:65k
文件大小:8k
源码类别:

汇编语言

开发平台:

WINDOWS

  1. /****************************************************/
  2. /* File: analyze.c                                  */
  3. /* Semantic analyzer implementation */
  4. /* for the C_Minus compiler */
  5. /****************************************************/
  6. #include "globals.h"
  7. #include "util.h"
  8. #include "parse.h"
  9. #include "symtab.h"
  10. #include "analyze.h"
  11. /* counter for variable memory locations */
  12. static int location = 0;
  13. /* current symble table */
  14. static Symtab * pTable;
  15. static FunEntry * pFun;
  16. /* procedure traverse is a generic recursive
  17.  * syntax tree traversal routine:
  18.  * it applies preProc in preorder and postProc 
  19.  * in postorder to tree pointed to by t
  20.  */
  21. static void traverse(TreeNode * t, 
  22.  void (* preProc) (TreeNode *),
  23.  void (* postProc) (TreeNode *))
  24. if (t != NULL)
  25. int i;
  26. preProc(t);
  27. for (i=0; i < MAXCHILDREN; i++)
  28. traverse(t->child[i], preProc, postProc);
  29. postProc(t);
  30. traverse(t->sibling, preProc, postProc);
  31. }
  32. }
  33. /* nullProc is a do-nothing procedure to 
  34.  * generate preorder-only or postorder-only
  35.  * traversals from traverse
  36.  */
  37. static void nullpreProc(TreeNode * t)
  38. if (t == NULL) return;
  39. else if (t->nodekind == Dec) {
  40. switch (t->kind.dec)
  41. {
  42. case FunDefK:
  43. pFun = Lookup_Fun(t->attr.name);
  44. break;
  45. case CompK:
  46. pTable = t->attr.table;
  47. break;
  48. }
  49. }
  50. }
  51. static void nullpostProc(TreeNode * t)
  52. if (t == NULL || pTable == NULL) return;
  53. else if (t->nodekind == Dec && t->kind.dec == CompK)
  54. pTable = pTable->parent;
  55. }
  56. /* procedure insertNode inserts 
  57.  * identifiers stored in t into 
  58.  * the symbol table 
  59.  */
  60. static void insertNode(TreeNode * t)
  61. switch (t->nodekind)
  62.     case Dec:
  63. switch (t->kind.dec)
  64. case FunDecK:
  65. if (Lookup_Fun(t->attr.name) == NULL)
  66. Insert_Fun(t->attr.name, t->type, t->child[0]);
  67. break;
  68. case FunDefK:
  69. if (Lookup_Fun(t->attr.name) == NULL)
  70. pFun = Insert_Fun(t->attr.name, t->type, t->child[0]);
  71. break;
  72. case VarK:
  73. {
  74. ValEntry Entry;
  75. TreeNode * child;
  76. for (child = t->child[0]; child != NULL; child = child->sibling) {
  77. if (child->nodekind == Exp && child->kind.exp == IdK) {
  78. if (Lookup_Var(pTable, pFun, child->attr.name, &Entry) != pTable->nestlevel)
  79. if (child->child[0] == NULL)
  80. Insert_Var(pTable, child->attr.name, t->type, 1);
  81. else
  82. Insert_Var(pTable, child->attr.name, t->type, child->child[0]->attr.val.i);
  83. }
  84. else if (child->nodekind == Stmt && child->kind.stmt == AssignK) {
  85. if (Lookup_Var(pTable, pFun, child->child[0]->attr.name, &Entry) != pTable->nestlevel)
  86. if (child->child[0]->child[0] == NULL)
  87. Insert_Var(pTable, child->child[0]->attr.name, t->type, 1);
  88. else
  89. Insert_Var(pTable, child->child[0]->attr.name, t->type, child->child[0]->child[0]->attr.val.i);
  90. }
  91. }
  92. }
  93. break;
  94. case CompK:
  95. pTable = Createtab(pTable, pFun);
  96. if (pTable==NULL)
  97. fprintf(listing, "Out of memory error at line %dn", t->lineno);
  98. t->attr.table = pTable;
  99. break;
  100.         default:
  101. break;
  102.       }
  103.       break;
  104. default:
  105. break;
  106. }
  107. }
  108. /* function buildSymtab constructs the symbol 
  109.  * table by preorder traversal of the syntax tree
  110.  */
  111. void buildSymtab(TreeNode * tree)
  112. {
  113. GlobalTable = Createtab(NULL, NULL);
  114. if (GlobalTable==NULL)
  115. fprintf(listing, "Out of memory error at line %dn", tree->lineno);
  116. pTable = GlobalTable;
  117. traverse(tree, insertNode, nullpostProc);
  118. if (TraceAnalyze)
  119. printFunTab();
  120. printSymTab(tree);
  121. }
  122. }
  123. static void typeError(TreeNode * t, char * message)
  124. fprintf(listing,"Type error at line %d: %sn", t->lineno, message);
  125. Error = TRUE;
  126. }
  127. /* procedure checkNode performs
  128.  * type checking at a single tree node
  129.  */
  130. static void checkNode(TreeNode * t)
  131. switch (t->nodekind)
  132.     case Dec:
  133. if (t->kind.dec == CompK)
  134. pTable = pTable->parent;
  135. break;
  136. case Exp:
  137. switch (t->kind.exp)
  138. case OpK:
  139. switch(t->attr.op) {
  140. case PLUS: case SUB: case MUT: case DIV:
  141. if ((t->child[0]->type != Integer && t->child[0]->type != Float) ||
  142. (t->child[1]->type != Integer && t->child[1]->type != Float))
  143. typeError(t, "Op applied to non-number");
  144. else if (t->child[0]->type == Float || t->child[1]->type == Float)
  145. t->type = Float;
  146. else
  147. t->type = Integer;
  148. break;
  149. case LT: case LE: case GT: case GE: case EQ: case NEQ:
  150. if ((t->child[0]->type != Integer && t->child[0]->type != Float) ||
  151. (t->child[1]->type != Integer && t->child[1]->type != Float))
  152. typeError(t, "Op applied to non-number");
  153. else 
  154. t->type = Boolean;
  155. break;
  156. case AND: case OR:
  157. if ((t->child[0]->type != Integer && t->child[0]->type != Boolean) ||
  158. (t->child[1]->type != Integer && t->child[1]->type != Boolean))
  159. typeError(t, "Op applied to non-boolean");
  160. else
  161. t->type = Boolean;
  162. break;
  163. }
  164. break;
  165.         case IdK:
  166. {
  167. ValEntry Entry;
  168. if (Lookup_Var(pTable, pFun, t->attr.name, &Entry) != -1)
  169. t->type = Entry.type;
  170. else {
  171. ValEntry * pEntry;
  172. for (pEntry = pFun->para; pEntry != NULL; pEntry = pEntry->next)
  173. if (strcmp(t->attr.name, pEntry->name) == 0) {
  174. t->type = pEntry->type;
  175. break;
  176. }
  177. if (pEntry == NULL)
  178. typeError(t, "reference to undefined id");
  179. }
  180. }
  181. break;
  182. }
  183. break;
  184.     case Stmt:
  185. switch (t->kind.stmt)
  186. case IfK:
  187. if (t->child[0]->type != Boolean && t->child[0]->type != Integer)
  188. typeError(t->child[0], "if test is not Boolean");
  189. break;
  190.         case WhileK:
  191. if (t->child[0]->type != Boolean && t->child[0]->type != Integer)
  192. typeError(t->child[0], "while test is not Boolean");
  193. break;
  194. case CallK: 
  195. {
  196. FunEntry * pEntry = Lookup_Fun(t->attr.name);
  197. if (pEntry != NULL) {
  198. ValEntry * para;
  199. t->type = pEntry->type;
  200. for (para = pEntry->para, t = t->child[0]; para != NULL && t != NULL;
  201. para = para->next, t = t->sibling)
  202. if (para->type != t->type)
  203. typeError(t, "call to function with wrong parameter");
  204. if (para != NULL || t != NULL)
  205. typeError(t, "call to function with wrong parameter");
  206. }
  207. else
  208. typeError(t, "call to undefined function");
  209. }
  210. break;
  211. case ReturnK:
  212. t->type = t->child[0]->type;
  213. if (t->type != pFun->type)
  214. typeError(t, "return type inconsistent with definition");
  215. break;
  216. case AssignK:
  217. if (t->child[0]->type != t->child[1]->type) {
  218. if (t->child[0]->type == Float && t->child[1]->type == Integer)
  219. t->type = t->child[1]->type = Float;
  220. else if (t->child[0]->type == Integer && t->child[1]->type == Float) 
  221. t->type = Integer;
  222. else 
  223. typeError(t->child[0], "assignment type mismatched");
  224. }
  225. t->type = t->child[0]->type;
  226. break;
  227. }
  228. break;
  229. }
  230. }
  231. /* procedure transNode transforms
  232.  * a tree node type to the appropriate one 
  233.  */
  234. static void transNode(TreeNode * t)
  235. {
  236. if (t->nodekind == Exp && t->kind.exp == OpK) {
  237. switch(t->attr.op) {
  238. case PLUS: case SUB: case MUT: case DIV:
  239. if ((t->type == Float && t->child[0]->type == Integer)) {
  240. t->child[0]->type = Float;
  241. if (t->child[0]->nodekind == Exp && t->child[0]->kind.exp == NumK)
  242. t->child[0]->attr.val.f = (float)(t->child[0]->attr.val.i);
  243. }
  244. if ((t->type == Float && t->child[1]->type == Integer)) {
  245. t->child[1]->type = Float;
  246. if (t->child[1]->nodekind == Exp && t->child[1]->kind.exp == NumK)
  247. t->child[1]->attr.val.f = (float)(t->child[1]->attr.val.i);
  248. }
  249. break;
  250. }
  251. }
  252. }
  253. /* procedure typeCheck performs type checking 
  254.  * by a postorder syntax tree traversal
  255.  */
  256. void typeCheck(TreeNode * syntaxTree)
  257. traverse(syntaxTree, nullpreProc, checkNode);
  258. traverse(syntaxTree, transNode, nullpostProc);
  259. }