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 + -
显示快捷键?