IMPLEMENTATION MODULE CRS; (* Scanner generated by Coco/R - assuming FileIO library will be available. *) IMPORT FileIO, Storage; CONST noSYMB = 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 := noSYMB; 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 := noSYMB; 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 := noSYMB; 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.