scanner.frm 10.0 KB

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