crt.mod
来自「一个Modula-2语言分析器」· MOD 代码 · 共 1,434 行 · 第 1/4 页
MOD
1,434 行
ClearMarkList(visited);
curSy := firstNt; (*get direct successors of nonterminals*)
WHILE curSy <= lastNt DO
GetSym(curSy, sn); CompFol(sn.struct);
INC(curSy)
END;
curSy := 0; (*add indirect successors to follow.ts*)
WHILE curSy <= lastNt - firstNt DO
ClearMarkList(visited); Complete(curSy);
INC(curSy);
END;
END CompFollowSets;
(* CompAnySets Compute all any-sets
----------------------------------------------------------------------*)
PROCEDURE CompAnySets;
VAR
curSy: INTEGER;
sn: SymbolNode;
PROCEDURE LeadingAny (gp: INTEGER; VAR a: GraphNode): BOOLEAN;
VAR
gn: GraphNode;
BEGIN
IF gp <= 0 THEN RETURN FALSE END;
GetNode(gp, gn);
IF (gn.typ = any) THEN a := gn; RETURN TRUE
ELSE
RETURN (gn.typ = alt) & (LeadingAny(gn.p1, a)
OR LeadingAny(gn.p2, a))
OR ((gn.typ=opt) OR (gn.typ=iter)) & LeadingAny(gn.p1, a)
OR DelNode(gn) & LeadingAny(gn.next, a)
END
END LeadingAny;
PROCEDURE FindAS (gp: INTEGER);
VAR
gn, gn2, a: GraphNode;
s1, s2: Set;
p: INTEGER;
BEGIN
WHILE gp > 0 DO
GetNode(gp, gn);
IF (gn.typ=opt) OR (gn.typ=iter) THEN
FindAS(gn.p1);
IF LeadingAny(gn.p1, a) THEN
CompExpected(ABS(gn.next), curSy, s1);
Sets.Differ(set[a.p1], s1)
END
ELSIF gn.typ = alt THEN
p := gp; Sets.Clear(s1);
WHILE p # 0 DO
GetNode(p, gn2); FindAS(gn2.p1);
IF LeadingAny(gn2.p1, a) THEN
CompExpected(gn2.p2, curSy, s2); Sets.Unite(s2, s1);
Sets.Differ(set[a.p1], s2)
ELSE
CompFirstSet(gn2.p1, s2); Sets.Unite(s1, s2)
END;
p := gn2.p2
END
END;
gp := gn.next
END
END FindAS;
BEGIN
curSy := firstNt;
WHILE curSy <= lastNt DO (* for all nonterminals *)
GetSym(curSy, sn); FindAS(sn.struct);
INC(curSy)
END
END CompAnySets;
(* CompSyncSets Compute follow symbols of sync-nodes
----------------------------------------------------------------------*)
PROCEDURE CompSyncSets;
VAR
curSy: INTEGER;
sn: SymbolNode;
visited: MarkList;
PROCEDURE CompSync (gp: INTEGER);
VAR
s: Set;
gn: GraphNode;
BEGIN
WHILE (gp > 0) & ~ Sets.In(visited, gp) DO
GetNode(gp, gn); Sets.Incl(visited, gp);
IF gn.typ = sync THEN
CompExpected(ABS(gn.next), curSy, s);
Sets.Incl(s, eofSy); Sets.Unite(set[0], s);
gn.p1 := NewSet(s); PutNode(gp, gn)
ELSIF gn.typ = alt THEN CompSync(gn.p1); CompSync(gn.p2)
ELSIF (gn.typ=opt) OR (gn.typ=iter) THEN CompSync(gn.p1)
END;
gp := gn.next
END
END CompSync;
BEGIN
curSy := firstNt; ClearMarkList(visited);
WHILE curSy <= lastNt DO
GetSym(curSy, sn); CompSync(sn.struct);
INC(curSy);
END
END CompSyncSets;
(* CompDeletableSymbols Compute all deletable symbols and print them
----------------------------------------------------------------------*)
PROCEDURE CompDeletableSymbols;
VAR
changed, none: BOOLEAN;
i: INTEGER;
sn: SymbolNode;
BEGIN
REPEAT
changed := FALSE;
i := firstNt;
WHILE i <= lastNt DO (*for all nonterminals*)
GetSym(i, sn);
IF ~ sn.deletable & DelGraph(sn.struct) THEN
sn.deletable := TRUE; PutSym(i, sn); changed := TRUE
END;
INC(i)
END;
UNTIL ~ changed;
FileIO.WriteString(CRS.lst, "Deletable symbols:");
i := firstNt; none := TRUE;
WHILE i <= lastNt DO
GetSym(i, sn);
IF sn.deletable THEN
none := FALSE;
FileIO.WriteLn(CRS.lst); FileIO.WriteString(CRS.lst, " ");
FileIO.WriteString(CRS.lst, sn.name)
END;
INC(i);
END;
IF none THEN FileIO.WriteString(CRS.lst, " -- none --") END;
FileIO.WriteLn(CRS.lst);
END CompDeletableSymbols;
(* CompSymbolSets Get first-sets, follow-sets, and sync-set
----------------------------------------------------------------------*)
PROCEDURE CompSymbolSets;
VAR
i: INTEGER;
sn: SymbolNode;
BEGIN
MovePragmas;
CompDeletableSymbols;
CompFirstSets;
CompFollowSets;
CompAnySets;
CompSyncSets;
IF ddt["F"] THEN
i := firstNt;
FileIO.WriteString(CRS.lst, "List of first & follow symbols:");
FileIO.WriteLn(CRS.lst); FileIO.WriteLn(CRS.lst);
WHILE i <= lastNt DO (* for all nonterminals *)
GetSym(i, sn);
FileIO.WriteString(CRS.lst, sn.name); FileIO.WriteLn(CRS.lst);
FileIO.WriteString(CRS.lst, "first: ");
PrintSet(CRS.lst, first[i - firstNt].ts, 10);
FileIO.WriteString(CRS.lst, "follow: ");
PrintSet(CRS.lst, follow[i - firstNt].ts, 10);
FileIO.WriteLn(CRS.lst);
INC(i);
END;
i := 0;
FileIO.WriteLn(CRS.lst); FileIO.WriteLn(CRS.lst);
FileIO.WriteString(CRS.lst, "List of sets (ANY, SYNC): ");
IF maxSet < 0 THEN FileIO.WriteString(CRS.lst, " -- none --");
ELSE FileIO.WriteLn(CRS.lst);
END;
WHILE i <= maxSet DO
FileIO.WriteString(CRS.lst, " set[");
FileIO.WriteInt(CRS.lst, i, 2);
FileIO.WriteString(CRS.lst, "] = ");
PrintSet(CRS.lst, set[i], 16);
INC(i)
END;
FileIO.WriteLn(CRS.lst);
END;
END CompSymbolSets;
(* GetFirstSet Get precomputed first-set for nonterminal sp
----------------------------------------------------------------------*)
PROCEDURE GetFirstSet (sp: INTEGER; VAR s: Set);
BEGIN
s := first[sp - firstNt].ts
END GetFirstSet;
(* GetFollowSet Get precomputed follow-set for nonterminal snix
----------------------------------------------------------------------*)
PROCEDURE GetFollowSet (sp: INTEGER; VAR s: Set);
BEGIN
s := follow[sp - firstNt].ts
END GetFollowSet;
(* GetSet Get set with index nr
----------------------------------------------------------------------*)
PROCEDURE GetSet (nr: INTEGER; VAR s: Set);
BEGIN
s := set[nr]
END GetSet;
(* PrintSymbolTable Print symbol table
----------------------------------------------------------------------*)
PROCEDURE PrintSymbolTable;
VAR
i: INTEGER;
PROCEDURE WriteBool (b: BOOLEAN);
BEGIN
IF b THEN FileIO.WriteString(CRS.lst, " TRUE ");
ELSE FileIO.WriteString(CRS.lst, " FALSE");
END;
END WriteBool;
PROCEDURE WriteTyp1 (typ: INTEGER);
BEGIN
CASE typ OF
unknown: FileIO.WriteString(CRS.lst, " unknown");
| t : FileIO.WriteString(CRS.lst, " t ");
| pr : FileIO.WriteString(CRS.lst, " pr ");
| nt : FileIO.WriteString(CRS.lst, " nt ");
END;
END WriteTyp1;
BEGIN (* PrintSymbolTable *)
FileIO.WriteString(CRS.lst, "SymbolTable:");
FileIO.WriteLn(CRS.lst); FileIO.WriteLn(CRS.lst);
FileIO.WriteString(CRS.lst, "nr definition ");
IF (*CRT.*) ddt["N"] OR (*CRT.*) symNames THEN
FileIO.WriteString(CRS.lst, "constant ")
END;
FileIO.WriteString(CRS.lst, "typ hasAttrs struct del line");
FileIO.WriteLn(CRS.lst); FileIO.WriteLn(CRS.lst);
i := 0;
WHILE i < maxSymbols DO
FileIO.WriteInt(CRS.lst, i, 3); FileIO.WriteText(CRS.lst, "", 3);
FileIO.WriteText(CRS.lst, st^[i].name, 26);
IF (*CRT.*) ddt["N"] OR (*CRT.*) symNames THEN
IF i <= maxT THEN
FileIO.WriteText(CRS.lst, st^[i].constant, 16);
ELSE
FileIO.WriteText(CRS.lst, "", 16);
END;
END;
WriteTyp1(st^[i].typ);
WriteBool(st^[i].attrPos.beg >= FileIO.Long0);
FileIO.WriteInt(CRS.lst, st^[i].struct, 5);
WriteBool(st^[i].deletable);
FileIO.WriteInt(CRS.lst, st^[i].line, 5);
FileIO.WriteLn(CRS.lst);
IF i = maxT THEN i := firstNt ELSE INC(i) END
END;
FileIO.WriteLn(CRS.lst); FileIO.WriteLn(CRS.lst);
END PrintSymbolTable;
(* NewClass Define a new character class
----------------------------------------------------------------------*)
PROCEDURE NewClass (name: Name; set: Set): INTEGER;
BEGIN
INC(maxC); IF maxC > maxClasses THEN Restriction(4, maxClasses) END;
IF name[0] = "#" THEN
name[1] := CHR(ORD("A") + dummyName); INC(dummyName)
END;
chClass[maxC].name := name; chClass[maxC].set := NewSet(set);
RETURN maxC
END NewClass;
(* ClassWithName Return index of class with name n
----------------------------------------------------------------------*)
PROCEDURE ClassWithName (n: Name): INTEGER;
VAR
i: INTEGER;
BEGIN
i := maxC;
WHILE (i >= 0) & (FileIO.Compare(chClass[i].name, n) # 0) DO
DEC(i)
END;
RETURN i
END ClassWithName;
(* ClassWithSet Return index of class with the specified set
----------------------------------------------------------------------*)
PROCEDURE ClassWithSet (s: Set): INTEGER;
VAR
i: INTEGER;
BEGIN
i := maxC;
WHILE (i >= 0) & ~ Sets.Equal(set[chClass[i].set], s) DO DEC(i) END;
RETURN i
END ClassWithSet;
(* GetClass Return character class n
----------------------------------------------------------------------*)
PROCEDURE GetClass (n: INTEGER; VAR s: Set);
BEGIN
GetSet(chClass[n].set, s);
END GetClass;
(* GetClassName Get the name of class n
----------------------------------------------------------------------*)
PROCEDURE GetClassName (n: INTEGER; VAR name: Name);
BEGIN
name := chClass[n].name
END GetClassName;
(* XRef Produce a cross reference listing of all symbols
----------------------------------------------------------------------*)
PROCEDURE XRef;
CONST
maxLineLen = 80;
TYPE
ListPtr = POINTER TO ListNode;
ListNode = RECORD
next: ListPtr;
line: INTEGER;
END;
ListHdr = RECORD
name: Name;
lptr: ListPtr;
END;
VAR
gn: GraphNode;
col, i: INTEGER;
l, p, q: ListPtr;
sn: SymbolNode;
xList: ARRAY [0 .. maxSymbols] OF ListHdr;
BEGIN (* XRef *)
IF maxT <= 0 THEN RETURN END;
MovePragmas;
(* initialize cross reference list *)
i := 0;
WHILE i <= lastNt DO (* for all symbols *)
GetSym(i, sn); xList[i].name := sn.name; xList[i].lptr := NIL;
IF i = maxP THEN i := firstNt ELSE INC(i) END
END;
(* search lines where symbol has been referenced *)
i := 1;
WHILE i <= nNodes DO (* for all graph nodes *)
GetNode(i, gn);
IF (gn.typ = t) OR (gn.typ = wt) OR (gn.typ = nt) THEN
Storage.ALLOCATE(l, SYSTEM.TSIZE(ListNode));
l^.next := xList[gn.p1].lptr; l^.line := gn.line;
xList[gn.p1].lptr := l
END;
INC(i);
END;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?