M2S.mod 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. IMPLEMENTATION MODULE M2S; (*NW 17.8.83 / 31.3.85*)
  2. FROM SYSTEM IMPORT LONG;
  3. FROM FileSystem IMPORT
  4. File, Response, Lookup, ReadChar, WriteChar, GetPos, SetPos, Close;
  5. CONST KW = 42; (*number of keywords*)
  6. maxDig = 7;
  7. maxCard = 177777B;
  8. maxExp = 38;
  9. IdBufLim = IdBufLeng - 100;
  10. FNM = 300C;
  11. ERR = 301C;
  12. VAR ch: CHAR; (*current character*)
  13. id0, id1: CARDINAL; (*indices of identifier buffer*)
  14. keyTab: ARRAY [0..KW-1] OF
  15. RECORD sym: Symbol; ind: CARDINAL END;
  16. K: CARDINAL;
  17. pow: ARRAY [0..5] OF REAL;
  18. lastPos: CARDINAL;
  19. errDat,
  20. errLog: File;
  21. PROCEDURE Times16(x: LONGINT): LONGINT;
  22. CODE 216B; 216B; 216B; 216B
  23. END Times16;
  24. PROCEDURE ErrorBlock(errPos: LONGINT; errCod: CARDINAL);
  25. VAR i: CARDINAL;
  26. conv: RECORD
  27. CASE :CARDINAL OF
  28. 0: long: LONGINT
  29. | 1: sys: ARRAY [0..3] OF CHAR;
  30. END;
  31. END;
  32. BEGIN
  33. IF errPos >= 2D THEN errPos := errPos - 2D END;
  34. WriteChar(errDat, ERR);
  35. WITH conv DO
  36. long := errPos; FOR i := 3 TO 0 BY -1 DO WriteChar(errDat, sys[i]) END;
  37. END;
  38. WriteChar(errDat, CHR(errCod MOD 256)); WriteChar(errDat, CHR(errCod DIV 256));
  39. END ErrorBlock;
  40. PROCEDURE Mark(n: CARDINAL);
  41. VAR k, p0, p1: CARDINAL; buf: CHAR;
  42. dig: ARRAY [0..3] OF CARDINAL;
  43. BEGIN scanerr := TRUE; k := 4; GetPos(source, p0, p1);
  44. IF lastPos + 8 < p1 THEN
  45. ErrorBlock(LONG(p0, p1), n);
  46. IF lastPos + 100 < p1 THEN
  47. lastPos := p1 - 100; SetPos(source, p0, lastPos);
  48. WriteChar(errLog, 36C); WriteChar(errLog, 36C);
  49. REPEAT ReadChar(source, buf); INC(lastPos)
  50. UNTIL (buf = 36C) OR (lastPos = p1)
  51. ELSE SetPos(source, p0, lastPos)
  52. END ;
  53. WHILE lastPos < p1 DO
  54. ReadChar(source, buf); WriteChar(errLog, buf); INC(lastPos)
  55. END ;
  56. WriteChar(errLog, " ");
  57. REPEAT WriteChar(errLog, "*"); DEC(k) UNTIL k = 0;
  58. REPEAT dig[k] := n MOD 10; n := n DIV 10; INC(k) UNTIL n = 0;
  59. REPEAT DEC(k); WriteChar(errLog, CHR(dig[k] + 60B)) UNTIL k = 0;
  60. WriteChar(errLog, " ")
  61. END
  62. END Mark;
  63. PROCEDURE GetCh;
  64. BEGIN ReadChar(source, ch)
  65. END GetCh;
  66. PROCEDURE Diff(i, j: CARDINAL): INTEGER;
  67. VAR k: CARDINAL;
  68. BEGIN k := ORD(IdBuf[i]);
  69. LOOP
  70. IF k = 0 THEN RETURN 0
  71. ELSIF IdBuf[i] # IdBuf[j] THEN
  72. RETURN INTEGER(ORD(IdBuf[i])) - INTEGER(ORD(IdBuf[j]))
  73. ELSE INC(i); INC(j); DEC(k)
  74. END
  75. END
  76. END Diff;
  77. PROCEDURE KeepId;
  78. BEGIN id := id1
  79. END KeepId;
  80. PROCEDURE String(termCh: CHAR);
  81. BEGIN id1 := id + 1;
  82. IF id1 > IdBufLim THEN Mark(91); id1 := 1 END ;
  83. LOOP GetCh;
  84. IF ch = termCh THEN EXIT END ;
  85. IF ch < " " THEN Mark(45); EXIT END ;
  86. IdBuf[id1] := ch; INC(id1)
  87. END ;
  88. GetCh; IdBuf[id] := CHR(id1-id); (*length*)
  89. IF IdBuf[id] = 2C THEN
  90. sym := number; numtyp := 3; intval := ORD(IdBuf[id+1])
  91. ELSE sym := string;
  92. IF IdBuf[id] = 1C THEN (*empty string*)
  93. IdBuf[id1] := 0C; INC(id1); IdBuf[id] := 2C
  94. END
  95. END
  96. END String;
  97. PROCEDURE Identifier;
  98. VAR k, l, m: CARDINAL;
  99. BEGIN id1 := id + 1;
  100. IF id1 > IdBufLim THEN Mark(91); id1 := 1 END;
  101. REPEAT
  102. IdBuf[id1] := ch; INC(id1); GetCh
  103. UNTIL (ch < "0") OR ("9" < ch) & (CAP(ch) < "A") OR ("Z" < CAP(ch));
  104. IdBuf[id] := CHR(id1-id); (*Length*)
  105. k := 0; l := KW;
  106. REPEAT m := (k + l) DIV 2;
  107. IF Diff(id, keyTab[m].ind) <= 0 THEN l := m ELSE k := m + 1 END
  108. UNTIL k >= l;
  109. IF (k < KW) & (Diff(id, keyTab[k].ind) = 0) THEN sym := keyTab[k].sym
  110. ELSE sym := ident
  111. END
  112. END Identifier;
  113. PROCEDURE Number;
  114. VAR i, j, l, d, e, n: CARDINAL;
  115. x, f: REAL;
  116. d0, d1: LONGINT;
  117. neg: BOOLEAN;
  118. lastCh: CHAR;
  119. dig: ARRAY [0..31] OF CHAR;
  120. PROCEDURE Ten(e: CARDINAL): REAL;
  121. VAR k: CARDINAL; u: REAL;
  122. BEGIN k := 0; u := 1.0;
  123. WHILE e > 0 DO
  124. IF ODD(e) THEN u := pow[k] * u END ;
  125. e := e DIV 2; INC(k)
  126. END ;
  127. RETURN u
  128. END Ten;
  129. BEGIN sym := number; i := 0;
  130. REPEAT dig[i] := ch; INC(i); GetCh
  131. UNTIL (ch < "0") OR ("9" < ch) & (CAP(ch) < "A") OR ("Z" < CAP(ch));
  132. lastCh := ch; j := 0;
  133. WHILE (j < i) & (dig[j] = "0") DO INC(j) END ;
  134. IF ch = "." THEN GetCh;
  135. IF ch = "." THEN
  136. lastCh := 0C; ch := 177C (*ellipsis*)
  137. END
  138. END ;
  139. IF lastCh = "." THEN (*decimal point*)
  140. x := 0.0; l := 0;
  141. WHILE j < i DO (*read int part*)
  142. IF l < maxDig THEN
  143. IF dig[j] > "9" THEN Mark(40) END ;
  144. x := x * 10.0 + FLOAT(ORD(dig[j])-60B); INC(l)
  145. ELSE Mark(41)
  146. END;
  147. INC(j)
  148. END ;
  149. l := 0; f := 0.0;
  150. WHILE ("0" <= ch) & (ch <= "9") DO (*read fraction*)
  151. IF l < maxDig THEN
  152. f := f * 10.0 + FLOAT(ORD(ch)-60B); INC(l)
  153. END ;
  154. GetCh
  155. END ;
  156. x := f / Ten(l) + x; e := 0; neg := FALSE;
  157. IF ch = "E" THEN GetCh;
  158. IF ch = "-" THEN
  159. neg := TRUE; GetCh
  160. ELSIF ch = "+" THEN GetCh
  161. END ;
  162. WHILE ("0" <= ch) & (ch <= "9") DO (*read exponent*)
  163. e := e * 10 + ORD(ch)-60B;
  164. GetCh
  165. END
  166. END ;
  167. IF neg THEN
  168. IF e <= maxExp THEN x := x / Ten(e) ELSE x := 0.0 END
  169. ELSE
  170. IF e <= maxExp THEN f := Ten(e);
  171. IF MAX(REAL) / f >= x THEN x := f*x ELSE Mark(41) END
  172. ELSE Mark(41)
  173. END
  174. END ;
  175. numtyp := 4; realval := x
  176. ELSE (*integer*)
  177. lastCh := dig[i-1];
  178. IF lastCh = "B" THEN
  179. DEC(i); intval := 0; numtyp := 1;
  180. WHILE j < i DO
  181. d := ORD(dig[j]) - 60B;
  182. IF (d < 10B) & ((maxCard - d) DIV 10B >= intval) THEN
  183. intval := 10B * intval + d
  184. ELSE Mark(29); intval := 0
  185. END ;
  186. INC(j)
  187. END
  188. ELSIF lastCh = "H" THEN DEC(i);
  189. IF i <= j+4 THEN
  190. numtyp := 1; intval := 0;
  191. WHILE j < i DO
  192. d := ORD(dig[j]) - 60B;
  193. IF d > 26B THEN Mark(29); d := 0
  194. ELSIF d > 9 THEN d := d-7
  195. END ;
  196. intval := 10H * intval + d; INC(j)
  197. END
  198. ELSIF i <= j+8 THEN
  199. numtyp := 2; dblval := 0D;
  200. REPEAT d := ORD(dig[j]) - 60B;
  201. IF d > 26B THEN Mark(29); d := 0
  202. ELSIF d > 9 THEN d := d-7
  203. END ;
  204. dblval := Times16(dblval) + LONG(0,d); INC(j)
  205. UNTIL j = i
  206. ELSE Mark(29); numtyp := 2
  207. END
  208. ELSIF lastCh = "D" THEN
  209. DEC(i); d1 := 0D; numtyp := 2;
  210. WHILE j < i DO
  211. d := ORD(dig[j]) - 60B;
  212. IF d < 10 THEN (*no overflow check*)
  213. d1 := d1 + d1; d0 := d1 + d1; d1 := d0 + d0 + d1 + LONG(0, d)
  214. ELSE Mark(29); d1 := 0D
  215. END ;
  216. INC(j)
  217. END ;
  218. dblval := d1
  219. ELSIF lastCh = "C" THEN
  220. DEC(i); intval := 0; numtyp := 3;
  221. WHILE j < i DO
  222. d := ORD(dig[j]) - 60B; intval := 10B * intval + d;
  223. IF (d >= 10B) OR (intval >= 400B) THEN
  224. Mark(29); intval := 0
  225. END ;
  226. INC(j)
  227. END
  228. ELSE (*decimal?*)
  229. numtyp := 1; intval := 0;
  230. WHILE j < i DO
  231. d := ORD(dig[j]) - 60B;
  232. IF (d < 10) & ((maxCard-d) DIV 10 >= intval) THEN
  233. intval := 10*intval + d
  234. ELSE Mark(29); intval := 0
  235. END ;
  236. INC(j)
  237. END
  238. END
  239. END
  240. END Number;
  241. PROCEDURE GetSym;
  242. VAR xch: CHAR;
  243. PROCEDURE Comment;
  244. BEGIN GetCh;
  245. REPEAT
  246. WHILE (ch # "*") & (ch > 0C) DO
  247. IF ch = "(" THEN GetCh;
  248. IF ch = "*" THEN Comment END
  249. ELSE GetCh
  250. END
  251. END ;
  252. GetCh
  253. UNTIL (ch = ")") OR (ch = 0C);
  254. IF ch > 0C THEN GetCh ELSE Mark(42) END
  255. END Comment;
  256. BEGIN
  257. LOOP (*ignore control characters*)
  258. IF ch <= " " THEN
  259. IF ch = 0C THEN ch := " "; EXIT ELSE GetCh END ;
  260. ELSIF ch > 177C THEN GetCh
  261. ELSE EXIT
  262. END
  263. END ;
  264. CASE ch OF (* " " <= ch <= 177C *)
  265. " " : sym := eof; ch := 0C |
  266. "!" : sym := null; GetCh |
  267. '"' : String('"') |
  268. "#" : sym := neq; GetCh |
  269. "$" : sym := null; GetCh |
  270. "%" : sym := null; GetCh |
  271. "&" : sym := and; GetCh |
  272. "'" : String("'") |
  273. "(" : GetCh;
  274. IF ch = "*" THEN Comment; GetSym
  275. ELSE sym := lparen
  276. END |
  277. ")" : sym := rparen; GetCh|
  278. "*" : sym := times; GetCh |
  279. "+" : sym := plus; GetCh |
  280. "," : sym := comma; GetCh |
  281. "-" : sym := minus; GetCh |
  282. "." : GetCh;
  283. IF ch = "." THEN GetCh; sym := ellipsis
  284. ELSE sym := period
  285. END |
  286. "/" : sym := slash; GetCh |
  287. "0".."9": Number |
  288. ":" : GetCh;
  289. IF ch = "=" THEN GetCh; sym := becomes
  290. ELSE sym := colon
  291. END |
  292. ";" : sym := semicolon; GetCh |
  293. "<" : GetCh;
  294. IF ch = "=" THEN GetCh; sym := leq
  295. ELSIF ch = ">" THEN GetCh; sym := neq
  296. ELSE sym := lss
  297. END |
  298. "=" : sym := eql; GetCh |
  299. ">" : GetCh;
  300. IF ch = "=" THEN GetCh; sym := geq
  301. ELSE sym := gtr
  302. END |
  303. "?" : sym := null; GetCh |
  304. "@" : sym := null; GetCh |
  305. "A".."Z": Identifier |
  306. "[" : sym := lbrak; GetCh |
  307. "\" : sym := null; GetCh |
  308. "]" : sym := rbrak; GetCh |
  309. "^" : sym := arrow; GetCh |
  310. "_" : sym := becomes; GetCh |
  311. "`" : sym := null; GetCh |
  312. "a".."z": Identifier |
  313. "{" : sym := lbrace; GetCh|
  314. "|" : sym := bar; GetCh |
  315. "}" : sym := rbrace; GetCh|
  316. "~" : sym := not; GetCh |
  317. 177C : sym := ellipsis; GetCh
  318. END
  319. END GetSym;
  320. PROCEDURE Enter(name: ARRAY OF CHAR): CARDINAL;
  321. VAR j, l: CARDINAL;
  322. BEGIN l := HIGH(name)+2; id1 := id;
  323. IF id1+l < IdBufLeng THEN
  324. IdBuf[id] := CHR(l); INC(id);
  325. FOR j := 0 TO l-2 DO IdBuf[id] := name[j]; INC(id) END
  326. END ;
  327. RETURN id1
  328. END Enter;
  329. PROCEDURE InitScanner(VAR name: ARRAY OF CHAR);
  330. VAR i: INTEGER;
  331. BEGIN ch := " "; scanerr := FALSE; lastPos := 0;
  332. IF id0 = 0 THEN
  333. id0 := id; Lookup(errLog, "DK.err.LST", TRUE);
  334. Lookup(errDat, "DK.err.DAT", TRUE)
  335. ELSE id := id0; WriteChar(errLog, "-"); WriteChar(errLog, 36C)
  336. END;
  337. WriteChar(errDat, FNM); i := 0;
  338. WHILE name[i] > 0C DO
  339. WriteChar(errDat, name[i]); WriteChar(errLog, name[i]); i := i+1
  340. END ;
  341. WriteChar(errLog, " "); WriteChar(errDat, 0C)
  342. END InitScanner;
  343. PROCEDURE CloseScanner;
  344. BEGIN Close(errLog); Close(errDat)
  345. END CloseScanner;
  346. PROCEDURE EnterKW(sym: Symbol; name: ARRAY OF CHAR);
  347. VAR l, L: CARDINAL;
  348. BEGIN
  349. keyTab[K].sym := sym;
  350. keyTab[K].ind := id;
  351. l := 0; L := HIGH(name);
  352. IdBuf[id] := CHR(L+2); INC(id);
  353. WHILE l <= L DO
  354. IdBuf[id] := name[l];
  355. INC(id); INC(l)
  356. END;
  357. INC(K)
  358. END EnterKW;
  359. BEGIN K := 0; IdBuf[0] := 1C; id := 1; id0 := 0;
  360. pow[0] := 1.0E1;
  361. pow[1] := 1.0E2;
  362. pow[2] := 1.0E4;
  363. pow[3] := 1.0E8;
  364. pow[4] := 1.0E16;
  365. pow[5] := 1.0E32;
  366. EnterKW(by,"BY");
  367. EnterKW(do,"DO");
  368. EnterKW(if,"IF");
  369. EnterKW(in,"IN");
  370. EnterKW(of,"OF");
  371. EnterKW(or,"OR");
  372. EnterKW(to,"TO");
  373. EnterKW(and,"AND");
  374. EnterKW(div,"DIV");
  375. EnterKW(end,"END");
  376. EnterKW(for,"FOR");
  377. EnterKW(mod,"MOD");
  378. EnterKW(not,"NOT");
  379. EnterKW(set,"SET");
  380. EnterKW(var,"VAR");
  381. EnterKW(case,"CASE");
  382. EnterKW(code,"CODE");
  383. EnterKW(else,"ELSE");
  384. EnterKW(exit,"EXIT");
  385. EnterKW(from,"FROM");
  386. EnterKW(loop,"LOOP");
  387. EnterKW(then,"THEN");
  388. EnterKW(type,"TYPE");
  389. EnterKW(with,"WITH");
  390. EnterKW(array,"ARRAY");
  391. EnterKW(begin,"BEGIN");
  392. EnterKW(const,"CONST");
  393. EnterKW(elsif,"ELSIF");
  394. EnterKW(until,"UNTIL");
  395. EnterKW(while,"WHILE");
  396. EnterKW(export,"EXPORT");
  397. EnterKW(import,"IMPORT");
  398. EnterKW(module,"MODULE");
  399. EnterKW(record,"RECORD");
  400. EnterKW(repeat,"REPEAT");
  401. EnterKW(return,"RETURN");
  402. EnterKW(forward,"FORWARD");
  403. EnterKW(pointer,"POINTER");
  404. EnterKW(procedure,"PROCEDURE");
  405. EnterKW(qualified,"QUALIFIED");
  406. EnterKW(definition,"DEFINITION");
  407. EnterKW(implementation,"IMPLEMENTATION");
  408. END M2S.