scanner.frm 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. IMPLEMENTATION MODULE -->modulename;
  2. (* Scanner generated by Coco/R - using the FileIO library supplied with this project. *)
  3. IMPORT FileIO, Storage;
  4. FROM Storage IMPORT ALLOCATE; (* gm2 needs this for NEW substitution *)
  5. CONST
  6. noSYMB = -->unknownsym; (*error token code*)
  7. (* not only for errors but also for not finished states of scanner analysis *)
  8. eof = CHR(26) (* MS-DOS Keyboard eof char *);
  9. EOF = CHR(0);
  10. EOL = CHR(13);
  11. CR = CHR(13);
  12. LF = CHR(10);
  13. Long0 = 0;
  14. Long1 = 1;
  15. BlkSize = 16384;
  16. TYPE
  17. BufBlock = ARRAY [0 .. BlkSize-1] OF CHAR;
  18. Buffer = ARRAY [0 .. 31] OF POINTER TO BufBlock;
  19. StartTable = ARRAY [0 .. 255] OF INTEGER;
  20. GetCH = PROCEDURE (INT32): CHAR;
  21. VAR
  22. lastCh,
  23. ch: CHAR; (*current input character*)
  24. curLine: INTEGER; (*current input line (may be higher than line)*)
  25. lineStart: INT32; (*start position of current line*)
  26. apx: INT32; (*length of appendix (CONTEXT phrase)*)
  27. oldEols: INTEGER; (*number of EOLs in a comment*)
  28. bp, bp0: INT32; (*current position in buf
  29. (bp0: position of current token)*)
  30. inputLen: INT32; (*source file size*)
  31. buf: Buffer; (*source buffer for low-level access*)
  32. start: StartTable; (*start state for every character*)
  33. CurrentCh: GetCH;
  34. (* Two-phase parse probe (milestone 1): exact save/restore of the
  35. scanner state around a token-level shadow skip. The pushed state
  36. covers the low-level buffer cursor plus every published position
  37. variable, so PopPos resumes the parse bit-exactly. `errors` is
  38. included: re-scanning a bad character must not double-count. *)
  39. posDepth: CARDINAL;
  40. saveLastCh: ARRAY [0 .. 7] OF CHAR;
  41. saveCh: ARRAY [0 .. 7] OF CHAR;
  42. saveCurLine: ARRAY [0 .. 7] OF INTEGER;
  43. saveLineStart: ARRAY [0 .. 7] OF INT32;
  44. saveApx: ARRAY [0 .. 7] OF INT32;
  45. saveOldEols: ARRAY [0 .. 7] OF INTEGER;
  46. saveBp: ARRAY [0 .. 7] OF INT32;
  47. saveBp0: ARRAY [0 .. 7] OF INT32;
  48. saveLine: ARRAY [0 .. 7] OF INTEGER;
  49. saveCol: ARRAY [0 .. 7] OF INTEGER;
  50. saveLen: ARRAY [0 .. 7] OF CARDINAL;
  51. savePos: ARRAY [0 .. 7] OF INT32;
  52. saveNextLine: ARRAY [0 .. 7] OF INTEGER;
  53. saveNextCol: ARRAY [0 .. 7] OF INTEGER;
  54. saveNextLen: ARRAY [0 .. 7] OF CARDINAL;
  55. saveNextPos: ARRAY [0 .. 7] OF INT32;
  56. saveErrors: ARRAY [0 .. 7] OF INTEGER;
  57. PROCEDURE Err (nr, line, col: INTEGER; pos: INT32);
  58. BEGIN
  59. INC(errors)
  60. END Err;
  61. PROCEDURE NextCh;
  62. (* Return global variable ch *)
  63. BEGIN
  64. lastCh := ch; INC(bp); ch := CurrentCh(bp);
  65. IF (ch = EOL) OR (ch = LF) AND (lastCh # EOL) THEN
  66. INC(curLine); lineStart := bp
  67. END
  68. END NextCh;
  69. PROCEDURE Comment (): BOOLEAN;
  70. VAR
  71. level, startLine: INTEGER;
  72. oldLineStart: INT32;
  73. BEGIN
  74. level := 1; startLine := curLine; oldLineStart := lineStart;
  75. -->commentRETURN FALSE;
  76. END Comment;
  77. PROCEDURE Get (VAR sym: CARDINAL);
  78. VAR
  79. state: CARDINAL;
  80. PROCEDURE Equal (s: ARRAY OF CHAR): BOOLEAN;
  81. VAR
  82. i: CARDINAL;
  83. q: INT32;
  84. BEGIN
  85. IF nextLen # LENGTH(s) THEN RETURN FALSE END;
  86. i := 1; q := bp0; INC(q);
  87. WHILE i < nextLen DO
  88. IF CurrentCh(q) # s[i] THEN RETURN FALSE END;
  89. INC(i); INC(q)
  90. END;
  91. RETURN TRUE
  92. END Equal;
  93. PROCEDURE CheckLiteral;
  94. BEGIN
  95. -->literals
  96. END CheckLiteral;
  97. BEGIN (*Get*)
  98. -->GetSy1
  99. pos := nextPos; nextPos := bp;
  100. col := nextCol; nextCol := VAL(INTEGER, bp - lineStart);
  101. line := nextLine; nextLine := curLine;
  102. len := nextLen; nextLen := 0;
  103. apx := 0; state := start[ORD(ch)]; bp0 := bp;
  104. LOOP
  105. NextCh; INC(nextLen);
  106. CASE state OF
  107. -->GetSy2
  108. ELSE sym := noSYMB; RETURN (*NextCh already done*)
  109. END
  110. END
  111. END Get;
  112. PROCEDURE GetString (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR);
  113. VAR
  114. i: CARDINAL;
  115. p: INT32;
  116. BEGIN
  117. IF len > HIGH(s) THEN len := HIGH(s) END;
  118. p := pos; i := 0;
  119. WHILE i < len DO
  120. s[i] := CharAt(p); INC(i); INC(p)
  121. END;
  122. s[len] := CHR(0);
  123. END GetString;
  124. PROCEDURE GetName (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR);
  125. VAR
  126. i: CARDINAL;
  127. p: INT32;
  128. BEGIN
  129. IF len > HIGH(s) THEN len := HIGH(s) END;
  130. p := pos; i := 0;
  131. WHILE i < len DO
  132. s[i] := CurrentCh(p); INC(i); INC(p)
  133. END;
  134. s[len] := CHR(0);
  135. END GetName;
  136. PROCEDURE CharAt (pos: INT32): CHAR;
  137. VAR
  138. ch: CHAR;
  139. BEGIN
  140. IF pos >= inputLen THEN RETURN EOF END;
  141. ch := buf[ORD(pos DIV BlkSize)]^[ORD(pos MOD BlkSize)];
  142. IF ch # eof THEN RETURN ch ELSE RETURN EOF END
  143. END CharAt;
  144. PROCEDURE CapChAt (pos: INT32): CHAR;
  145. VAR
  146. ch: CHAR;
  147. BEGIN
  148. IF pos >= inputLen THEN RETURN EOF END;
  149. ch := CAP(buf[ORD(pos DIV BlkSize)]^[ORD(pos MOD BlkSize)]);
  150. IF ch # eof THEN RETURN ch ELSE RETURN EOF END
  151. END CapChAt;
  152. PROCEDURE Reset;
  153. VAR
  154. i, read: CARDINAL;
  155. BEGIN (*assert: src has been opened*)
  156. i := 0; inputLen := 0;
  157. REPEAT
  158. NEW(buf[i]); (* typed alloc: sets the block descriptor's count *)
  159. read := BlkSize; FileIO.ReadBytes(src, buf[i]^, read);
  160. INC(i); INC(inputLen, VAL(INT32, read))
  161. UNTIL read # BlkSize;
  162. buf[i-1]^[read] := EOF;
  163. curLine := 1; lineStart := -2; bp := -1;
  164. oldEols := 0; apx := 0; errors := 0;
  165. posDepth := 0;
  166. NextCh;
  167. END Reset;
  168. PROCEDURE PushPos;
  169. (* Save the full scanner state (milestone 1 probe). *)
  170. BEGIN
  171. IF posDepth > HIGH(saveBp) THEN RETURN END;
  172. saveLastCh[posDepth] := lastCh; saveCh[posDepth] := ch;
  173. saveCurLine[posDepth] := curLine; saveLineStart[posDepth] := lineStart;
  174. saveApx[posDepth] := apx; saveOldEols[posDepth] := oldEols;
  175. saveBp[posDepth] := bp; saveBp0[posDepth] := bp0;
  176. saveLine[posDepth] := line; saveCol[posDepth] := col;
  177. saveLen[posDepth] := len; savePos[posDepth] := pos;
  178. saveNextLine[posDepth] := nextLine; saveNextCol[posDepth] := nextCol;
  179. saveNextLen[posDepth] := nextLen; saveNextPos[posDepth] := nextPos;
  180. saveErrors[posDepth] := errors;
  181. INC(posDepth)
  182. END PushPos;
  183. PROCEDURE PopPos;
  184. (* Restore the state saved by PushPos. *)
  185. BEGIN
  186. IF posDepth = 0 THEN RETURN END;
  187. DEC(posDepth);
  188. lastCh := saveLastCh[posDepth]; ch := saveCh[posDepth];
  189. curLine := saveCurLine[posDepth]; lineStart := saveLineStart[posDepth];
  190. apx := saveApx[posDepth]; oldEols := saveOldEols[posDepth];
  191. bp := saveBp[posDepth]; bp0 := saveBp0[posDepth];
  192. line := saveLine[posDepth]; col := saveCol[posDepth];
  193. len := saveLen[posDepth]; pos := savePos[posDepth];
  194. nextLine := saveNextLine[posDepth]; nextCol := saveNextCol[posDepth];
  195. nextLen := saveNextLen[posDepth]; nextPos := saveNextPos[posDepth];
  196. errors := saveErrors[posDepth]
  197. END PopPos;
  198. PROCEDURE DropPos;
  199. (* Discard the top PushPos snapshot without restoring it (the caller has
  200. chosen to keep the current scanner position, e.g. after a successful
  201. body skip). *)
  202. BEGIN
  203. IF posDepth > 0 THEN DEC(posDepth) END
  204. END DropPos;
  205. PROCEDURE SeekTo (p: INT32);
  206. (* Reposition the scanner to the token starting at buffer offset p
  207. (two-phase re-parse). Replays NextCh from the start so curLine /
  208. lineStart / lastCh match a fresh parse exactly; the buffer is
  209. in-memory so this is O(p) with no file I/O. Published pos / len /
  210. line / col still describe the previous token afterwards — the caller
  211. must Get immediately, exactly like the priming Get in Parse. *)
  212. VAR k: INT32;
  213. BEGIN
  214. curLine := 1; lineStart := -2; bp := -1;
  215. ch := EOF; lastCh := EOF;
  216. oldEols := 0; apx := 0; bp0 := p;
  217. k := 0;
  218. WHILE k <= p DO NextCh; INC(k) END
  219. END SeekTo;
  220. BEGIN
  221. -->initializations
  222. Error := Err; lastCh := EOF;
  223. END -->modulename.
  224. -->definitionDEFINITION MODULE -->modulename;
  225. (* Scanner generated by Coco/R - using the FileIO library supplied with this project. *)
  226. IMPORT FileIO;
  227. TYPE
  228. INT32 = FileIO.INT32 (* need 32 bit integers *);
  229. VAR
  230. src, lst: FileIO.File;(*source/list files. To be opened by the main pgm*)
  231. directory: ARRAY [0 .. 255] OF CHAR (*of source file*);
  232. line, col: INTEGER; (*line and column of current symbol*)
  233. len: CARDINAL; (*length of current symbol*)
  234. pos: INT32; (*file position of current symbol*)
  235. nextLine: INTEGER; (*line of lookahead symbol*)
  236. nextCol: INTEGER; (*column of lookahead symbol*)
  237. nextLen: CARDINAL; (*length of lookahead symbol*)
  238. nextPos: INT32; (*file position of lookahead symbol*)
  239. errors: INTEGER; (*number of detected errors*)
  240. Error: PROCEDURE ((*nr*)INTEGER, (*line*)INTEGER, (*col*)INTEGER,
  241. (*pos*)INT32);
  242. PROCEDURE Get (VAR sym: CARDINAL);
  243. (* Gets next symbol from source file *)
  244. PROCEDURE GetString (pos: INT32; len: CARDINAL; VAR name: ARRAY OF CHAR);
  245. (* Retrieves exact string of max length len from position pos in source file *)
  246. PROCEDURE GetName (pos: INT32; len: CARDINAL; VAR name: ARRAY OF CHAR);
  247. (* Retrieves name of symbol of length len at position pos in source file *)
  248. PROCEDURE CharAt (pos: INT32): CHAR;
  249. (* Returns exact character at position pos in source file *)
  250. PROCEDURE Reset;
  251. (* Reads and stores source file internally *)
  252. PROCEDURE PushPos;
  253. (* Save the full scanner state for a shadow skip (two-phase probe) *)
  254. PROCEDURE PopPos;
  255. (* Restore the state saved by PushPos *)
  256. PROCEDURE DropPos;
  257. (* Discard the top PushPos snapshot without restoring *)
  258. PROCEDURE SeekTo (p: INT32);
  259. (* Reposition the scanner to buffer offset p (two-phase re-parse);
  260. caller must Get immediately afterwards *)
  261. END -->modulename.