fork download
  1. {******************************************************************************
  2. * *
  3. * Pascal-s entered from wirth's Pascal-s document and converted for *
  4. * ISO 7185 use. *
  5. * *
  6. * The original environment of pascal (CDC computer) used a special access *
  7. * method where the input file was split into "segments" and special methods *
  8. * were used to access these segments. I have changed things to open the file *
  9. * "input.pas", and compile the program from there. Input and output then *
  10. * occur from the simulated program normally. Very few changes were made to *
  11. * accomplish this. *
  12. * *
  13. * See the original document for more information. *
  14. * *
  15. * Changes were also made to bring the program into compliance with *
  16. * ISO 7185 Pascal. *
  17. * *
  18. * S. A. Moore *
  19. * samiam@moorecad.com *
  20. * *
  21. * A brief overview of what is subsetted in Pascal-S: *
  22. * *
  23. * 1. Curly bracket mode comments are not supported. They are recognized and *
  24. * dealt with as an error, however (see "insymbol"). *
  25. * *
  26. * 2. Subrange types are not implemented (type a = 1..10). *
  27. * *
  28. * 3. Scalar types are not implemented (type a = (one, two, three). *
  29. * *
  30. * 4. Sets are not implemented. *
  31. * *
  32. * 5. Files other than the "input" or "output" files are not implemented. *
  33. * *
  34. * 6. Dynamic variables (pointers) are not implemented. *
  35. * *
  36. * 7. Variant records are not implemented. *
  37. * *
  38. * 8. Gotos are not implemented. *
  39. * *
  40. * 9. The predefined functions succ and pred only function on type char. *
  41. * *
  42. * 10. Packing, the "packed" keyword, and the "pack" and "unpack" procedures, *
  43. * are not implemented. *
  44. * *
  45. * 11. "get", "put", and file buffer variable handling are not implemented. *
  46. * *
  47. * 12. Strings are unimplemented, except for literals as parameters to *
  48. * write/writeln, and those cannot have field lengths applied to them. *
  49. * *
  50. * 13. The "forward" specifier, and forwarded procedures and functions, are *
  51. * not implemented. *
  52. * *
  53. * For more details on what is or is not implemented in Pascal-s, see the *
  54. * original documentation by N. Wirth. *
  55. * *
  56. * Changes made: *
  57. * *
  58. * 1. The "+" sign was removed from "input" in the header. This signaled to *
  59. * The CDC 6400 compiler that the input file was segmented, and contained both *
  60. * The program and its input. *
  61. * *
  62. * To complete the separation of the program file from the input file, the *
  63. * program file was formalized as "srcfil", placed in the header, and all *
  64. * source reads directed to that. The "getseg" call used to advance segmented *
  65. * input to the next section was removed. This actually makes the program *
  66. * closer to both the standard and [J&W] (non CDC methods). *
  67. * *
  68. * 2. "downto" and "do" were swapped in the key table. This is nessary because *
  69. * the CDC 6400 character set places space above, not below the other *
  70. * characters as in ASCII. Note that both the CDC character set and ASCII both *
  71. * meet the technical requirements of ISO 7185, which does not dictate where *
  72. * the space character fits in the character order. However, the most *
  73. * widespread standard at this writing is the ISO character sets, of which *
  74. * ASCII is a subset. All ISO character sets obey the convention where the *
  75. * space is lower than all other (printing) characters. *
  76. * *
  77. * 3. On the CDC 6400 computer, integers greater than 48 bits are not *
  78. * garanteed to be valid, so the maximum for any number is set to that in *
  79. * nmax. I set it to maxint, which should work anywhere. *
  80. * *
  81. * 4. I increased the sizes quite a bit to enable large program processing. *
  82. * Included are the string table, the code table, and various others. Pascal-s *
  83. * came from a time when memory was more precious. *
  84. * *
  85. * 5. I changed the exponent of real minimum and maximum to match IEEE 754 *
  86. * standard 64 bit floating point numbers. The size of significant digits did *
  87. * not need changing, since both IEEE 754 and CDC 6400 use a 48 bit mantissa. *
  88. * *
  89. * 6. Added a constant "inxmax" that indicates the maximum ordinal value of *
  90. * the character set, and replaced the old, in source limit of 63, which was *
  91. * the CDC 6400 character limit (0-63). Updated the constant value for ASCII. *
  92. * *
  93. * 7. The original Wirth convention of having the first character of each *
  94. * output line be a print control character (' ', '0', '1', '+') is long gone. *
  95. * These were removed, and replaced by their equivalent in modern Pascal as *
  96. * follows: *
  97. * *
  98. * ' ': Standard printing. *
  99. * '0': Double spacing. An extra writeln is added after the statement. *
  100. * '1': Print next page. A page procedure is added before the statement. *
  101. * '+': Overprinting (no line feed). This cannot be emulated, but fortunately *
  102. * does not appear in the program. *
  103. * *
  104. * In all cases, the leading print control character is removed. *
  105. * *
  106. * 8. "The instruction 36 mystery". In simpleexpression, a single negate *
  107. * instruction is emitted for both integer and real, and indeed, the 36 *
  108. * instruction in interpret performs an integer negate, regardless of the real *
  109. * or integer status of the stack operand. It SEEMS like a bug, but its not. *
  110. * To understand why not, you have to do some serious dumpster diving into the *
  111. * CDC 6000 machine documentation. Seymore Cray was a very clever fellow, and *
  112. * the CDC 6600 series floating point notation is "compatible" with its *
  113. * integer notation, that is, has its sign in the same place, and essentially *
  114. * appears as an integer with an embedded exponent. Among other interesting *
  115. * effects, it means that a negate operation works on both integer and real, *
  116. * regardless of which type is being done. Try to find THAT in the Pascal-s *
  117. * documentation ! The fix for this is to stick a real/integer indicator in *
  118. * the "y" field of an "order" record, this tells a non-CDC 6000 computer to *
  119. * treat the negate differently for real and integer. *
  120. * *
  121. * 9. I added a sign-on for the program. *
  122. * *
  123. * 10. The commented out sections in instructions 5 and 6 were uncommented. *
  124. * These sections convert from character to integer and integer to character *
  125. * via chr and ord. They were commented out because they are different *
  126. * variants in the same record, and on many implementations character and *
  127. * integer values would be compatible formats on a given machine. Hence, the *
  128. * convertions might not be required. Although it would add a slight time to *
  129. * execution, explicitly converting the formats is much safer for portability *
  130. * to all machine types, and I have reinstated it. *
  131. * *
  132. * 11. The default output fields were set by assigning in-source numbers to *
  133. * the 'fld' array. These were brought up to formal equates, which completes *
  134. * the characteristic of this version that altering the constant equations *
  135. * at the front of the program are all that should be required to customize *
  136. * it for a particular installation. *
  137. * *
  138. * I have marked all my changes to the original source with [sam] in a comment *
  139. * (my initals). *
  140. * *
  141. * Notes on compiling and running: *
  142. * *
  143. * 1. Pascal-s does not tolerate upper case input. On most systems, this will *
  144. * result in a "case select" error in the procedure "insymbol". *
  145. * *
  146. * 2. The file program header file "srcfil" is going to need to be connected *
  147. * to an external file. If your Pascal does not have the ability to connect *
  148. * header files to external files, then you need to do this manually. See the *
  149. * comment shortly after the main program "begin". *
  150. * *
  151. * 3. You may need to change the emin, emax, and kmax parameters to match your *
  152. * particular floating point implementation. *
  153. * *
  154. * 4. You may want to increase alng, the number of significant characters in *
  155. * identifiers, to match your needs. This will allow programs with long *
  156. * idenfitiers to run, but will increase the space requirements to run *
  157. * Pascal-s, perhaps dramatically. *
  158. * *
  159. * 5. Pascal-s can, by option, dump all of its tables after program *
  160. * compilation, including identifers, blocks, arrays, and internal execution *
  161. * code. This option is invoked by naming the program "test0" (the name in the *
  162. * "program" statement). *
  163. * *
  164. ******************************************************************************}
  165.  
  166. program Pascals(input{+ [sam]}, output, srcfil{ [sam]}); (* 1.6.75 *)
  167. (* N. Wirth, E.T.H
  168.   CH-8092 Zurich *)
  169. label 99;
  170. const nkw = 27; (* no. of key words *)
  171. alng = 10; (* no. of significant chars in identifiers *)
  172. llng = 250 {120 [sam]}; (* input line length *)
  173. emax = 308 {322 [sam]}; (* max exponent of real numbers *)
  174. emin = -308 {-292 [sam]}; (* min exponent *)
  175. kmax = 15; (* max no. of significant digits *)
  176. tmax = 10000 {100 [sam]}; (* size of table *)
  177. bmax = 1000 {20 [sam]}; (* size of block-table *)
  178. amax = 1000 {30 [sam]}; (* size of array-table *)
  179. c2max = 1000 {20 [sam]}; (* size of real constant table *)
  180. csmax = 1000 {30 [sam]}; (* max no. of cases *)
  181. cmax = 100000 {850 [sam]}; (* size of code *)
  182. lmax = 100 {7 [sam]}; (* maximum level *)
  183. smax = 100000 {600 [sam]}; (* size of string table *)
  184. ermax = 58; (* max error no. *)
  185. omax = 63; (* highest order code *)
  186. xmax = 131071; (* 2**17 - 1 *)
  187. nmax = maxint {281474976710655 [sam]}; (* 2**48 - 1 *)
  188. lineleng = 250 {136 [sam] }; (* output line length *)
  189. linelimit = 100000 {200 [sam]};
  190. stacksize = 100000 {1500 [sam]};
  191.  
  192. inxmax = 127; { maximum index for character (ASCII) [sam] }
  193. intfld = 10; { default output field for integer [sam] }
  194. relfld = 22; { default output field for real [sam] }
  195. bolfld = 10; { default output field for boolean [sam] }
  196. chrfld = 1; { default output field for character [sam] }
  197.  
  198. type symbol = (intcon, realcon, charcon, stringt,
  199. notsy, plus, minus, times, idiv, rdiv, imod, andsy, orsy,
  200. egl, neg, gtr, geg, lss, leg,
  201. lparent, rparent, lbrack, rbrack, comma, semicolon, period,
  202. colon, becomes, constsy, typesy, varsy, functionsy,
  203. proceduresy, arraysy, recordsy, programsy, ident,
  204. beginsy, ifsy, casesy, repeatsy, whilesy, forsy,
  205. endsy, elsesy, untilsy, ofsy, dosy, tosy, downtosy, thensy);
  206.  
  207. index = -xmax .. +xmax;
  208. alfa = packed array [1..alng] of char;
  209. object = (konstant, variable, typel, prozedure, funktion);
  210. types = (notyp, ints, reals, bools, chars, arrays, records);
  211. symset = set of symbol;
  212. typset = set of types;
  213. item = record
  214. typ: types; ref: index;
  215. end;
  216. order = packed record
  217. f: -omax..+omax;
  218. x: -lmax..+lmax;
  219. y: -nmax..+nmax;
  220. end;
  221.  
  222. var sy: symbol; (* last symbol read by insymbol *)
  223. id: alfa; (* identifier from insymbol *)
  224. inum: integer; (* integer from insymbol *)
  225. rnum: real; (* real number from insymbol *)
  226. sleng: integer; (* string length *)
  227. ch: char; (* last character read from source program *)
  228. line: array [1..llng] of char;
  229. cc: integer; (* character counter *)
  230. lc: integer; (* program location counter *)
  231. ll: integer; (* length of current line *)
  232. errs: set of 0..ermax;
  233. errpos: integer;
  234. progname: alfa;
  235. iflag, oflag: boolean;
  236. constbegsys, typebegsys, blockbegsys, facbegsys, statbegsys: symset;
  237. key: array [1..nkw] of alfa;
  238. ksy: array [1..nkw] of symbol;
  239. sps: array [char] of symbol; (* special symbols *)
  240.  
  241. t, a, b, sx, c1, c2: integer; (* indicies to tables *)
  242. stantyps: typset;
  243. display: array [0..lmax] of integer;
  244.  
  245. tab: array [0..tmax] of (* identifier table *)
  246. packed record
  247. name: alfa; link: index;
  248. obj: object; typ: types;
  249. ref: index; normal: boolean;
  250. lev: 0..lmax; adr: integer;
  251. end;
  252. atab: array [1..amax] of (* array-table *)
  253. packed record
  254. inxtyp, eltyp: types;
  255. elref, low, high, elsize, size: index;
  256. end;
  257. btab: array [1..bmax] of (* block table *)
  258. packed record
  259. last, lastpar, psize, vsize: index
  260. end;
  261. stab: packed array [0..smax] of char; (* string table *)
  262. rconst: array [1..c2max] of real;
  263. code: array [0..cmax] of order;
  264.  
  265. srcfil: text; { source input file [sam] }
  266.  
  267. procedure errormsg;
  268. var k: integer;
  269. msg: array [0..ermax] of alfa;
  270.  
  271. begin
  272. msg[ 0] := 'undef id '; msg[ 1] := 'multi def ';
  273. msg[ 2] := 'identifier'; msg[ 3] := 'program ';
  274. msg[ 4] := ') '; msg[ 5] := ': ';
  275. msg[ 6] := 'syntax '; msg[ 7] := 'ident, var';
  276. msg[ 8] := 'of '; msg[ 9] := '( ';
  277. msg[10] := 'id, array '; msg[11] := '[ ';
  278. msg[12] := '] '; msg[13] := '.. ';
  279. msg[14] := '; '; msg[15] := 'func. type';
  280. msg[16] := '= '; msg[17] := 'boolean ';
  281. msg[18] := 'convar typ'; msg[19] := 'type ';
  282. msg[20] := 'prog.param'; msg[21] := 'too big ';
  283. msg[22] := '. '; msg[23] := 'typ (case)';
  284. msg[24] := 'character '; msg[25] := 'const id ';
  285. msg[26] := 'index type'; msg[27] := 'indexbound';
  286. msg[28] := 'no array '; msg[29] := 'type id ';
  287. msg[30] := 'undef type'; msg[31] := 'no record ';
  288. msg[32] := 'boole type'; msg[33] := 'arith type';
  289. msg[34] := 'integer '; msg[35] := 'types ';
  290. msg[36] := 'param type'; msg[37] := 'variab id ';
  291. msg[38] := 'string '; msg[39] := 'no.of pars';
  292. msg[40] := 'type '; msg[41] := 'type ';
  293. msg[42] := 'real type '; msg[43] := 'integer ';
  294. msg[44] := 'var, const'; msg[45] := 'var, proc ';
  295. msg[46] := 'types (:=)'; msg[47] := 'typ (case)';
  296. msg[48] := 'type '; msg[49] := 'store ovfl';
  297. msg[50] := 'constant '; msg[51] := ':= ';
  298. msg[52] := 'then '; msg[53] := 'until ';
  299. msg[54] := 'do '; msg[55] := 'to downto ';
  300. msg[56] := 'begin '; msg[57] := 'end ';
  301. msg[58] := 'factor ';
  302. k := 0; writeln; writeln(' key words');
  303. while errs <> [] do
  304. begin while not (k in errs) do k := k+1;
  305. writeln(k,' ',msg[k]); errs := errs - [k]
  306. end
  307. end (* errormsg *);
  308.  
  309. procedure nextch; (* read next character; process line end *)
  310. begin if cc = ll then
  311. begin if eof(srcfil) {[sam]} then
  312. begin writeln;
  313. writeln(' program incomplete');
  314. errormsg; goto 99
  315. end;
  316. if errpos <> 0 then
  317. begin writeln; errpos := 0
  318. end;
  319. write(lc:5, ' ');
  320. ll := 0; cc := 0;
  321. while not eoln(srcfil) {[sam]} do
  322. begin ll := ll+1; read(srcfil{[sam]}, ch); write(ch); line[ll] := ch
  323. end;
  324. writeln; ll := ll+1; read(srcfil{[sam]}, line[ll]);
  325. end;
  326. cc := cc+1; ch := line[cc];
  327. end (* nextch *);
  328.  
  329. procedure error(n: integer);
  330. begin if errpos = 0 then write(' ****');
  331. if cc > errpos then
  332. begin write(' ': cc-errpos, '^', n:2);
  333. errpos := cc+3; errs := errs + [n]
  334. end
  335. end (* error *);
  336.  
  337. procedure fatal(n: integer);
  338. var msg: array [1..7] of alfa;
  339. begin writeln; errormsg;
  340. msg[ 1] := 'identifier'; msg[ 2] := 'procedures';
  341. msg[ 3] := 'reals '; msg[ 4] := 'arrays ';
  342. msg[ 5] := 'levels '; msg[ 6] := 'code ';
  343. msg[ 7] := 'strings ';
  344. writeln(' compiler table for ', msg[n], ' is too small');
  345. goto 99 (* terminate compilation *)
  346. end (* fatal *);
  347.  
  348. procedure insymbol; (* reads next symbol *)
  349. label 1, 2, 3;
  350. var i, j, k, e: integer;
  351.  
  352. procedure readscale;
  353. var s, sign: integer;
  354. begin nextch; sign := 1; s := 0;
  355. if ch = '+' then nextch else
  356. if ch = '-' then begin nextch; sign := -1 end;
  357. while ch in ['0'..'9'] do
  358. begin s := 10*s + ord(ch) - ord('0'); nextch
  359. end;
  360. e := s*sign + e
  361. end (* readscale *);
  362.  
  363. procedure adjustscale;
  364. var s: integer; d, t: real;
  365. begin if k+e > emax then error(21) else
  366. if k+e < emin then rnum := 0 else
  367. begin s := abs(e); t := 1.0; d := 10.0;
  368. repeat
  369. while not odd(s) do
  370. begin s := s div 2; d := sqr(d)
  371. end;
  372. s := s-1; t := d*t
  373. until s = 0;
  374. if e >= 0 then rnum := rnum*t else rnum := rnum/t
  375. end
  376. end (* adjustscale *);
  377.  
  378. begin (* insymbol *)
  379. 1: while ch = ' ' do nextch;
  380. if ch in ['a'..'z'] then
  381. begin (* word *) k := 0; id := ' ';
  382. repeat if k < alng then
  383. begin k := k+1; id[k] := ch
  384. end;
  385. nextch
  386. until not (ch in ['a'..'z', '0'..'9']);
  387. i := 1; j := nkw; (* binary search *)
  388. repeat k := (i+j) div 2;
  389. if id <= key[k] then j := k-1;
  390. if id >= key[k] then i := k+1
  391. until i > j;
  392. if i-1 > j then sy := ksy[k] else sy := ident
  393. end else
  394. if ch in ['0'..'9'] then
  395. begin (* number *) k := 0; inum := 0; sy := intcon;
  396. repeat inum := inum*10 + ord(ch) - ord('0');
  397. k := k+1; nextch
  398. until not (ch in ['0'..'9']);
  399. if (k > kmax) or (inum > nmax) then
  400. begin error(21); inum := 0; k := 0
  401. end;
  402. if ch = '.' then
  403. begin nextch;
  404. if ch = '.' then ch := ':' else
  405. begin sy := realcon; rnum := inum; e := 0;
  406. while ch in ['0'..'9'] do
  407. begin e := e-1;
  408. rnum := 10.0*rnum + (ord(ch)-ord('0')); nextch
  409. end;
  410. if ch = 'e' then readscale;
  411. if e <> 0 then adjustscale
  412. end
  413. end else
  414. if ch = 'e' then
  415. begin sy := realcon; rnum := inum; e := 0;
  416. readscale; if e <> 0 then adjustscale
  417. end;
  418. end else
  419. case ch of
  420. ':': begin nextch;
  421. if ch = '=' then
  422. begin sy := becomes; nextch
  423. end else sy := colon
  424. end;
  425. '<': begin nextch;
  426. if ch = '=' then begin sy := leg; nextch end else
  427. if ch = '>' then begin sy := neg; nextch end else sy := lss
  428. end;
  429. '>': begin nextch;
  430. if ch = '=' then begin sy := geg; nextch end else sy := gtr
  431. end;
  432. '.': begin nextch;
  433. if ch = '.' then
  434. begin sy := colon; nextch
  435. end else sy := period
  436. end;
  437. '''': begin k := 0;
  438. 2: nextch;
  439. if ch = '''' then
  440. begin nextch; if ch <> '''' then goto 3
  441. end;
  442. if sx+k = smax then fatal(7);
  443. stab[sx+k] := ch; k := k+1;
  444. if cc = 1 then
  445. begin (* end of line *) k := 0;
  446. end
  447. else goto 2;
  448. 3: if k = 1 then
  449. begin sy := charcon; inum := ord(stab[sx])
  450. end else
  451. if k = 0 then
  452. begin error(38); sy := charcon; inum := 0
  453. end else
  454. begin sy := stringt; inum := sx; sleng := k; sx := sx+k
  455. end
  456. end;
  457. '(': begin nextch;
  458. if ch <> '*' then sy := lparent else
  459. begin (* comment *) nextch;
  460. repeat
  461. while ch <> '*' do nextch;
  462. nextch
  463. until ch = ')';
  464. nextch; goto 1
  465. end
  466. end;
  467. '+', '-', '*', '/', ')', '=', ',', '[', ']', '#', '&', ';':
  468. begin sy := sps[ch]; nextch
  469. end;
  470. '$', '%', '@', '\', '~', '{', '}', '^':
  471. begin error(24); nextch; goto 1
  472. end
  473. end
  474. end (* insymbol *);
  475.  
  476. procedure enter(x0: alfa; x1: object;
  477. x2: types; x3: integer);
  478. begin t := t+1; (* enter standard identifier *)
  479. with tab[t] do
  480. begin name := x0; link := t-1; obj := x1;
  481. typ := x2; ref := 0; normal := true;
  482. lev := 0; adr := x3
  483. end
  484. end (* enter *);
  485.  
  486. procedure enterarray(tp: types; l, h: integer);
  487. begin if l > h then error(27);
  488. if (abs(l)>xmax) or (abs(h)>xmax) then
  489. begin error(27); l := 0; h := 0;
  490. end;
  491. if a = amax then fatal(4) else
  492. begin a:= a+1;
  493. with atab[a] do
  494. begin inxtyp := tp; low := l; high := h
  495. end
  496. end
  497. end (* enterarray *);
  498.  
  499. procedure enterblock;
  500. begin if b = bmax then fatal(2) else
  501. begin b := b+1; btab[b].last := 0; btab[b].lastpar := 0
  502. end
  503. end (* enterblock *);
  504.  
  505. procedure enterreal(x: real);
  506. begin if c2 = c2max-1 then fatal(3) else
  507. begin rconst[c2+1] := x; c1 := 1;
  508. while rconst[c1] <> x do c1 := c1+1;
  509. if c1 > c2 then c2 := c1
  510. end
  511. end (* enterreal *);
  512.  
  513. procedure emit(fct: integer);
  514. begin if lc = cmax then fatal(6);
  515. code[lc].f := fct; lc := lc+1
  516. end (* emit *);
  517.  
  518. procedure emit1(fct, b: integer);
  519. begin if lc = cmax then fatal(6);
  520. with code[lc] do
  521. begin f := fct; y := b end;
  522. lc := lc+1
  523. end (* emit1 *);
  524.  
  525. procedure emit2(fct, a, b: integer);
  526. begin if lc = cmax then fatal(6);
  527. with code[lc] do
  528. begin f := fct; x := a; y := b end;
  529. lc := lc+1
  530. end (* emit2 *);
  531.  
  532. procedure printtables;
  533. var i: integer; o: order;
  534. begin
  535. { Changed to double spacing [sam] }
  536. writeln('identifiers link obj typ ref nrm lev adr');
  537. writeln;
  538. for i := btab[1].last +1 to t do
  539. with tab[i] do
  540. writeln(i, ' ', name, link:5, ord(obj):5, ord(typ):5, ref:5,
  541. ord(normal):5, lev:5, adr:5);
  542. { Changed to double spacing [sam] }
  543. writeln('blocks last lpar psze vsze');
  544. writeln;
  545. for i := 1 to b do
  546. with btab[i] do
  547. writeln(i, last:5, lastpar:5, psize:5, vsize:5);
  548. { Changed to double spacing [sam] }
  549. writeln('arrays xtyp etyp eref low high elsz size');
  550. writeln;
  551. for i := 1 to a do
  552. with atab[i] do
  553. writeln(i, ord(inxtyp):5, ord(eltyp):5,
  554. elref:5, low:5, high:5, elsize:5, size:5);
  555. { Changed to double spacing [sam] }
  556. writeln('code:');
  557. writeln;
  558. for i := 0 to lc-1 do
  559. begin if i mod 5 = 0 then
  560. begin writeln; write(i: 5)
  561. end;
  562. o := code[i]; write(o.f:5);
  563. { Changed 36 to have a parameter, see notes in header [sam] }
  564. if (o.f < 31) or (o.f = 36) then
  565. if o.f < 4 then write(o.x:2, o.y:5)
  566. else write(o.y:7)
  567. else write(' ');
  568. write(',')
  569. end;
  570. writeln
  571. end (* printtables *);
  572.  
  573. procedure block(fsys: symset; isfun: boolean; level: integer);
  574. type conrec =
  575. record case tp: types of
  576. ints, chars, bools: (i: integer);
  577. reals: (r: real);
  578. notyp, arrays, records: ();
  579. end;
  580.  
  581. var dx: integer; (* data allocation index *)
  582. prt: integer; (* t-index of this procedure *)
  583. prb: integer; (* b-index of this procedure *)
  584. x: integer;
  585.  
  586. procedure skip(fsys: symset; n: integer);
  587. begin error(n);
  588. while not (sy in fsys) do insymbol
  589. end (* skip *);
  590.  
  591. procedure test(s1, s2: symset; n: integer);
  592. begin if not (sy in s1) then
  593. skip(s1+s2, n)
  594. end (* test *);
  595.  
  596. procedure testsemicolon;
  597. begin
  598. if sy = semicolon then insymbol else
  599. begin error(14);
  600. if sy in [comma, colon] then insymbol
  601. end;
  602. test([ident]+blockbegsys, fsys, 6)
  603. end (* testsemicolon *);
  604.  
  605. procedure enter(id: alfa; k: object);
  606. var j, l: integer;
  607. begin if t = tmax then fatal(1) else
  608. begin tab[0].name := id;
  609. j := btab[display[level]].last; l := j;
  610. while tab[j].name <> id do j := tab[j].link;
  611. if j <> 0 then error(1) else
  612. begin t := t+1;
  613. with tab[t] do
  614. begin name := id; link := l;
  615. obj := k; typ := notyp; ref := 0; lev := level;
  616. adr := 0
  617. end;
  618. btab[display[level]].last := t
  619. end
  620. end
  621. end (* enter *);
  622.  
  623. function loc(id: alfa): integer;
  624. var i, j: integer; (* locate id in table *)
  625. begin i := level; tab[0].name := id; (* sentinel *)
  626. repeat j := btab[display[i]].last;
  627. while tab[j].name <> id do j := tab[j].link;
  628. i := i-1;
  629. until (i<0) or (j<>0);
  630. if j = 0 then error(0); loc := j
  631. end (* loc *);
  632.  
  633. procedure entervariable;
  634. begin if sy = ident then
  635. begin enter(id, variable); insymbol
  636. end
  637. else error(2)
  638. end (* entervariable *);
  639.  
  640. procedure constant(fsys: symset; var c: conrec);
  641. var x, sign: integer;
  642. begin c.tp := notyp; c.i := 0;
  643. test(constbegsys, fsys, 50);
  644. if sy in constbegsys then
  645. begin
  646. if sy = charcon then
  647. begin c.tp := chars; c.i := inum; insymbol
  648. end
  649. else
  650. begin sign := 1;
  651. if sy in [plus, minus] then
  652. begin if sy = minus then sign := -1;
  653. insymbol
  654. end;
  655. if sy = ident then
  656. begin x := loc(id);
  657. if x <> 0 then
  658. if tab[x].obj <> konstant then error(25) else
  659. begin c.tp := tab[x].typ;
  660. if c.tp = reals
  661. then c.r := sign*rconst[tab[x].adr]
  662. else c.i := sign*tab[x].adr
  663. end;
  664. insymbol
  665. end
  666. else
  667. if sy = intcon then
  668. begin c.tp := ints; c.i := sign*inum; insymbol
  669. end else
  670. if sy = realcon then
  671. begin c.tp := reals; c.r := sign*rnum; insymbol
  672. end else skip(fsys, 50)
  673. end;
  674. test(fsys, [], 6)
  675. end
  676. end (* constant *);
  677.  
  678. procedure typ(fsys: symset; var tp: types; var rf, sz: integer);
  679. var x: integer;
  680. eltp: types; elrf: integer;
  681. elsz, offset, t0, t1: integer;
  682.  
  683. procedure arraytyp(var aref, arsz: integer);
  684. var eltp: types;
  685. low, high: conrec;
  686. elrf, elsz: integer;
  687. begin constant([colon, rbrack, rparent, ofsy]+fsys, low);
  688. if low.tp = reals then
  689. begin error(27); low.tp := ints; low.i := 0
  690. end;
  691. if sy = colon then insymbol else error(13);
  692. constant([rbrack, comma, rparent, ofsy]+fsys, high);
  693. if high.tp <> low.tp then
  694. begin error(27); high.i := low.i
  695. end;
  696. enterarray(low.tp, low.i, high.i); aref := a;
  697. if sy = comma then
  698. begin insymbol; eltp := arrays; arraytyp(elrf, elsz)
  699. end else
  700. begin
  701. if sy = rbrack then insymbol else
  702. begin error(12);
  703. if sy = rparent then insymbol
  704. end;
  705. if sy = ofsy then insymbol else error(8);
  706. typ(fsys, eltp, elrf, elsz)
  707. end;
  708. with atab[aref] do
  709. begin arsz := (high-low+1)*elsz; size := arsz;
  710. eltyp := eltp; elref := elrf; elsize := elsz
  711. end;
  712. end (* arraytyp *);
  713.  
  714. begin (* typ *) tp := notyp; rf := 0; sz := 0;
  715. test(typebegsys, fsys, 10);
  716. if sy in typebegsys then
  717. begin
  718. if sy = ident then
  719. begin x := loc(id);
  720. if x <> 0 then
  721. with tab[x] do
  722. if obj <> typel then error(29) else
  723. begin tp := typ; rf := ref; sz := adr;
  724. if tp = notyp then error(30)
  725. end;
  726. insymbol
  727. end else
  728. if sy = arraysy then
  729. begin insymbol;
  730. if sy = lbrack then insymbol else
  731. begin error(11);
  732. if sy = lparent then insymbol
  733. end;
  734. tp := arrays; arraytyp(rf, sz)
  735. end else
  736. begin (* records *) insymbol;
  737. enterblock; tp := records; rf := b;
  738. if level = lmax then fatal(5);
  739. level := level+1; display[level] := b; offset := 0;
  740. while sy <> endsy do
  741. begin (* field section *)
  742. if sy = ident then
  743. begin t0 := t; entervariable;
  744. while sy = comma do
  745. begin insymbol; entervariable
  746. end;
  747. if sy = colon then insymbol else error(5);
  748. t1 := t;
  749. typ(fsys+[semicolon, endsy, comma, ident],
  750. eltp, elrf, elsz);
  751. while t0 < t1 do
  752. begin t0 := t0+1;
  753. with tab[t0] do
  754. begin typ := eltp; ref := elrf; normal := true;
  755. adr := offset; offset := offset + elsz
  756. end
  757. end
  758. end;
  759. if sy <> endsy then
  760. begin if sy = semicolon then insymbol else
  761. begin error(14);
  762. if sy = comma then insymbol
  763. end;
  764. test([ident, endsy, semicolon], fsys, 6)
  765. end
  766. end;
  767. btab[rf].vsize := offset; sz := offset;
  768. btab[rf].psize := 0; insymbol; level := level-1
  769. end;
  770. test(fsys, [], 6)
  771. end
  772. end (* typ *);
  773.  
  774. procedure parameterlist; (* formal parameter list *)
  775. var tp: types;
  776. rf, sz, x, t0: integer;
  777. valpar: boolean;
  778. begin insymbol; tp := notyp; rf := 0; sz := 0;
  779. test([ident, varsy], fsys+[rparent], 7);
  780. while sy in [ident, varsy] do
  781. begin if sy <> varsy then valpar := true else
  782. begin insymbol; valpar := false
  783. end;
  784. t0 := t; entervariable;
  785. while sy = comma do
  786. begin insymbol; entervariable;
  787. end;
  788. if sy = colon then
  789. begin insymbol;
  790. if sy <> ident then error(2) else
  791. begin x := loc(id); insymbol;
  792. if x <> 0 then
  793. with tab[x] do
  794. if obj <> typel then error(29) else
  795. begin tp := typ; rf := ref;
  796. if valpar then sz := adr else sz := 1
  797. end;
  798. end;
  799. test([semicolon, rparent], [comma, ident]+fsys, 14)
  800. end
  801. else error(5);
  802. while t0 < t do
  803. begin t0 := t0+1;
  804. with tab[t0] do
  805. begin typ := tp; ref := rf;
  806. normal := valpar; adr := dx; lev := level;
  807. dx := dx + sz
  808. end
  809. end;
  810. if sy <> rparent then
  811. begin if sy = semicolon then insymbol else
  812. begin error(14);
  813. if sy = comma then insymbol
  814. end;
  815. test([ident, varsy], [rparent]+fsys, 6)
  816. end
  817. end (* while *);
  818. if sy = rparent then
  819. begin insymbol;
  820. test([semicolon, colon], fsys, 6)
  821. end
  822. else error(4)
  823. end (* parameter list *);
  824.  
  825. procedure constantdeclaration;
  826. var c: conrec;
  827. begin insymbol;
  828. test([ident], blockbegsys, 2);
  829. while sy = ident do
  830. begin enter(id, konstant); insymbol;
  831. if sy = egl then insymbol else
  832. begin error(16);
  833. if sy = becomes then insymbol
  834. end;
  835. constant([semicolon, comma, ident]+fsys, c);
  836. tab[t].typ := c.tp; tab[t].ref := 0;
  837. if c.tp = reals then
  838. begin enterreal(c.r); tab[t].adr := c1 end
  839. else tab[t].adr := c.i;
  840. testsemicolon
  841. end
  842. end (* constantdeclaration *);
  843.  
  844. procedure typedeclaration;
  845. var tp: types; rf, sz, t1: integer;
  846. begin insymbol;
  847. test([ident], blockbegsys, 2);
  848. while sy = ident do
  849. begin enter(id, typel); t1 := t; insymbol;
  850. if sy = egl then insymbol else
  851. begin error(16);
  852. if sy = becomes then insymbol
  853. end;
  854. typ([semicolon, comma, ident]+fsys, tp, rf, sz);
  855. with tab[t1] do
  856. begin typ := tp; ref := rf; adr := sz
  857. end;
  858. testsemicolon
  859. end
  860. end (* typedeclaration *);
  861.  
  862. procedure variabledeclaration;
  863. var t0, t1, rf, sz: integer;
  864. tp: types;
  865. begin insymbol;
  866. while sy = ident do
  867. begin t0 := t; entervariable;
  868. while sy = comma do
  869. begin insymbol; entervariable;
  870. end;
  871. if sy = colon then insymbol else error(5);
  872. t1 := t;
  873. typ([semicolon, comma, ident]+fsys, tp, rf, sz);
  874. while t0 < t1 do
  875. begin t0 := t0+1;
  876. with tab[t0] do
  877. begin typ := tp; ref := rf;
  878. lev := level; adr := dx; normal := true;
  879. dx := dx + sz
  880. end
  881. end;
  882. testsemicolon
  883. end
  884. end (* variabledeclaration *);
  885.  
  886. procedure procdeclaration;
  887. var isfun: boolean;
  888. begin isfun := sy = functionsy; insymbol;
  889. if sy <> ident then
  890. begin error(2); id := ' ';
  891. end;
  892. if isfun then enter(id, funktion) else enter(id, prozedure);
  893. tab[t].normal := true;
  894. insymbol; block([semicolon]+fsys, isfun, level+1);
  895. if sy = semicolon then insymbol else error(14);
  896. emit(32+ord(isfun)) (* exit *)
  897. end (* proceduredeclaration *);
  898.  
  899. procedure statement(fsys: symset);
  900. var i: integer;
  901. procedure expression(fsys: symset; var x: item); forward;
  902.  
  903. procedure selector(fsys: symset; var v: item);
  904. var x: item; a, j: integer;
  905. begin (* sy in [lparent, lbrack, period] *)
  906. repeat if sy = period then
  907. begin insymbol; (* field selector *)
  908. if sy <> ident then error(2) else
  909. begin
  910. if v.typ <> records then error(31) else
  911. begin (* search field identifier *)
  912. j := btab[v.ref].last; tab[0].name := id;
  913. while tab[j].name <> id do j := tab[j].link;
  914. if j = 0 then error(0);
  915. v.typ := tab[j].typ; v.ref := tab[j].ref;
  916. a := tab[j].adr; if a <> 0 then emit1(9, a)
  917. end;
  918. insymbol
  919. end
  920. end else
  921. begin (* array selector *)
  922. if sy <> lbrack then error(11);
  923. repeat insymbol;
  924. expression(fsys+[comma, rbrack], x);
  925. if v.typ <> arrays then error(28) else
  926. begin a := v.ref;
  927. if atab[a].inxtyp <> x.typ then error(26) else
  928. if atab[a].elsize = 1 then emit1(20, a)
  929. else emit1(21, a);
  930. v.typ := atab[a].eltyp; v.ref := atab[a].elref
  931. end
  932. until sy <> comma;
  933. if sy = rbrack then insymbol else
  934. begin error(12); if sy = rparent then insymbol
  935. end
  936. end
  937. until not (sy in [lbrack, lparent, period]);
  938. test(fsys, [], 6)
  939. end (* selector *);
  940.  
  941. procedure call(fsys: symset; i: integer);
  942. var x: item;
  943. lastp, cp, k: integer;
  944. begin emit1(18, i); (* mark stack *)
  945. lastp := btab[tab[i].ref].lastpar; cp := i;
  946. if sy = lparent then
  947. begin (* actual parameter list *)
  948. repeat insymbol;
  949. if cp >= lastp then error(39) else
  950. begin cp := cp+1;
  951. if tab[cp].normal then
  952. begin (* value parameter *)
  953. expression(fsys+[comma, colon, rparent], x);
  954. if x.typ = tab[cp].typ then
  955. begin
  956. if x.ref <> tab[cp].ref then error(36) else
  957. if x.typ = arrays then emit1(22, atab[x.ref].size) else
  958. if x.typ = records then emit1(22, btab[x.ref].vsize)
  959.  
  960. end else
  961. if (x.typ = ints) and (tab[cp].typ = reals) then
  962. emit1(26, 0) else
  963. if x.typ <> notyp then error(36);
  964. end else
  965. begin (* variable parameter *)
  966. if sy <> ident then error(2) else
  967. begin k := loc(id); insymbol;
  968. if k <> 0 then
  969. begin if tab[k].obj <> variable then error(37);
  970. x.typ := tab[k].typ; x.ref := tab[k].ref;
  971. if tab[k].normal
  972. then emit2(0, tab[k].lev, tab[k].adr)
  973. else emit2(1, tab[k].lev, tab[k].adr);
  974. if sy in [lbrack, lparent, period] then
  975. selector(fsys+[comma, colon, rparent], x);
  976. if (x.typ <> tab[cp].typ) or (x.ref<>tab[cp].ref)
  977. then error(36)
  978. end
  979. end
  980. end
  981. end;
  982. test([comma, rparent], fsys, 6)
  983. until sy <> comma;
  984. if sy = rparent then insymbol else error(4)
  985. end;
  986. if cp < lastp then error(39); (* too few actual parameters *)
  987. emit1(19, btab[tab[i].ref].psize-1);
  988. if tab[i].lev < level then emit2(3, tab[i].lev, level)
  989. end (* call *);
  990.  
  991. function resulttype(a, b: types): types;
  992. begin
  993. if (a>reals) or (b>reals) then
  994. begin error(33); resulttype := notyp
  995. end else
  996. if (a=notyp) or (b=notyp) then resulttype := notyp else
  997. if a=ints then
  998. if b=ints then resulttype := ints else
  999. begin resulttype := reals; emit1(26, 1)
  1000. end
  1001. else
  1002. begin resulttype := reals;
  1003. if b=ints then emit1(26, 0)
  1004. end
  1005. end (* resulttype *);
  1006.  
  1007. procedure expression;
  1008. var y: item; op: symbol;
  1009.  
  1010. procedure simpleexpression(fsys: symset; var x: item);
  1011. var y: item; op: symbol;
  1012.  
  1013. procedure term(fsys: symset; var x: item);
  1014. var y: item; op: symbol;
  1015.  
  1016. procedure factor(fsys: symset; var x: item);
  1017. var i, f: integer;
  1018.  
  1019. procedure standfct(n: integer);
  1020. var ts: typset;
  1021. begin (* standard function no. n *)
  1022. if sy = lparent then insymbol else error(9);
  1023. if n < 17 then
  1024. begin expression(fsys+[rparent], x);
  1025. case n of
  1026. (* abs, sqr *) 0, 2: begin ts:= [ints, reals];
  1027. tab[i].typ := x.typ;
  1028. if x.typ = reals then n := n+1
  1029. end;
  1030. (* odd, chr *) 4, 5: ts := [ints];
  1031. (* ord *) 6: ts := [ints, bools, chars];
  1032. (* succ, pred *) 7, 8: ts := [chars];
  1033. (* round, trunc *) 9, 10, 11, 12, 13, 14, 15, 16:
  1034. (* sin, cos, ...*) begin ts := [ints, reals];
  1035. if x.typ = ints then emit1(26, 0)
  1036. end;
  1037. end;
  1038. if x.typ in ts then emit1(8, n) else
  1039. if x.typ <> notyp then error(48)
  1040. end else
  1041. (* eof, eoln *) begin (* n in [17, 18] *)
  1042. if sy <> ident then error(2) else
  1043. if id <> 'input ' then error(0) else insymbol;
  1044. emit1(8, n);
  1045. end;
  1046. x.typ := tab[i].typ;
  1047. if sy = rparent then insymbol else error(4)
  1048. end (* standfct *);
  1049.  
  1050. begin (* factor *) x.typ := notyp; x.ref := 0;
  1051. test(facbegsys, fsys, 58);
  1052. while sy in facbegsys do
  1053. begin
  1054. if sy = ident then
  1055. begin i := loc(id); insymbol;
  1056. with tab[i] do
  1057. case obj of
  1058. konstant: begin x.typ := typ; x.ref := 0;
  1059. if x.typ = reals then
  1060. emit1(25, adr) else
  1061. emit1(24, adr)
  1062. end;
  1063.  
  1064. variable: begin x.typ := typ; x.ref := ref;
  1065. if sy in [lbrack, lparent, period] then
  1066. begin if normal then f := 0 else f := 1;
  1067. emit2(f, lev, adr);
  1068. selector(fsys, x);
  1069. if x.typ in stantyps then emit(34)
  1070. end else
  1071. begin
  1072. if x.typ in stantyps then
  1073. if normal then f := 1 else f := 2
  1074. else
  1075. if normal then f := 0 else f := 1;
  1076. emit2(f, lev, adr)
  1077. end
  1078. end;
  1079. typel, prozedure: error(44);
  1080. funktion: begin x.typ := typ;
  1081. if lev <> 0 then call(fsys, i)
  1082. else standfct(adr)
  1083. end
  1084. end (* case, with *)
  1085. end else
  1086. if sy in [charcon, intcon, realcon] then
  1087. begin
  1088. if sy = realcon then
  1089. begin x.typ := reals; enterreal(rnum);
  1090. emit1(25, c1)
  1091. end else
  1092. begin if sy = charcon then x.typ := chars
  1093. else x.typ := ints;
  1094. emit1(24, inum)
  1095. end;
  1096. x.ref := 0; insymbol
  1097. end else
  1098. if sy = lparent then
  1099. begin insymbol; expression(fsys+[rparent], x);
  1100. if sy = rparent then insymbol else error(4)
  1101. end else
  1102. if sy = notsy then
  1103. begin insymbol; factor(fsys, x);
  1104. if x.typ=bools then emit(35) else
  1105. if x.typ<>notyp then error(32)
  1106. end;
  1107. test(fsys, facbegsys, 6)
  1108. end (* while *)
  1109. end (* factor *);
  1110.  
  1111. begin (* term *)
  1112. factor(fsys+[times, rdiv, idiv, imod, andsy], x);
  1113. while sy in [times, rdiv, idiv, imod, andsy] do
  1114. begin op := sy; insymbol;
  1115. factor(fsys+[times, rdiv, idiv, imod, andsy], y);
  1116. if op = times then
  1117. begin x.typ := resulttype(x.typ, y.typ);
  1118. case x.typ of
  1119. notyp: ;
  1120. ints : emit(57);
  1121. reals: emit(60);
  1122. end
  1123. end else
  1124. if op = rdiv then
  1125. begin
  1126. if x.typ = ints then
  1127. begin emit1(26, 1); x.typ := reals
  1128. end;
  1129. if y.typ = ints then
  1130. begin emit1(26, 0); y.typ := reals
  1131. end;
  1132. if (x.typ=reals) and (y.typ=reals) then
  1133. emit(61) else
  1134. begin if (x.typ<>notyp) and (y.typ<>notyp) then
  1135. error(32);
  1136. x.typ := notyp
  1137. end
  1138. end else
  1139. if op = andsy then
  1140. begin if (x.typ=bools) and (y.typ=bools) then
  1141. emit(56) else
  1142. begin if (x.typ<>notyp) and (y.typ<>notyp)
  1143. then error(32);
  1144. x.typ := notyp
  1145. end
  1146. end else
  1147. begin (* op in [idiv, imod] *)
  1148. if (x.typ=ints) and (y.typ=ints) then
  1149. if op=idiv then emit(58)
  1150. else emit(59) else
  1151. begin if (x.typ<>notyp) and (y.typ<>notyp) then
  1152. error(34);
  1153. x.typ := notyp
  1154. end
  1155. end
  1156. end
  1157. end (* term *);
  1158.  
  1159. begin (* simpleexpression *)
  1160. if sy in [plus, minus] then
  1161. begin op := sy; insymbol;
  1162. term(fsys+[plus, minus], x);
  1163. if x.typ > reals then error(33) else
  1164. { Changed the negate instruction 36 to also emit a parameter that
  1165.   says if the operand is real or integer. See comments at top. [sam] }
  1166. if op = minus then emit1(36, ord(x.typ))
  1167. end else
  1168. term(fsys+[plus, minus, orsy], x);
  1169. while sy in [plus, minus, orsy] do
  1170. begin op := sy; insymbol;
  1171. term(fsys+[plus, minus, orsy], y);
  1172. if op = orsy then
  1173. begin
  1174. if (x.typ=bools) and (y.typ=bools) then emit(51) else
  1175. begin if (x.typ<>notyp) and (y.typ<>notyp) then
  1176. error(32);
  1177. x.typ := notyp
  1178. end
  1179. end else
  1180. begin x.typ := resulttype(x.typ, y.typ);
  1181. case x.typ of
  1182. notyp: ;
  1183. ints: if op = plus then emit (52)
  1184. else emit(53);
  1185. reals: if op = plus then emit(54)
  1186. else emit(55)
  1187. end
  1188. end
  1189. end
  1190. end (* simpleexpression *);
  1191.  
  1192. begin (* expression *)
  1193. simpleexpression(fsys+[egl, neg, lss, leg, gtr, geg], x);
  1194. if sy in [egl, neg, lss, leg, gtr, geg] then
  1195. begin op := sy; insymbol;
  1196. simpleexpression(fsys, y);
  1197. if (x.typ in [notyp, ints, bools, chars]) and
  1198. (x.typ = y.typ) then
  1199. case op of
  1200. egl: emit(45);
  1201. neg: emit(46);
  1202. lss: emit(47);
  1203. leg: emit(48);
  1204. gtr: emit(49);
  1205. geg: emit(50);
  1206. end else
  1207. begin if x.typ = ints then
  1208. begin x.typ := reals; emit1(26, 1)
  1209. end else
  1210. if y.typ = ints then
  1211. begin y.typ := reals; emit1(26, 0)
  1212. end;
  1213. if (x.typ=reals) and (y.typ=reals) then
  1214. case op of
  1215. egl: emit(39);
  1216. neg: emit(40);
  1217. lss: emit(41);
  1218. leg: emit(42);
  1219. gtr: emit(43);
  1220. geg: emit(44);
  1221. end
  1222. else error(35)
  1223. end;
  1224. x.typ := bools
  1225. end
  1226. end (* expression *);
  1227.  
  1228. procedure assignment(lv, ad: integer);
  1229. var x,y: item; f: integer;
  1230. (* tab[i].obj in [variable, prozedure] *)
  1231. begin x.typ := tab[i].typ; x.ref := tab[i].ref;
  1232. if tab[i].normal then f := 0 else f := 1;
  1233. emit2(f, lv, ad);
  1234. if sy in [lbrack, lparent, period] then
  1235. selector([becomes, egl]+fsys, x);
  1236. if sy = becomes then insymbol else
  1237. begin error(51); if sy = egl then insymbol
  1238. end;
  1239. expression(fsys, y);
  1240. if x.typ = y.typ then
  1241. if x.typ in stantyps then emit(38) else
  1242. if x.ref <> y.ref then error(46) else
  1243. if x.typ = arrays then emit1(23, atab[x.ref].size)
  1244. else emit1(23, btab[x.ref].vsize)
  1245. else
  1246. if (x.typ=reals) and (y.typ=ints) then
  1247. begin emit1(26, 0); emit(38)
  1248. end else
  1249. if (x.typ<>notyp) and (y.typ<>notyp) then error(46)
  1250. end (* assignment *);
  1251.  
  1252. procedure compoundstatement;
  1253. begin insymbol;
  1254. statement([semicolon, endsy]+fsys);
  1255. while sy in [semicolon]+statbegsys do
  1256. begin if sy = semicolon then insymbol else error(14);
  1257. statement([semicolon, endsy]+fsys)
  1258. end;
  1259. if sy = endsy then insymbol else error(57)
  1260. end (* compoundstatement *);
  1261.  
  1262. procedure ifstatement;
  1263. var x: item; lc1, lc2: integer;
  1264. begin insymbol;
  1265. expression(fsys+[thensy, dosy], x);
  1266. if not (x.typ in [bools, notyp]) then error(17);
  1267. lc1 := lc; emit(11); (* jmpc *)
  1268. if sy = thensy then insymbol else
  1269. begin error(52); if sy = dosy then insymbol
  1270. end;
  1271. statement(fsys+[elsesy]);
  1272. if sy = elsesy then
  1273. begin insymbol; lc2 := lc; emit(10);
  1274. code[lc1].y := lc; statement(fsys); code[lc2].y := lc
  1275. end
  1276. else code[lc1].y := lc
  1277. end (* if statment *);
  1278.  
  1279. procedure casestatement;
  1280. var x: item;
  1281. i, j, k, lc1: integer;
  1282. casetab: array [1..csmax] of
  1283. packed record val, lc: index end;
  1284. exittab: array [1..csmax] of integer;
  1285.  
  1286. procedure caselabel;
  1287. var lab: conrec; k: integer;
  1288. begin constant(fsys+[comma, colon], lab);
  1289. if lab.tp <> x.typ then error(47) else
  1290. if i = csmax then fatal(6) else
  1291. begin i := i+1; k := 0;
  1292. casetab[i].val := lab.i; casetab[i].lc := lc;
  1293. repeat k := k+1 until casetab[k].val = lab.i;
  1294. if k < i then error(1); (* multiple definition *)
  1295. end
  1296. end (* caselabel *);
  1297.  
  1298. procedure onecase;
  1299. begin if sy in constbegsys then
  1300. begin caselabel;
  1301. while sy = comma do
  1302. begin insymbol; caselabel
  1303. end;
  1304. if sy = colon then insymbol else error(5);
  1305. statement([semicolon, endsy]+fsys);
  1306. j := j+1; exittab[j] := lc; emit(10)
  1307. end
  1308. end (* onecase *);
  1309.  
  1310. begin insymbol; i := 0; j := 0;
  1311. expression(fsys+[ofsy, comma, colon], x);
  1312. if not (x.typ in [ints, bools, chars, notyp]) then error(23);
  1313. lc1 := lc; emit(12); (* jmpx *)
  1314. if sy = ofsy then insymbol else error(8);
  1315. onecase;
  1316. while sy = semicolon do
  1317. begin insymbol; onecase
  1318. end;
  1319. code[lc1].y := lc;
  1320. for k := 1 to i do
  1321. begin emit1(13, casetab[k].val); emit1(13, casetab[k].lc)
  1322. end;
  1323. emit1(10, 0);
  1324. for k := 1 to j do code[exittab[k]].y := lc;
  1325. if sy = endsy then insymbol else error(57)
  1326. end (* casestement *);
  1327.  
  1328. procedure repeatstatement;
  1329. var x: item; lc1: integer;
  1330. begin lc1 := lc;
  1331. insymbol; statement([semicolon, untilsy]+fsys);
  1332. while sy in [semicolon]+statbegsys do
  1333. begin if sy = semicolon then insymbol else error(14);
  1334. statement([semicolon, untilsy]+fsys)
  1335. end;
  1336. if sy = untilsy then
  1337. begin insymbol; expression(fsys, x);
  1338. if not (x.typ in [bools, notyp]) then error(17);
  1339. emit1(11, lc1)
  1340. end
  1341. else error(53)
  1342. end (* repeatstement *);
  1343.  
  1344. procedure whilestatement;
  1345. var x: item; lc1, lc2: integer;
  1346. begin insymbol; lc1 := lc;
  1347. expression(fsys+[dosy], x);
  1348. if not (x.typ in [bools, notyp]) then error(17);
  1349. lc2 := lc; emit(11);
  1350. if sy = dosy then insymbol else error(54);
  1351. statement(fsys); emit1(10, lc1); code[lc2].y := lc
  1352. end (* whilestatement *);
  1353.  
  1354. procedure forstatement;
  1355. var cvt: types; x: item;
  1356. i, f, lc1, lc2: integer;
  1357. begin insymbol;
  1358. if sy = ident then
  1359. begin i := loc(id); insymbol;
  1360. if i = 0 then cvt := ints else
  1361. if tab[i].obj = variable then
  1362. begin cvt := tab[i].typ;
  1363. emit2(0, tab[i].lev, tab[i].adr);
  1364. if not (cvt in [notyp, ints, bools, chars])
  1365. then error(18)
  1366. end else
  1367. begin error(37); cvt := ints
  1368. end
  1369. end else skip([becomes, tosy, downtosy, dosy]+fsys, 2);
  1370. if sy = becomes then
  1371. begin insymbol; expression([tosy, downtosy, dosy]+fsys, x);
  1372. if x.typ <> cvt then error(19);
  1373. end else skip([tosy, downtosy, dosy]+fsys, 51);
  1374. f := 14;
  1375. if sy in [tosy, downtosy] then
  1376. begin if sy = downtosy then f := 16;
  1377. insymbol; expression([dosy]+fsys, x);
  1378. if x.typ <> cvt then error(19)
  1379. end else skip([dosy]+fsys, 55);
  1380. lc1 := lc; emit(f);
  1381. if sy = dosy then insymbol else error(54);
  1382. lc2 := lc; statement(fsys);
  1383. emit1(f+1, lc2); code[lc1].y := lc
  1384. end (* forstatement *);
  1385.  
  1386. procedure standproc(n: integer);
  1387. var i, f: integer;
  1388. x, y: item;
  1389. begin
  1390. case n of
  1391. 1, 2: begin (* read *)
  1392. if not iflag then
  1393. begin error(20); iflag := true
  1394. end;
  1395. if sy = lparent then
  1396. begin
  1397. repeat insymbol;
  1398. if sy <> ident then error(2) else
  1399. begin i := loc(id); insymbol;
  1400. if i <> 0 then
  1401. if tab[i].obj <> variable then error(37) else
  1402. begin x.typ := tab[i].typ; x.ref := tab[i].ref;
  1403. if tab[i].normal then f := 0 else f := 1;
  1404. emit2(f, tab[i].lev, tab[i].adr);
  1405. if sy in [lbrack, lparent, period] then
  1406. selector(fsys+[comma, rparent], x);
  1407. if x.typ in [ints, reals, chars, notyp] then
  1408. emit1(27, ord(x.typ)) else error(40)
  1409. end
  1410. end;
  1411. test([comma, rparent], fsys, 6);
  1412. until sy <> comma;
  1413. if sy = rparent then insymbol else error(4)
  1414. end;
  1415. if n = 2 then emit(62)
  1416. end;
  1417. 3, 4: begin (* write *)
  1418. if sy = lparent then
  1419. begin
  1420. repeat insymbol;
  1421. if sy = stringt then
  1422. begin emit1(24, sleng); emit1(28, inum); insymbol
  1423. end else
  1424. begin expression(fsys+[comma, colon, rparent], x);
  1425. if not (x.typ in stantyps) then error(41);
  1426. if sy = colon then
  1427. begin insymbol;
  1428. expression(fsys+[comma, colon, rparent], y);
  1429. if y.typ <> ints then error(43);
  1430. if sy = colon then
  1431. begin if x.typ <> reals then error(42);
  1432. insymbol; expression(fsys+[comma, rparent], y);
  1433. if y.typ <> ints then error(43);
  1434. emit(37)
  1435. end
  1436. else emit1(30, ord(x.typ))
  1437. end
  1438. else emit1(29, ord(x.typ))
  1439. end
  1440. until sy <> comma;
  1441. if sy = rparent then insymbol else error(4)
  1442. end;
  1443. if n = 4 then emit(63)
  1444. end;
  1445. end(* case *)
  1446. end (* standproc *);
  1447.  
  1448. begin (* statement *)
  1449. if sy in statbegsys+[ident] then
  1450. case sy of
  1451. ident: begin i:= loc(id); insymbol;
  1452. if i <> 0 then
  1453. case tab[i].obj of
  1454. konstant, typel: error(45);
  1455. variable:
  1456. assignment(tab[i].lev, tab[i].adr);
  1457. prozedure:
  1458. if tab[i].lev <> 0 then call(fsys, i)
  1459. else standproc(tab[i].adr);
  1460. funktion:
  1461. if tab[i].ref = display[level]
  1462. then assignment(tab[i].lev+1, 0)
  1463. else error(45)
  1464. end
  1465. end;
  1466. beginsy: compoundstatement;
  1467. ifsy: ifstatement;
  1468. casesy: casestatement;
  1469. whilesy: whilestatement;
  1470. repeatsy: repeatstatement;
  1471. forsy: forstatement;
  1472. end;
  1473. test(fsys, [], 14)
  1474. end (* statement *);
  1475.  
  1476. begin (* block *) dx := 5; prt := t;
  1477. if level > lmax then fatal(5);
  1478. test([lparent, colon, semicolon], fsys, 7);
  1479. enterblock; display[level] := b; prb := b;
  1480. tab[prt].typ := notyp; tab[prt].ref := prb;
  1481. if sy = lparent then parameterlist;
  1482. btab[prb].lastpar := t; btab[prb].psize := dx;
  1483. if isfun then
  1484. if sy = colon then
  1485. begin insymbol; (* function type *)
  1486. if sy = ident then
  1487. begin x := loc(id); insymbol;
  1488. if x <> 0 then
  1489. if tab[x].obj <> typel then error(29) else
  1490. if tab[x].typ in stantyps
  1491. then tab[prt].typ := tab[x].typ
  1492. else error(15)
  1493. end else skip([semicolon]+fsys, 2)
  1494. end else error(5);
  1495. if sy = semicolon then insymbol else error(14);
  1496. repeat
  1497. if sy = constsy then constantdeclaration;
  1498. if sy = typesy then typedeclaration;
  1499. if sy = varsy then variabledeclaration;
  1500. btab[prb].vsize := dx;
  1501. while sy in [proceduresy, functionsy] do procdeclaration;
  1502. test([beginsy], blockbegsys+statbegsys, 56)
  1503. until sy in statbegsys;
  1504. tab[prt].adr := lc;
  1505. insymbol; statement([semicolon, endsy]+fsys);
  1506. while sy in [semicolon]+statbegsys do
  1507. begin if sy = semicolon then insymbol else error(14);
  1508. statement([semicolon, endsy]+fsys)
  1509. end;
  1510. if sy = endsy then insymbol else error(57);
  1511. test(fsys+[period], [], 6)
  1512. end (* block *);
  1513.  
  1514. procedure interpret;
  1515. (* global code, tab, btab *)
  1516. var ir: order; (* instruction buffer *)
  1517. pc: integer; (* program counter *)
  1518. ps: (run, fin, caschk, divchk, inxchk, stkchk, linchk,
  1519. lngchk, redchk);
  1520. t: integer; (* top stack index *)
  1521. b: integer; (* base index *)
  1522. lncnt, ocnt, blkcnt, chrcnt: integer; (* counters *)
  1523. h1, h2, h3, h4: integer;
  1524. fld: array [1..4] of integer; (* default field widths *)
  1525.  
  1526. display: array [1..lmax] of integer;
  1527. s: array [1..stacksize] of (* blockmark: *)
  1528. record case types of (* s[b+0] = fct result *)
  1529. ints: (i: integer); (* s[b+1] = return adr *)
  1530. reals: (r: real); (* s[b+2] = static link *)
  1531. bools: (b: boolean); (* s[b+3] = dynamic link *)
  1532. chars: (c: char); (* s[b+4] = table index *)
  1533. notyp, arrays, records: ()
  1534. end;
  1535.  
  1536. begin (* interpret *)
  1537. s[1].i := 0; s[2].i := 0; s[3].i := -1; s[4].i := btab[1].last;
  1538. b := 0; display[1] := 0;
  1539. t := btab[2].vsize - 1; pc := tab[s[4].i].adr;
  1540. ps := run;
  1541. lncnt := 0; ocnt := 0; chrcnt := 0;
  1542. fld[1] := intfld; fld[2] := relfld; fld[3] := bolfld; fld[4] := chrfld;
  1543. repeat ir := code[pc]; pc := pc+1; ocnt := ocnt + 1;
  1544. case ir.f of
  1545. 0: begin (* load address *) t := t+1;
  1546. if t > stacksize then ps := stkchk
  1547. else s[t].i := display[ir.x] + ir.y
  1548. end;
  1549. 1: begin (* load value *) t := t+1;
  1550. if t > stacksize then ps := stkchk
  1551. else s[t] := s[display[ir.x] + ir.y]
  1552. end;
  1553. 2: begin (* load indirect *) t := t+1;
  1554. if t > stacksize then ps := stkchk
  1555. else s[t] := s[s[display[ir.x] + ir.y].i]
  1556. end;
  1557. 3: begin (* update display *)
  1558. h1 := ir.y; h2 := ir.x; h3 := b;
  1559. repeat display[h1] := h3; h1 := h1-1; h3 := s[h3+2].i
  1560. until h1 = h2
  1561. end;
  1562. 8: case ir.y of
  1563. 0: s[t].i := abs(s[t].i);
  1564. 1: s[t].r := abs(s[t].r);
  1565. 2: s[t].i := sqr(s[t].i);
  1566. 3: s[t].r := sqr(s[t].r);
  1567. 4: s[t].b := odd(s[t].i);
  1568. 5: begin s[t].c := chr(s[t].i); { [sam] commented section restored }
  1569. if (s[t].i < 0) or (s[t].i > inxmax {[sam]}) then ps := inxchk
  1570. end;
  1571. 6: s[t].i := ord(s[t].c); { [sam] commented section restored }
  1572. 7: s[t].c := succ(s[t].c);
  1573. 8: s[t].c := pred(s[t].c);
  1574. 9: s[t].i := round(s[t].r);
  1575. 10: s[t].i := trunc(s[t].r);
  1576. 11: s[t].r := sin(s[t].r);
  1577. 12: s[t].r := cos(s[t].r);
  1578. 13: s[t].r := exp(s[t].r);
  1579. 14: s[t].r := ln(s[t].r);
  1580. 15: s[t].r := sqrt(s[t].r);
  1581. 16: s[t].r := arctan(s[t].r);
  1582. 17: begin t := t+1;
  1583. if t > stacksize then ps := stkchk
  1584. else s[t].b := eof(input)
  1585. end;
  1586. 18: begin t := t+1;
  1587. if t > stacksize then ps := stkchk
  1588. else s[t].b := eoln(input)
  1589. end;
  1590. end;
  1591. 9: s[t].i := s[t].i + ir.y; (* offset *)
  1592. 10: pc := ir.y; (* jump *)
  1593. 11: begin (* conditional jump *)
  1594. if not s[t].b then pc := ir.y; t := t-1
  1595. end;
  1596. 12: begin (* switch *) h1 := s[t].i; t := t-1;
  1597. h2 := ir.y; h3 := 0;
  1598. repeat if code[h2].f <> 13 then
  1599. begin h3 := 1; ps := caschk
  1600. end else
  1601. if code[h2].y = h1 then
  1602. begin h3 := 1; pc := code[h2+1].y
  1603. end else
  1604. h2 := h2 + 2
  1605. until h3 <> 0
  1606. end;
  1607. 14: begin (* forlup *) h1 := s[t-1].i;
  1608. if h1 <= s[t].i then s[s[t-2].i].i := h1 else
  1609. begin t := t-3; pc := ir.y
  1610. end
  1611. end;
  1612. 15: begin (* for2up *) h2 := s[t-2].i; h1 := s[h2].i + 1;
  1613. if h1 <= s[t].i then
  1614. begin s[h2].i := h1; pc := ir.y end
  1615. else t := t-3;
  1616. end;
  1617. 16: begin (* for1down *) h1 := s[t-1].i;
  1618. if h1 >= s[t].i then s[s[t-2].i].i := h1 else
  1619. begin pc := ir.y; t := t-3
  1620. end
  1621. end;
  1622. 17: begin (* for2down *) h2 := s[t-2].i; h1 := s[h2].i - 1;
  1623. if h1 >= s[t].i then
  1624. begin s[h2].i := h1; pc := ir.y end
  1625. else t := t-3;
  1626. end;
  1627. 18: begin (* mark stack *) h1 := btab[tab[ir.y].ref].vsize;
  1628. if t+h1 > stacksize then ps := stkchk else
  1629. begin t := t+5; s[t-1].i := h1-1; s[t].i := ir.y
  1630. end
  1631. end;
  1632. 19: begin (* call *) h1 := t - ir.y; (* h1 points top base *)
  1633. h2 := s[h1+4].i;
  1634. h3 := tab[h2].lev; display[h3+1] := h1;
  1635. h4 := s[h1+3].i + h1;
  1636. s[h1+1].i := pc; s[h1+2].i := display[h3]; s[h1+3].i := b;
  1637. for h3 := t+1 to h4 do s[h3].i := 0;
  1638. b := h1; t := h4; pc := tab[h2].adr
  1639. end;
  1640. 20: begin (* index *) h1 := ir.y; (* h1 points to atab *)
  1641. h2 := atab[h1].low; h3 := s[t].i;
  1642. if h3 < h2 then ps := inxchk else
  1643. if h3 > atab[h1].high then ps := inxchk else
  1644. begin t := t-1; s[t].i := s[t].i + (h3-h2)
  1645. end
  1646. end;
  1647. 21: begin (* index *) h1 := ir.y; (* h1 points to atab *)
  1648. h2 := atab[h1].low; h3 := s[t].i;
  1649. if h3 < h2 then ps := inxchk else
  1650. if h3 > atab[h1].high then ps := inxchk else
  1651. begin t := t-1; s[t].i := s[t].i + (h3-h2)*atab[h1].elsize
  1652. end
  1653. end;
  1654. 22: begin (* load block *) h1 := s[t].i; t := t-1;
  1655. h2 := ir.y + t; if h2 > stacksize then ps := stkchk else
  1656. while t < h2 do
  1657. begin t := t+1; s[t] := s[h1]; h1 := h1+1
  1658. end
  1659. end;
  1660. 23: begin (* copy block *) h1 := s[t-1].i;
  1661. h2 := s[t].i; h3 := h1 + ir.y;
  1662. while h1 < h3 do
  1663. begin s[h1] := s[h2]; h1 := h1+1; h2 := h2+1
  1664. end;
  1665. t := t-2
  1666. end;
  1667. 24: begin (* literal *) t := t+1;
  1668. if t > stacksize then ps := stkchk else s[t].i := ir.y
  1669. end;
  1670. 25: begin (* load real *) t := t+1;
  1671. if t > stacksize then ps := stkchk else s[t].r := rconst[ir.y]
  1672. end;
  1673. 26: begin (* float *) h1 := t - ir.y; s[h1].r := s[h1].i
  1674. end;
  1675. 27: begin (* read *)
  1676. if eof(input) then ps := redchk else
  1677. case ir.y of
  1678. 1: read(s[s[t].i].i);
  1679. 2: read(s[s[t].i].r);
  1680. 4: read(s[s[t].i].c)
  1681. end;
  1682. t := t-1
  1683. end;
  1684. 28: begin (* write string *)
  1685. h1 := s[t].i; h2 := ir.y; t := t-1;
  1686. chrcnt := chrcnt+h1; if chrcnt > lineleng then ps := lngchk;
  1687. repeat write(stab[h2]); h1 := h1-1; h2 := h2+1
  1688. until h1 = 0
  1689. end;
  1690. 29: begin (* write1 *)
  1691. chrcnt := chrcnt + fld[ir.y];
  1692. if chrcnt > lineleng then ps := lngchk else
  1693. case ir.y of
  1694. 1: write(s[t].i: fld[1]);
  1695. 2: write(s[t].r: fld[2]);
  1696. 3: write(s[t].b: fld[3]);
  1697. 4: write(s[t].c);
  1698. end;
  1699. t := t-1
  1700. end;
  1701. 30: begin (* write2 *)
  1702. chrcnt := chrcnt + s[t].i;
  1703. if chrcnt > lineleng then ps := lngchk else
  1704. case ir.y of
  1705. 1: write(s[t-1].i: s[t].i);
  1706. 2: write(s[t-1].r: s[t].i);
  1707. 3: write(s[t-1].b: s[t].i);
  1708. 4: write(s[t-1].c: s[t].i);
  1709. end;
  1710. t := t-2
  1711. end;
  1712. 31: ps := fin;
  1713. 32: begin (* exit procedure *)
  1714. t := b-1; pc := s[b+1].i; b := s[b+3].i
  1715. end;
  1716. 33: begin (* exit function *)
  1717. t := b; pc := s[b+1].i; b := s[b+3].i
  1718. end;
  1719. 34: s[t] := s[s[t].i];
  1720. 35: s[t].b := not s[t].b;
  1721. { Changed the negate instruction to work according to the type of the
  1722.   operand. See the header comments. [sam] }
  1723. 36: begin (* negate *)
  1724. case ir.y of
  1725. 1: s[t].i := - s[t].i;
  1726. 2: s[t].r := -s[t].r;
  1727. end
  1728. end;
  1729. 37: begin chrcnt := chrcnt + s[t-1].i;
  1730. if chrcnt > lineleng then ps := lngchk else
  1731. write(s[t-2].r: s[t-1].i: s[t].i);
  1732. t := t-3
  1733. end;
  1734. 38: begin (* store *) s[s[t-1].i] := s[t]; t := t-2;
  1735. end;
  1736. 39: begin t := t-1; s[t].b := s[t].r = s[t+1].r
  1737. end;
  1738. 40: begin t := t-1; s[t].b := s[t].r <> s[t+1].r
  1739. end;
  1740. 41: begin t := t-1; s[t].b := s[t].r < s[t+1].r
  1741. end;
  1742. 42: begin t := t-1; s[t].b := s[t].r <= s[t+1].r
  1743. end;
  1744. 43: begin t := t-1; s[t].b := s[t].r > s[t+1].r
  1745. end;
  1746. 44: begin t := t-1; s[t].b := s[t].r >= s[t+1].r
  1747. end;
  1748. 45: begin t := t-1; s[t].b := s[t].i = s[t+1].i
  1749. end;
  1750. 46: begin t := t-1; s[t].b := s[t].i <> s[t+1].i
  1751. end;
  1752. 47: begin t := t-1; s[t].b := s[t].i < s[t+1].i
  1753. end;
  1754. 48: begin t := t-1; s[t].b := s[t].i <= s[t+1].i
  1755. end;
  1756. 49: begin t := t-1; s[t].b := s[t].i > s[t+1].i
  1757. end;
  1758. 50: begin t := t-1; s[t].b := s[t].i >= s[t+1].i
  1759. end;
  1760. 51: begin t := t-1; s[t].b := s[t].b or s[t+1].b
  1761. end;
  1762. 52: begin t := t-1; s[t].i := s[t].i + s[t+1].i
  1763. end;
  1764. 53: begin t := t-1; s[t].i := s[t].i - s[t+1].i
  1765. end;
  1766. 54: begin t := t-1; s[t].r := s[t].r + s[t+1].r;
  1767. end;
  1768. 55: begin t := t-1; s[t].r := s[t].r - s[t+1].r;
  1769. end;
  1770. 56:
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
Free Pascal Compiler version 2.6.4+dfsg-4 [2014/10/14] for i386
Copyright (c) 1993-2014 by Florian Klaempfl and others
Target OS: Linux for i386
Compiling prog.pas
prog.pas(209,8) Fatal: Syntax error, "BEGIN" expected but "OBJECT" found
Fatal: Compilation aborted
Error: /usr/bin/ppc386 returned an error exitcode (normal if you did not specify a source file to be compiled)
stdout
Standard output is empty