SymTable.Mod 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. MODULE SymTable;
  2. IMPORT Out, S := Scanner;
  3. CONST
  4. (* Классы объектов (и одновременно режимы предметов) *)
  5. Head* = 0; Const* = 1; Var* = 2; Par* = 3; Typ* = 5; Mod* = 8;
  6. (*Par - это вар-параметр*)
  7. (* Формы типов *)
  8. Char* = 3;
  9. Int* = 4;
  10. NoTyp* = 9;
  11. Proc* = 10;
  12. TYPE
  13. Object* = POINTER TO ObjDesc;
  14. Type* = POINTER TO TypeDesc;
  15. TypeDesc* = RECORD
  16. form*: INTEGER; (* Форма типа *)
  17. size*: INTEGER; (* Размер типа в байтах *)
  18. nofpar*: INTEGER; (* Количество параметров *)
  19. base*: Type; (* Тип возвращаемого значения процедуры *)
  20. dsc*: Object (* Список формальных параметров процедуры *)
  21. END;
  22. ObjDesc* = RECORD
  23. class*: INTEGER; (* Класс объекта *)
  24. type*: Type;
  25. name*: ARRAY 32 OF CHAR;
  26. val*: INTEGER;
  27. next*, dsc*: Object
  28. END;
  29. (* Назначение поля val в зависимости от значения поля class (в Object):
  30. class | val
  31. ------+-----------------------
  32. Var | адрес переменной
  33. Const | значение константы
  34. Type | не используется (пока) *)
  35. VAR
  36. curScope: Object;
  37. charType*, intType*, noType*: Type;
  38. (*Для удобочитаемой отладки*)
  39. PROCEDURE OutType*(t: Type);
  40. BEGIN
  41. IF t.form = Int THEN Out.String("целое число")
  42. ELSIF t.form = Char THEN Out.String("литера")
  43. ELSE Out.Int(t.form, 0)
  44. END
  45. END OutType;
  46. PROCEDURE MakeType(form, size: INTEGER): Type;
  47. VAR t: Type;
  48. BEGIN
  49. NEW(t);
  50. t.form := form;
  51. t.size := size;
  52. RETURN t
  53. END MakeType;
  54. PROCEDURE NewObj*(name: ARRAY OF CHAR; class: INTEGER): Object;
  55. VAR o, p: Object;
  56. BEGIN
  57. p := curScope;
  58. WHILE (p.next # NIL) & (p.next.name # name) DO p := p.next END;
  59. IF p.next = NIL THEN
  60. NEW(o);
  61. o.class := class;
  62. o.name := name;
  63. o.next := NIL;
  64. p.next := o
  65. ELSE
  66. o := p.next;
  67. S.Mark("Такой объект уже есть")
  68. END;
  69. RETURN o
  70. END NewObj;
  71. PROCEDURE ThisObjInModule*(mod: Object): Object;
  72. VAR o: Object;
  73. BEGIN
  74. o := mod.dsc;
  75. WHILE (o # NIL) & (o.name # S.id) DO o := o.next END;
  76. RETURN o
  77. END ThisObjInModule;
  78. (*Предусловие: sym = S.ident*)
  79. PROCEDURE ThisObj*(): Object;
  80. VAR o, p: Object;
  81. BEGIN
  82. p := curScope;
  83. WHILE p # NIL DO
  84. o := p.next;
  85. WHILE (o # NIL) & (o.name # S.id) DO
  86. o := o.next
  87. END;
  88. IF o = NIL THEN p := p.dsc
  89. ELSE p := NIL
  90. END
  91. END;
  92. RETURN o
  93. END ThisObj;
  94. (*Добавить процедуру в модуль*)
  95. PROCEDURE AddProc(m: Object; name: ARRAY OF CHAR; key: INTEGER): Object;
  96. VAR o, g: Object;
  97. BEGIN
  98. NEW(o);
  99. IF m.dsc = NIL THEN
  100. m.dsc := o
  101. ELSE
  102. g := m.dsc;
  103. WHILE g.next # NIL DO g := g.next END;
  104. g.next := o
  105. END;
  106. o.class := Const;
  107. o.name := name;
  108. o.val := key;
  109. o.next := NIL;
  110. o.dsc := NIL;
  111. o.type := MakeType(Proc, 4);
  112. o.type.nofpar := 0;
  113. o.type.base := noType;
  114. RETURN o
  115. END AddProc;
  116. (*Добавить формальный параметр в процедуру*)
  117. PROCEDURE AddParam(proc: Object; name: ARRAY OF CHAR; varParam: BOOLEAN;
  118. type: Type; offset: INTEGER);
  119. VAR o, p: Object;
  120. BEGIN
  121. NEW(p);
  122. IF proc.type.dsc = NIL THEN
  123. proc.type.dsc := p
  124. ELSE
  125. o := proc.type.dsc;
  126. WHILE o.next # NIL DO o := o.next END;
  127. o.next := p
  128. END;
  129. INC(proc.type.nofpar);
  130. IF varParam THEN p.class := Par ELSE p.class := Var END;
  131. p.name := name;
  132. p.val := offset; (*?*)
  133. p.type := type;
  134. p.next := NIL;
  135. p.dsc := NIL
  136. END AddParam;
  137. PROCEDURE Import*(alias, modname: ARRAY OF CHAR);
  138. VAR m, o, p: Object;
  139. tp: Type;
  140. BEGIN
  141. IF modname = "Out" THEN
  142. NEW(m);
  143. curScope.next := m;
  144. m.class := Mod;
  145. m.name := alias;
  146. m.val := 1; (*!FIXME*)
  147. m.type := NIL;
  148. m.dsc := NIL;
  149. (*Out.Char(ch)*)
  150. o := AddProc(m, "Char", 0);
  151. AddParam(o, "ch", FALSE, charType, 4);
  152. (*Out.Int(n, w)*)
  153. o := AddProc(m, "Int", 1);
  154. AddParam(o, "n", FALSE, intType, 4);
  155. AddParam(o, "w", FALSE, intType, 8);
  156. (*Out.Ln*)
  157. o := AddProc(m, "Ln", 2)
  158. ELSIF modname = "In" THEN
  159. NEW(m);
  160. m.next := curScope.next;
  161. curScope.next := m;
  162. m.class := Mod;
  163. m.name := alias;
  164. m.val := 2; (*!FIXME*)
  165. m.type := NIL;
  166. m.dsc := NIL;
  167. (*In.Int(n)*)
  168. o := AddProc(m, "Int", 0);
  169. AddParam(o, "n", TRUE, intType, 4)
  170. ELSE
  171. S.Mark("Такого модуля не существует")
  172. END;
  173. Out.String("Импортируем "); Out.String(modname);
  174. Out.String(" под псевдонимом "); Out.String(alias);
  175. Out.Char("."); Out.Ln
  176. END Import;
  177. PROCEDURE Init*;
  178. VAR o: Object;
  179. BEGIN
  180. NEW(curScope);
  181. curScope.class := Head;
  182. curScope.name[0] := 0X;
  183. curScope.next := NIL;
  184. NEW(curScope.dsc);
  185. curScope.dsc.class := Head;
  186. curScope.dsc.name[0] := 0X;
  187. curScope.dsc.dsc := NIL;
  188. NEW(o);
  189. o.class := Typ;
  190. o.name := "CHAR";
  191. o.next := NIL;
  192. o.dsc := NIL;
  193. charType := MakeType(Char, 1);
  194. o.type := charType;
  195. curScope.dsc.next := o;
  196. NEW(o);
  197. o.class := Typ;
  198. o.name := "INTEGER";
  199. o.next := NIL;
  200. o.dsc := NIL;
  201. intType := MakeType(Int, 4);
  202. o.type := intType;
  203. curScope.dsc.next.next := o;
  204. noType := MakeType(NoTyp, 4)
  205. END Init;
  206. PROCEDURE Display*;
  207. VAR h, p: Object;
  208. BEGIN
  209. Out.String("Содержимое символьной таблицы:"); Out.Ln;
  210. h := curScope;
  211. WHILE h # NIL DO
  212. p := h.next;
  213. WHILE p # NIL DO
  214. Out.String(" "); Out.String(p.name); Out.String(": ");
  215. IF p.class = Head THEN Out.String("заголовочный")
  216. ELSIF p.class = Var THEN
  217. Out.String("переменная типа "); OutType(p.type)
  218. ELSIF p.class = Typ THEN Out.String("тип")
  219. ELSIF p.class = Mod THEN Out.String("модуль")
  220. END;
  221. Out.Ln;
  222. p := p.next
  223. END;
  224. IF h.dsc # NIL THEN
  225. Out.String("Следующая область видимости:"); Out.Ln
  226. END;
  227. h := h.dsc
  228. END
  229. END Display;
  230. END SymTable.