crs.mod

来自「一个Modula-2语言分析器」· MOD 代码 · 共 373 行

MOD
373
字号
IMPLEMENTATION MODULE CRS;

(* Scanner generated by Coco/R - assuming FileIO library will be available. *)

IMPORT FileIO, Storage;

CONST
  noSym   = 41; (*error token code*)
  (* not only for errors but also for not finished states of scanner analysis *)
  eof     = 32C (* MS-DOS Keyboard eof char *);
  EOF     = FileIO.EOF;
  EOL     = FileIO.CR;
  CR      = FileIO.CR;
  LF      = FileIO.LF;
  Long0   = FileIO.Long0;
  Long1   = FileIO.Long1;
  BlkSize = 16384;
TYPE
  BufBlock   = ARRAY [0 .. BlkSize-1] OF CHAR;
  Buffer     = ARRAY [0 .. 31] OF POINTER TO BufBlock;
  StartTable = ARRAY [0 .. 255] OF INTEGER;
  GetCH      = PROCEDURE (INT32): CHAR;
VAR
  lastCh,
  ch:        CHAR;       (*current input character*)
  curLine:   INTEGER;    (*current input line (may be higher than line)*)
  lineStart: INT32;      (*start position of current line*)
  apx:       INT32;      (*length of appendix (CONTEXT phrase)*)
  oldEols:   INTEGER;    (*number of EOLs in a comment*)
  bp, bp0:   INT32;      (*current position in buf
                           (bp0: position of current token)*)
  LBlkSize:  INT32;      (*BlkSize*)
  inputLen:  INT32;      (*source file size*)
  buf:       Buffer;     (*source buffer for low-level access*)
  start:     StartTable; (*start state for every character*)
  CurrentCh: GetCH;

PROCEDURE ORDL (n: INT32): CARDINAL;
 BEGIN
   RETURN FileIO.ORDL(n)
 END ORDL;

PROCEDURE Err (nr, line, col: INTEGER; pos: INT32);
  BEGIN
    INC(errors)
  END Err;

PROCEDURE NextCh;
(* Return global variable ch *)
  BEGIN
    lastCh := ch; INC(bp); ch := CurrentCh(bp);
    IF (ch = EOL) OR (ch = FileIO.LF) AND (lastCh # EOL) THEN
      INC(curLine); lineStart := bp
    END
  END NextCh;

PROCEDURE Comment (): BOOLEAN;
  VAR
    level, startLine: INTEGER;
    oldLineStart: INT32;
  BEGIN
    level := 1; startLine := curLine; oldLineStart := lineStart;
    IF (ch = "/") THEN
      NextCh;
      IF (ch = "*") THEN
        NextCh;
        LOOP
          IF (ch = "*") THEN
            NextCh;
            IF (ch = "/") THEN
              DEC(level); NextCh;
              IF level = 0 THEN RETURN TRUE END
            END;
          ELSIF ch = EOF THEN RETURN FALSE
          ELSE NextCh END;
        END; (* LOOP *)
      ELSE
        IF (ch = CR) OR (ch = LF) THEN
          DEC(curLine); lineStart := oldLineStart
        END;
        DEC(bp); ch := lastCh;
      END;
    END;
    IF (ch = "(") THEN
      NextCh;
      IF (ch = "*") THEN
        NextCh;
        LOOP
          IF (ch = "*") THEN
            NextCh;
            IF (ch = ")") THEN
              DEC(level); NextCh;
              IF level = 0 THEN RETURN TRUE END
            END;
          ELSIF (ch = "(") THEN
            NextCh;
            IF (ch = "*") THEN INC(level); NextCh END;
          ELSIF ch = EOF THEN RETURN FALSE
          ELSE NextCh END;
        END; (* LOOP *)
      ELSE
        IF (ch = CR) OR (ch = LF) THEN
          DEC(curLine); lineStart := oldLineStart
        END;
        DEC(bp); ch := lastCh;
      END;
    END;
    RETURN FALSE;
  END Comment;

PROCEDURE Get (VAR sym: CARDINAL);
  VAR
    state: CARDINAL;

  PROCEDURE Equal (s: ARRAY OF CHAR): BOOLEAN;
    VAR
      i: CARDINAL;
      q: INT32;
    BEGIN
      IF nextLen # FileIO.SLENGTH(s) THEN RETURN FALSE END;
      i := 1; q := bp0; INC(q);
      WHILE i < nextLen DO
        IF CurrentCh(q) # s[i] THEN RETURN FALSE END;
        INC(i); INC(q)
      END;
      RETURN TRUE
    END Equal;

  PROCEDURE CheckLiteral;
    BEGIN
      CASE CurrentCh(bp0) OF
        "A": IF Equal("ANY") THEN sym := 23; 
             END
      | "C": IF Equal("CASE") THEN sym := 19; 
             ELSIF Equal("CHARACTERS") THEN sym := 10; 
             ELSIF Equal("CHR") THEN sym := 24; 
             ELSIF Equal("COMMENTS") THEN sym := 14; 
             ELSIF Equal("COMPILER") THEN sym := 5; 
             ELSIF Equal("CONTEXT") THEN sym := 34; 
             END
      | "E": IF Equal("END") THEN sym := 9; 
             END
      | "F": IF Equal("FROM") THEN sym := 15; 
             END
      | "I": IF Equal("IGNORE") THEN sym := 18; 
             END
      | "N": IF Equal("NAMES") THEN sym := 12; 
             ELSIF Equal("NESTED") THEN sym := 17; 
             END
      | "P": IF Equal("PRAGMAS") THEN sym := 13; 
             ELSIF Equal("PRODUCTIONS") THEN sym := 6; 
             END
      | "S": IF Equal("SYNC") THEN sym := 33; 
             END
      | "T": IF Equal("TO") THEN sym := 16; 
             ELSIF Equal("TOKENS") THEN sym := 11; 
             END
      | "W": IF Equal("WEAK") THEN sym := 28; 
             END
      ELSE
      END
    END CheckLiteral;

  BEGIN (*Get*)
    WHILE (ch=' ') OR
          (ch >= CHR(9)) & (ch <= CHR(10)) OR
          (ch = CHR(13)) DO NextCh END;
    IF ((ch = "/") OR (ch = "(")) & Comment() THEN Get(sym); RETURN END;
    pos := nextPos;   nextPos := bp;
    col := nextCol;   nextCol := FileIO.INTL(bp - lineStart);
    line := nextLine; nextLine := curLine;
    len := nextLen;   nextLen := 0;
    apx := FileIO.Long0; state := start[ORD(ch)]; bp0 := bp;
    LOOP
      NextCh; INC(nextLen);
      CASE state OF
         1: IF (ch >= "0") & (ch <= "9") OR
               (ch >= "A") & (ch <= "Z") OR
               (ch = "_") OR
               (ch >= "a") & (ch <= "z") THEN 
            ELSE sym := 1; CheckLiteral; RETURN
            END;
      |  2: sym := 2; RETURN
      |  3: sym := 3; RETURN
      |  4: IF (ch >= "0") & (ch <= "9") THEN 
            ELSE sym := 4; RETURN
            END;
      |  5: IF (ch >= "0") & (ch <= "9") OR
               (ch >= "A") & (ch <= "Z") OR
               (ch = "_") OR
               (ch >= "a") & (ch <= "z") THEN 
            ELSE sym := 42; RETURN
            END;
      |  6: IF (ch = CHR(0)) OR
               (ch >= " ") & (ch <= "!") OR
               (ch >= "#") THEN 
            ELSIF (ch = CHR(10)) OR
                  (ch = CHR(13)) THEN state := 3; 
            ELSIF (ch = '"') THEN state := 2; 
            ELSE sym := noSym; RETURN
            END;
      |  7: IF (ch = CHR(0)) OR
               (ch >= " ") & (ch <= "&") OR
               (ch >= "(") THEN 
            ELSIF (ch = CHR(10)) OR
                  (ch = CHR(13)) THEN state := 3; 
            ELSIF (ch = "'") THEN state := 2; 
            ELSE sym := noSym; RETURN
            END;
      |  8: sym := 7; RETURN
      |  9: IF (ch = ".") THEN state := 12; 
            ELSIF (ch = ">") THEN state := 23; 
            ELSIF (ch = ")") THEN state := 25; 
            ELSE sym := 8; RETURN
            END;
      | 10: sym := 20; RETURN
      | 11: sym := 21; RETURN
      | 12: sym := 22; RETURN
      | 13: IF (ch = ".") THEN state := 24; 
            ELSE sym := 25; RETURN
            END;
      | 14: sym := 26; RETURN
      | 15: sym := 27; RETURN
      | 16: sym := 29; RETURN
      | 17: sym := 30; RETURN
      | 18: sym := 31; RETURN
      | 19: sym := 32; RETURN
      | 20: IF (ch = ".") THEN state := 22; 
            ELSE sym := 35; RETURN
            END;
      | 21: sym := 36; RETURN
      | 22: sym := 37; RETURN
      | 23: sym := 38; RETURN
      | 24: sym := 39; RETURN
      | 25: sym := 40; RETURN
      | 26: sym := 0; ch := 0C; DEC(bp); RETURN
      ELSE sym := noSym; RETURN (*NextCh already done*)
      END
    END
  END Get;

PROCEDURE GetString (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR);
  VAR
    i: CARDINAL;
    p: INT32;
  BEGIN
    IF len > HIGH(s) THEN len := HIGH(s) END;
    p := pos; i := 0;
    WHILE i < len DO
      s[i] := CharAt(p); INC(i); INC(p)
    END;
    s[len] := 0C;
  END GetString;

PROCEDURE GetName (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR);
  VAR
    i: CARDINAL;
    p: INT32;
  BEGIN
    IF len > HIGH(s) THEN len := HIGH(s) END;
    p := pos; i := 0;
    WHILE i < len DO
      s[i] := CurrentCh(p); INC(i); INC(p)
    END;
    s[len] := 0C;
  END GetName;

PROCEDURE CharAt (pos: INT32): CHAR;
  VAR
    ch: CHAR;
  BEGIN
    IF pos >= inputLen THEN RETURN FileIO.EOF END;
    ch := buf[FileIO.ORDL(pos DIV LBlkSize)]^[FileIO.ORDL(pos MOD LBlkSize)];
    IF ch # eof THEN RETURN ch ELSE RETURN FileIO.EOF END
  END CharAt;

PROCEDURE CapChAt (pos: INT32): CHAR;
  VAR
    ch: CHAR;
  BEGIN
    IF pos >= inputLen THEN RETURN FileIO.EOF END;
    ch := CAP(buf[FileIO.ORDL(pos DIV LBlkSize)]^[FileIO.ORDL(pos MOD LBlkSize)]);
    IF ch # eof THEN RETURN ch ELSE RETURN FileIO.EOF END
  END CapChAt;

PROCEDURE Reset;
  VAR
    len: INT32;
    i, read: CARDINAL;
  BEGIN (*assert: src has been opened*)
    len := FileIO.Length(src); i := 0; inputLen := len;
    WHILE len > LBlkSize DO
      Storage.ALLOCATE(buf[i], BlkSize);
      read := BlkSize; FileIO.ReadBytes(src, buf[i]^, read);
      len := len - FileIO.INT(read); INC(i)
    END;
    Storage.ALLOCATE(buf[i], FileIO.ORDL(len) + 1);
    read := FileIO.ORDL(len); FileIO.ReadBytes(src, buf[i]^, read);
    buf[i]^[read] := EOF;
    curLine := 1; lineStart := -FileIO.Long2; bp := -FileIO.Long1;
    oldEols := 0; apx := FileIO.Long0; errors := 0;
    NextCh;
  END Reset;

BEGIN
  CurrentCh := CharAt;
  start[  0] := 26; start[  1] := 27; start[  2] := 27; start[  3] := 27; 
  start[  4] := 27; start[  5] := 27; start[  6] := 27; start[  7] := 27; 
  start[  8] := 27; start[  9] := 27; start[ 10] := 27; start[ 11] := 27; 
  start[ 12] := 27; start[ 13] := 27; start[ 14] := 27; start[ 15] := 27; 
  start[ 16] := 27; start[ 17] := 27; start[ 18] := 27; start[ 19] := 27; 
  start[ 20] := 27; start[ 21] := 27; start[ 22] := 27; start[ 23] := 27; 
  start[ 24] := 27; start[ 25] := 27; start[ 26] := 27; start[ 27] := 27; 
  start[ 28] := 27; start[ 29] := 27; start[ 30] := 27; start[ 31] := 27; 
  start[ 32] := 27; start[ 33] := 27; start[ 34] :=  6; start[ 35] := 27; 
  start[ 36] :=  5; start[ 37] := 27; start[ 38] := 27; start[ 39] :=  7; 
  start[ 40] := 13; start[ 41] := 14; start[ 42] := 27; start[ 43] := 10; 
  start[ 44] := 27; start[ 45] := 11; start[ 46] :=  9; start[ 47] := 27; 
  start[ 48] :=  4; start[ 49] :=  4; start[ 50] :=  4; start[ 51] :=  4; 
  start[ 52] :=  4; start[ 53] :=  4; start[ 54] :=  4; start[ 55] :=  4; 
  start[ 56] :=  4; start[ 57] :=  4; start[ 58] := 27; start[ 59] := 27; 
  start[ 60] := 20; start[ 61] :=  8; start[ 62] := 21; start[ 63] := 27; 
  start[ 64] := 27; start[ 65] :=  1; start[ 66] :=  1; start[ 67] :=  1; 
  start[ 68] :=  1; start[ 69] :=  1; start[ 70] :=  1; start[ 71] :=  1; 
  start[ 72] :=  1; start[ 73] :=  1; start[ 74] :=  1; start[ 75] :=  1; 
  start[ 76] :=  1; start[ 77] :=  1; start[ 78] :=  1; start[ 79] :=  1; 
  start[ 80] :=  1; start[ 81] :=  1; start[ 82] :=  1; start[ 83] :=  1; 
  start[ 84] :=  1; start[ 85] :=  1; start[ 86] :=  1; start[ 87] :=  1; 
  start[ 88] :=  1; start[ 89] :=  1; start[ 90] :=  1; start[ 91] := 16; 
  start[ 92] := 27; start[ 93] := 17; start[ 94] := 27; start[ 95] :=  1; 
  start[ 96] := 27; start[ 97] :=  1; start[ 98] :=  1; start[ 99] :=  1; 
  start[100] :=  1; start[101] :=  1; start[102] :=  1; start[103] :=  1; 
  start[104] :=  1; start[105] :=  1; start[106] :=  1; start[107] :=  1; 
  start[108] :=  1; start[109] :=  1; start[110] :=  1; start[111] :=  1; 
  start[112] :=  1; start[113] :=  1; start[114] :=  1; start[115] :=  1; 
  start[116] :=  1; start[117] :=  1; start[118] :=  1; start[119] :=  1; 
  start[120] :=  1; start[121] :=  1; start[122] :=  1; start[123] := 18; 
  start[124] := 15; start[125] := 19; start[126] := 27; start[127] := 27; 
  start[128] := 27; start[129] := 27; start[130] := 27; start[131] := 27; 
  start[132] := 27; start[133] := 27; start[134] := 27; start[135] := 27; 
  start[136] := 27; start[137] := 27; start[138] := 27; start[139] := 27; 
  start[140] := 27; start[141] := 27; start[142] := 27; start[143] := 27; 
  start[144] := 27; start[145] := 27; start[146] := 27; start[147] := 27; 
  start[148] := 27; start[149] := 27; start[150] := 27; start[151] := 27; 
  start[152] := 27; start[153] := 27; start[154] := 27; start[155] := 27; 
  start[156] := 27; start[157] := 27; start[158] := 27; start[159] := 27; 
  start[160] := 27; start[161] := 27; start[162] := 27; start[163] := 27; 
  start[164] := 27; start[165] := 27; start[166] := 27; start[167] := 27; 
  start[168] := 27; start[169] := 27; start[170] := 27; start[171] := 27; 
  start[172] := 27; start[173] := 27; start[174] := 27; start[175] := 27; 
  start[176] := 27; start[177] := 27; start[178] := 27; start[179] := 27; 
  start[180] := 27; start[181] := 27; start[182] := 27; start[183] := 27; 
  start[184] := 27; start[185] := 27; start[186] := 27; start[187] := 27; 
  start[188] := 27; start[189] := 27; start[190] := 27; start[191] := 27; 
  start[192] := 27; start[193] := 27; start[194] := 27; start[195] := 27; 
  start[196] := 27; start[197] := 27; start[198] := 27; start[199] := 27; 
  start[200] := 27; start[201] := 27; start[202] := 27; start[203] := 27; 
  start[204] := 27; start[205] := 27; start[206] := 27; start[207] := 27; 
  start[208] := 27; start[209] := 27; start[210] := 27; start[211] := 27; 
  start[212] := 27; start[213] := 27; start[214] := 27; start[215] := 27; 
  start[216] := 27; start[217] := 27; start[218] := 27; start[219] := 27; 
  start[220] := 27; start[221] := 27; start[222] := 27; start[223] := 27; 
  start[224] := 27; start[225] := 27; start[226] := 27; start[227] := 27; 
  start[228] := 27; start[229] := 27; start[230] := 27; start[231] := 27; 
  start[232] := 27; start[233] := 27; start[234] := 27; start[235] := 27; 
  start[236] := 27; start[237] := 27; start[238] := 27; start[239] := 27; 
  start[240] := 27; start[241] := 27; start[242] := 27; start[243] := 27; 
  start[244] := 27; start[245] := 27; start[246] := 27; start[247] := 27; 
  start[248] := 27; start[249] := 27; start[250] := 27; start[251] := 27; 
  start[252] := 27; start[253] := 27; start[254] := 27; start[255] := 27; 
  Error := Err; LBlkSize := FileIO.INT(BlkSize); lastCh := EOF;
END CRS.

⌨️ 快捷键说明

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