⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cr.frm

📁 一个Modula-2语言分析器
💻 FRM
字号:
(* CR   Main Module of Coco/R
   ==   =====================

   This is a compiler generator that produces a scanner and a parser
   from an attributed grammar, and optionally a complete small compiler.

   Original code in Oberon by Hanspeter Moessenboeck, ETH Zurich
   Ported at ETH to Apple Modula, and thence to JPI-2 Modula.

   JPI version of 27 January 1991 was then modified to make more
   portable by Pat Terry, January - October 1992

   This is the WinTel version


Usage:
          COCOR [-options] GrammarName[.atg] [$options]

Input:
  attributed grammar   input grammar
  scanner.frm          frame file
  parser.frm           frame file
  compiler.frm         frame file (optional)

(Frame files must be in the sme directory as the grammar, or may be
found on a path specified by DOS environment variable CRFRAMES).

Output:
  <GrammarName>S.def + mod  generated scanner
  <GrammarName>P.def + mod  generated parser
  <GrammarName>.err         error numbers and corresponding error messages
  <GrammarName>.lst         source listing with error messages and trace output

Optionally

  <GrammarName>G.def + mod  generated symbolic names
  <GrammarName>.mod         generated compiler main module

Implementation restrictions
  1  too many nodes in graph (>1500)                 CRT.NewNode
  2  too many symbols (>500)                         CRT.NewSym, MovePragmas
  3  too many sets (>256 ANY-syms or SYNC syms)      CRT.NewSet,
  4  too many character classes (>250)               CRT.NewClass
  5  too many conditions in generated code (>100)    CRX.NewCondSet
  6  too many token names in "NAMES" (>100)          CRT.NewName
  7  too many states in automata (>500)              CRA.NewState

Trace output
(To activate a trace switch, write "${letter}" in the input grammar, or
invoke Coco with a second command line parameter)

  A  Prints states of automaton

  C  Generates complete compiler module

  D  Suppresses Def Mod generation

  F  Prints start symbols and followers of nonterminals.

  G  Prints the top-down graph.

  I  Trace of start symbol set computation.

  L  Forces a listing (otherwise a listing is only printed if errors are found).
  
  M  Suppresses FORWARD declarations in parser (for multipass compilers).

  N  Uses default names for symbol value constants.  This generates an
     extra module <grammar name>G, and corresponding import statements
     using constant names instead of numbers for symbols in parser and
     scanner.
     The constants are used unqualified and hence all needed constants
     have to be imported; so a complete import list for these constants
     is generated.
     There is no decision whether a constant is actually needed.

     The default conventions are (only terminals or pragmas can have names):
     single character   -->  <ASCII name (lowercase)>Sym
          eg. "+"       -->  plusSym
     character string   -->  <string>Sym
          eg. "PROGRAM" -->  PROGRAMSym
     scanner token      -->  <token name>Sym
          eg. ident     -->  identSym

  O  Trace of follow set computation (not yet implemented).

  P  Generates parser only

  S  Prints the symbol list.

  T  Suppresses generation of def and mod files (grammar tests only).

  X  Prints a cross reference list.

==========================================================================*)

MODULE -->Grammar;

  FROM -->Scanner IMPORT lst, src, errors, directory, Error, CharAt;
  FROM -->Parser IMPORT Parse;
  IMPORT CRC, CRT, CRA, CRP, CRS, CRX, FileIO, Storage;
  IMPORT SYSTEM (* for TSIZE only *);

  CONST
    ATGExt = ".atg";
    LSTExt = ".lst";
    Version = "1.48";
    ReleaseDate = "9 July 1999";

  TYPE
    INT32 = FileIO.INT32;

  VAR
    Options,
    GrammarName,
    ATGFileName,
    lstFileName: ARRAY [0 .. 63] OF CHAR;
    ll1:         BOOLEAN; (* TRUE, if grammar is LL(1) *)
    ok:          BOOLEAN; (* TRUE, if grammar tests ok so far *)

  MODULE ListHandler;
  (* ------------------- Source Listing and Error handler -------------- *)
  IMPORT FileIO, Storage, SYSTEM;
  IMPORT lst, CharAt, errors, INT32;
  EXPORT StoreError, PrintListing;

  TYPE
    Err = POINTER TO ErrDesc;
    ErrDesc = RECORD
      nr, line, col: INTEGER;
      next: Err
    END;

  CONST
    tab = 11C;

  VAR
    firstErr, lastErr: Err;
    Extra: INTEGER;

  PROCEDURE StoreError (nr, line, col: INTEGER; pos: INT32);
  (* Store an error message for later printing *)
    VAR
      nextErr: Err;
    BEGIN
      Storage.ALLOCATE(nextErr, SYSTEM.TSIZE(ErrDesc));
      nextErr^.nr := nr; nextErr^.line := line; nextErr^.col := col;
      nextErr^.next := NIL;
      IF firstErr = NIL
        THEN firstErr := nextErr
        ELSE lastErr^.next := nextErr
      END;
      lastErr := nextErr;
      INC(errors)
    END StoreError;

  PROCEDURE GetLine (VAR pos: INT32;
                     VAR line: ARRAY OF CHAR;
                     VAR eof: BOOLEAN);
  (* Read a source line. Return empty line if eof *)
    VAR
      ch: CHAR;
      i:  CARDINAL;
    BEGIN
      i := 0; eof := FALSE; ch := CharAt(pos); INC(pos);
      WHILE (ch # FileIO.CR) & (ch # FileIO.LF) & (ch # FileIO.EOF) DO
        line[i] := ch; INC(i); ch := CharAt(pos); INC(pos);
      END;
      eof := (i = 0) & (ch = FileIO.EOF); line[i] := 0C;
      IF ch = FileIO.CR THEN (* check for MsDos *)
        ch := CharAt(pos);
        IF ch = FileIO.LF THEN INC(pos); Extra := 0 END
      END
    END GetLine;

  PROCEDURE PrintErr (line: ARRAY OF CHAR; nr, col: INTEGER);
  (* Print an error message *)

    PROCEDURE Msg (s: ARRAY OF CHAR);
      BEGIN
        FileIO.WriteString(lst, s)
      END Msg;

    PROCEDURE Pointer;
      VAR
        i: INTEGER;
      BEGIN
        FileIO.WriteString(lst, "*****  ");
        i := 0;
        WHILE i < col + Extra - 2 DO
          IF line[i] = tab
            THEN FileIO.Write(lst, tab)
            ELSE FileIO.Write(lst, ' ')
          END;
          INC(i)
        END;
        FileIO.WriteString(lst, "^ ")
      END Pointer;

    BEGIN
      Pointer;
      CASE nr OF
      -->Errors
      | 102: Msg("string literal may not extend over line end");
      | 103: Msg("a literal must not have attributes");
      | 104: Msg("this symbol kind not allowed in production");
      | 105: Msg("attribute mismatch between declaration and use");
      | 106: Msg("undefined string in production");
      | 107: Msg("name declared twice");
      | 108: Msg("this type not allowed on left side of production");
      | 109: Msg("earlier semantic action was not terminated");
      | 111: Msg("no production found for grammar name");
      | 112: Msg("grammar symbol must not have attributes");
      | 113: Msg("a literal must not be declared with a structure")
      | 114: Msg("semantic action not allowed here")
      | 115: Msg("undefined name")
      | 116: Msg("attributes not allowed in token declaration")
      | 117: Msg("name does not match grammar name")
      | 118: Msg("unacceptable constant value")
      | 119: Msg("may not ignore CHR(0)")
      | 120: Msg("token may not be empty")
      | 121: Msg("token must not start with an iteration")
      | 122: Msg("only characters allowed in comment declaration")
      | 123: Msg("only terminals may be weak")
      | 124: Msg("literal tokens may not contain white space")
      | 125: Msg("comment delimiter must be 1 or 2 characters long")
      | 126: Msg("character set contains more than one character")
      | 127: Msg("could not make deterministic automaton")
      | 128: Msg("semantic action text too long - please split it")
      | 129: Msg("literal tokens may not be empty")
      ELSE Msg("Error: "); FileIO.WriteInt(lst, nr, 1);
      END;
      FileIO.WriteLn(lst)
    END PrintErr;

  PROCEDURE PrintListing;
  (* Print a source listing with error messages *)
    VAR
      nextErr:   Err;
      eof:       BOOLEAN;
      lnr, errC: INTEGER;
      srcPos:    INT32;
      line:      ARRAY [0 .. 255] OF CHAR;
    BEGIN
      FileIO.WriteString(lst, "Listing:");
      FileIO.WriteLn(lst); FileIO.WriteLn(lst);
      srcPos := FileIO.Long0; nextErr := firstErr;
      GetLine(srcPos, line, eof); lnr := 1; errC := 0;
      WHILE ~ eof DO
        FileIO.WriteInt(lst, lnr, 5); FileIO.WriteString(lst, "  ");
        FileIO.WriteString(lst, line); FileIO.WriteLn(lst);
        WHILE (nextErr # NIL) & (nextErr^.line = lnr) DO
          PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
          nextErr := nextErr^.next
        END;
        GetLine(srcPos, line, eof); INC(lnr);
      END;
      IF nextErr # NIL THEN
        FileIO.WriteInt(lst, lnr, 5); FileIO.WriteLn(lst);
        WHILE nextErr # NIL DO
          PrintErr(line, nextErr^.nr, nextErr^.col); INC(errC);
          nextErr := nextErr^.next
        END
      END;
      FileIO.WriteLn(lst);
      FileIO.WriteInt(lst, errC, 5); FileIO.WriteString(lst, " error");
      IF errC # 1 THEN FileIO.Write(lst, "s") END;
      FileIO.WriteLn(lst); FileIO.WriteLn(lst); FileIO.WriteLn(lst);
    END PrintListing;

  BEGIN
    firstErr := NIL; Extra := 1;
  END ListHandler;

  PROCEDURE SetOption (s: ARRAY OF CHAR);
  (* Set compiler options *)
    VAR
      i: CARDINAL;
    BEGIN
      i := 1;
      WHILE s[i] # 0C DO
        s[i] := CAP(s[i]);
        IF (s[i] >= "A") AND (s[i] <= "Z") THEN CRT.ddt[s[i]] := TRUE END;
        INC(i);
      END;
    END SetOption;

  PROCEDURE Msg (S: ARRAY OF CHAR);
    BEGIN
      FileIO.WriteString(FileIO.StdOut, S); FileIO.WriteLn(FileIO.StdOut);
    END Msg;

  (* --------------------------- Help ------------------------------- *)

  PROCEDURE Help;
    BEGIN
      Msg("Usage: COCOR [-Options] [Grammar[.atg]] [-Options]");
      Msg("Example: COCOR -mcs Test");
      Msg("");
      Msg("Options are");
      Msg("a  - Trace automaton");
      Msg("c  - Generate compiler module");
      Msg("d  - Suppress generation of Definition Modules");
      Msg("f  - Give Start and Follower sets");
      Msg("g  - Print top-down graph");
      Msg("i  - Trace start set computations");
      Msg("l  - Force listing");
      Msg("m  - (Multipass) Suppress FORWARD declarations");
      Msg("n  - Generate symbolic names");
      Msg("p  - Generate parser only");
      Msg("s  - Print symbol table");
      Msg("t  - Grammar tests only - no code generated");
      Msg("x  - Print cross reference list");
      Msg("COMPILER.FRM, SCANNER.FRM and PARSER.FRM must be in the working directory,");
      Msg("or on the path specified by the environment variable CRFRAMES");
    END Help;

  BEGIN (* CR *)
    FileIO.WriteString(FileIO.StdOut, "Coco/R (WinTel) - Compiler-Compiler V");
    FileIO.WriteString(FileIO.StdOut, Version);
    FileIO.WriteLn(FileIO.StdOut);
    FileIO.WriteString(FileIO.StdOut, "Released by Pat Terry ");
    FileIO.WriteString(FileIO.StdOut, ReleaseDate);
    FileIO.WriteLn(FileIO.StdOut);
    FileIO.NextParameter(GrammarName);
    IF (GrammarName[0] = "?")
        OR (GrammarName[0] = "/") AND (GrammarName[1] = "?") THEN
      Help; FileIO.QuitExecution
    END;
    IF GrammarName[0] = 0C THEN
      FileIO.WriteString(FileIO.StdOut, "(COCOR ? gives short help screen)");
      FileIO.WriteLn(FileIO.StdOut);
    END;
    WHILE (GrammarName[0] = "-") OR (GrammarName[0] = "/") DO
      (* accept options before filename *)
      SetOption(GrammarName); FileIO.NextParameter(GrammarName)
    END;
    ok := GrammarName[0] # 0C;
    REPEAT
      IF ~ ok THEN
        FileIO.WriteString(FileIO.StdOut, "Grammar[.atg] ? : ");
        FileIO.ReadString(FileIO.StdIn, GrammarName);
        IF ~ FileIO.Okay THEN FileIO.QuitExecution END;
        FileIO.ReadLn(FileIO.StdIn);
      END;
      FileIO.AppendExtension(GrammarName, ATGExt, ATGFileName);
      GrammarName := ATGFileName;
      FileIO.Open(src, GrammarName, FALSE);
      ok := FileIO.Okay;
      IF ~ ok THEN
        FileIO.WriteString(FileIO.StdOut, "File <");
        FileIO.WriteString(FileIO.StdOut, GrammarName);
        FileIO.WriteString(FileIO.StdOut, "> not found.");
        FileIO.WriteLn(FileIO.StdOut);
      END
    UNTIL ok;
    FileIO.NextParameter(Options);
    IF Options[0] # 0C THEN SetOption(Options) END;
    FileIO.ExtractDirectory(GrammarName, directory);
    FileIO.ChangeExtension(GrammarName, LSTExt, lstFileName);
    FileIO.Open(lst, lstFileName, TRUE);
    FileIO.WriteString(lst, "Coco/R - Compiler-Compiler V");
    FileIO.WriteString(lst, Version);
    FileIO.WriteLn(lst);
    FileIO.WriteString(lst, "Released by Pat Terry ");
    FileIO.WriteString(lst, ReleaseDate);
    FileIO.WriteLn(lst);
    FileIO.WriteString(lst, "Source file: ");
    FileIO.WriteString(lst, GrammarName);
    FileIO.WriteLn(lst); FileIO.WriteLn(lst);
    FileIO.WriteLn(FileIO.StdOut);
    FileIO.WriteString(FileIO.StdOut, "parsing file ");
    FileIO.WriteString(FileIO.StdOut, GrammarName);
    FileIO.WriteLn(FileIO.StdOut);
    CRS.Error := StoreError;
    CRP.Parse;
    IF errors = 0 THEN
      Msg("testing grammar");
      FileIO.WriteString(lst, "Grammar Tests:");
      FileIO.WriteLn(lst); FileIO.WriteLn(lst);
      CRT.CompSymbolSets;
      CRT.TestCompleteness(ok);
      IF ok THEN CRT.TestIfAllNtReached(ok) END;
      IF ok THEN CRT.FindCircularProductions(ok) END;
      IF ok THEN CRT.TestIfNtToTerm(ok) END;
      IF ok THEN CRT.LL1Test(ll1) END;
      FileIO.WriteLn(lst);
      IF CRT.genScanner & CRT.ddt["A"] THEN CRA.PrintStates END;
      IF ~ ok OR ~ ll1 OR CRT.ddt["L"] OR CRT.ddt["X"] THEN
        Msg("listing");
        PrintListing; IF CRT.ddt["X"] THEN CRT.XRef; END;
      END;
      IF CRT.ddt["N"] OR CRT.symNames THEN
        Msg("symbol name assignment");
        CRT.AssignSymNames(CRT.ddt["N"], CRT.symNames);
      END;
      IF ok AND ~ CRT.ddt["T"] THEN
        Msg("generating parser");
        CRX.GenCompiler;
        IF CRT.genScanner AND ~ CRT.ddt["P"] THEN
          Msg("generating scanner");
          CRA.WriteScanner;
        END;
        IF CRT.ddt["C"] THEN
          Msg("generating compiler");
          CRC.WriteDriver;
        END;
        CRX.WriteStatistics;
      END;
      IF ~ ok THEN Msg("Compilation ended with errors in grammar tests.");
        ELSIF ~ ll1 THEN Msg("Compilation ended with LL(1) errors.");
        ELSE Msg("Compilation completed. No errors detected.");
      END;
    ELSE
      Msg("listing");
      PrintListing; IF CRT.ddt["X"] THEN CRT.XRef END;
      Msg("*** errors detected ***");
    END;
    IF CRT.ddt["G"] THEN CRT.PrintGraph END;
    IF CRT.ddt["S"] THEN CRT.PrintSymbolTable END;
    FileIO.Close(lst); FileIO.Close(src);
  END -->Grammar.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -