| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- MODULE SymTable;
- IMPORT Out, S := Scanner;
- CONST
- (* Классы объектов (и одновременно режимы предметов) *)
- Head* = 0; Const* = 1; Var* = 2; Par* = 3; Typ* = 5; Mod* = 8;
- (*Par - это вар-параметр*)
- (* Формы типов *)
- Char* = 3;
- Int* = 4;
- NoTyp* = 9;
- Proc* = 10;
- TYPE
- Object* = POINTER TO ObjDesc;
- Type* = POINTER TO TypeDesc;
- TypeDesc* = RECORD
- form*: INTEGER; (* Форма типа *)
- size*: INTEGER; (* Размер типа в байтах *)
- nofpar*: INTEGER; (* Количество параметров *)
- base*: Type; (* Тип возвращаемого значения процедуры *)
- dsc*: Object (* Список формальных параметров процедуры *)
- END;
- ObjDesc* = RECORD
- class*: INTEGER; (* Класс объекта *)
- type*: Type;
- name*: ARRAY 32 OF CHAR;
- val*: INTEGER;
- next*, dsc*: Object
- END;
- (* Назначение поля val в зависимости от значения поля class (в Object):
- class | val
- ------+-----------------------
- Var | адрес переменной
- Const | значение константы
- Type | не используется (пока) *)
- VAR
- curScope: Object;
- charType*, intType*, noType*: Type;
- (*Для удобочитаемой отладки*)
- PROCEDURE OutType*(t: Type);
- BEGIN
- IF t.form = Int THEN Out.String("целое число")
- ELSIF t.form = Char THEN Out.String("литера")
- ELSE Out.Int(t.form, 0)
- END
- END OutType;
- PROCEDURE MakeType(form, size: INTEGER): Type;
- VAR t: Type;
- BEGIN
- NEW(t);
- t.form := form;
- t.size := size;
- RETURN t
- END MakeType;
- PROCEDURE NewObj*(name: ARRAY OF CHAR; class: INTEGER): Object;
- VAR o, p: Object;
- BEGIN
- p := curScope;
- WHILE (p.next # NIL) & (p.next.name # name) DO p := p.next END;
- IF p.next = NIL THEN
- NEW(o);
- o.class := class;
- o.name := name;
- o.next := NIL;
- p.next := o
- ELSE
- o := p.next;
- S.Mark("Такой объект уже есть")
- END;
- RETURN o
- END NewObj;
- PROCEDURE ThisObjInModule*(mod: Object): Object;
- VAR o: Object;
- BEGIN
- o := mod.dsc;
- WHILE (o # NIL) & (o.name # S.id) DO o := o.next END;
- RETURN o
- END ThisObjInModule;
- (*Предусловие: sym = S.ident*)
- PROCEDURE ThisObj*(): Object;
- VAR o, p: Object;
- BEGIN
- p := curScope;
- WHILE p # NIL DO
- o := p.next;
- WHILE (o # NIL) & (o.name # S.id) DO
- o := o.next
- END;
- IF o = NIL THEN p := p.dsc
- ELSE p := NIL
- END
- END;
- RETURN o
- END ThisObj;
- (*Добавить процедуру в модуль*)
- PROCEDURE AddProc(m: Object; name: ARRAY OF CHAR; key: INTEGER): Object;
- VAR o, g: Object;
- BEGIN
- NEW(o);
- IF m.dsc = NIL THEN
- m.dsc := o
- ELSE
- g := m.dsc;
- WHILE g.next # NIL DO g := g.next END;
- g.next := o
- END;
- o.class := Const;
- o.name := name;
- o.val := key;
- o.next := NIL;
- o.dsc := NIL;
- o.type := MakeType(Proc, 4);
- o.type.nofpar := 0;
- o.type.base := noType;
- RETURN o
- END AddProc;
- (*Добавить формальный параметр в процедуру*)
- PROCEDURE AddParam(proc: Object; name: ARRAY OF CHAR; varParam: BOOLEAN;
- type: Type; offset: INTEGER);
- VAR o, p: Object;
- BEGIN
- NEW(p);
- IF proc.type.dsc = NIL THEN
- proc.type.dsc := p
- ELSE
- o := proc.type.dsc;
- WHILE o.next # NIL DO o := o.next END;
- o.next := p
- END;
- INC(proc.type.nofpar);
- IF varParam THEN p.class := Par ELSE p.class := Var END;
- p.name := name;
- p.val := offset; (*?*)
- p.type := type;
- p.next := NIL;
- p.dsc := NIL
- END AddParam;
- PROCEDURE Import*(alias, modname: ARRAY OF CHAR);
- VAR m, o, p: Object;
- tp: Type;
- BEGIN
- IF modname = "Out" THEN
- NEW(m);
- curScope.next := m;
- m.class := Mod;
- m.name := alias;
- m.val := 1; (*!FIXME*)
- m.type := NIL;
- m.dsc := NIL;
- (*Out.Char(ch)*)
- o := AddProc(m, "Char", 0);
- AddParam(o, "ch", FALSE, charType, 4);
- (*Out.Int(n, w)*)
- o := AddProc(m, "Int", 1);
- AddParam(o, "n", FALSE, intType, 4);
- AddParam(o, "w", FALSE, intType, 8);
- (*Out.Ln*)
- o := AddProc(m, "Ln", 2)
- ELSIF modname = "In" THEN
- NEW(m);
- m.next := curScope.next;
- curScope.next := m;
- m.class := Mod;
- m.name := alias;
- m.val := 2; (*!FIXME*)
- m.type := NIL;
- m.dsc := NIL;
- (*In.Int(n)*)
- o := AddProc(m, "Int", 0);
- AddParam(o, "n", TRUE, intType, 4)
- ELSE
- S.Mark("Такого модуля не существует")
- END;
- Out.String("Импортируем "); Out.String(modname);
- Out.String(" под псевдонимом "); Out.String(alias);
- Out.Char("."); Out.Ln
- END Import;
- PROCEDURE Init*;
- VAR o: Object;
- BEGIN
- NEW(curScope);
- curScope.class := Head;
- curScope.name[0] := 0X;
- curScope.next := NIL;
- NEW(curScope.dsc);
- curScope.dsc.class := Head;
- curScope.dsc.name[0] := 0X;
- curScope.dsc.dsc := NIL;
- NEW(o);
- o.class := Typ;
- o.name := "CHAR";
- o.next := NIL;
- o.dsc := NIL;
- charType := MakeType(Char, 1);
- o.type := charType;
- curScope.dsc.next := o;
- NEW(o);
- o.class := Typ;
- o.name := "INTEGER";
- o.next := NIL;
- o.dsc := NIL;
- intType := MakeType(Int, 4);
- o.type := intType;
- curScope.dsc.next.next := o;
- noType := MakeType(NoTyp, 4)
- END Init;
- PROCEDURE Display*;
- VAR h, p: Object;
- BEGIN
- Out.String("Содержимое символьной таблицы:"); Out.Ln;
- h := curScope;
- WHILE h # NIL DO
- p := h.next;
- WHILE p # NIL DO
- Out.String(" "); Out.String(p.name); Out.String(": ");
- IF p.class = Head THEN Out.String("заголовочный")
- ELSIF p.class = Var THEN
- Out.String("переменная типа "); OutType(p.type)
- ELSIF p.class = Typ THEN Out.String("тип")
- ELSIF p.class = Mod THEN Out.String("модуль")
- END;
- Out.Ln;
- p := p.next
- END;
- IF h.dsc # NIL THEN
- Out.String("Следующая область видимости:"); Out.Ln
- END;
- h := h.dsc
- END
- END Display;
- END SymTable.
|