CRX.mod 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. IMPLEMENTATION MODULE CRX;
  2. (* CRX Parser Generation
  3. === =================
  4. Uses the top-down graph and the computed sets of terminal start symbols
  5. from CRT to generate recursive descent parsing procedures.
  6. Errors are reported by error numbers. The corresponding error messages
  7. are written to <grammar name>.ERR.
  8. ---------------------------------------------------------------------*)
  9. IMPORT CRS, CRT, CRA, FileIO, Sets;
  10. CONST
  11. symSetSize = 100; (* max.number of symbol sets of the generated parser *)
  12. maxTerm = 5; (* sets of size < maxTerm are enumerated *)
  13. maxAlter = 5; (* more than maxAlter alternatives are handled with
  14. a case statement *)
  15. (* kinds of generated error messages *)
  16. tErr = 0; (* unmatched terminal symbol *)
  17. altErr = 1; (* unmatched alternatives *)
  18. syncErr = 2; (* error reported at synchronization point *)
  19. TYPE
  20. INT32 = FileIO.INT32;
  21. VAR
  22. symSet: ARRAY [0 .. symSetSize] OF CRT.Set; (* symbol sets in the
  23. generated parser *)
  24. maxSS: INTEGER; (* number of symbol sets *)
  25. errorNr: INTEGER; (* number of last generated error message*)
  26. curSy: INTEGER; (* symbol whose production is currently generated *)
  27. err: FileIO.File; (* output: error message texts *)
  28. fram: FileIO.File; (* input: parser frame parser.frm *)
  29. syn: FileIO.File; (* output: generated parser *)
  30. NewLine: BOOLEAN;
  31. IndDisp: INTEGER;
  32. (*#check(overflow=>off)*)
  33. (* Put Write ch
  34. ----------------------------------------------------------------------*)
  35. PROCEDURE Put (ch: CHAR);
  36. BEGIN
  37. FileIO.Write(syn, ch)
  38. END Put;
  39. (* PutLn Write line mark
  40. ----------------------------------------------------------------------*)
  41. PROCEDURE PutLn;
  42. BEGIN
  43. FileIO.WriteLn(syn)
  44. END PutLn;
  45. (* PutB Write n blanks
  46. ----------------------------------------------------------------------*)
  47. PROCEDURE PutB (n: INTEGER);
  48. BEGIN
  49. IF n > 0 THEN FileIO.WriteText(syn, "", n) END;
  50. END PutB;
  51. (* Indent Indent n characters
  52. ----------------------------------------------------------------------*)
  53. PROCEDURE Indent (n: INTEGER);
  54. BEGIN
  55. IF NewLine THEN PutB(n) ELSE NewLine := TRUE END;
  56. END Indent;
  57. (* IndentProc IndentProc n characters with additional IndDisp
  58. ----------------------------------------------------------------------*)
  59. PROCEDURE IndentProc (n: INTEGER);
  60. BEGIN
  61. Indent(n + IndDisp);
  62. END IndentProc;
  63. (* PutS Shortcut for WriteString(syn, ..)
  64. ----------------------------------------------------------------------*)
  65. PROCEDURE PutS (s: ARRAY OF CHAR);
  66. VAR
  67. i: CARDINAL;
  68. BEGIN
  69. i := 0;
  70. WHILE (i <= HIGH(s)) & (s[i] # 0C) DO
  71. IF s[i] = "$"
  72. THEN FileIO.WriteLn(syn)
  73. ELSE FileIO.Write(syn, s[i])
  74. END;
  75. INC(i)
  76. END
  77. END PutS;
  78. (* PutI Shortcut for WriteInt(syn, i, 1)
  79. ----------------------------------------------------------------------*)
  80. PROCEDURE PutI (i: INTEGER);
  81. BEGIN
  82. FileIO.WriteInt(syn, i, 1)
  83. END PutI;
  84. (* PutI2 Shortcut for WriteInt(syn, i, 2)
  85. ----------------------------------------------------------------------*)
  86. PROCEDURE PutI2 (i: INTEGER);
  87. BEGIN
  88. FileIO.WriteInt(syn, i, 2)
  89. END PutI2;
  90. (* PutSI Writes i or named constant of symbol i
  91. ----------------------------------------------------------------------*)
  92. PROCEDURE PutSI (i: INTEGER);
  93. VAR
  94. sn: CRT.SymbolNode;
  95. BEGIN
  96. CRT.GetSym(i, sn);
  97. IF FileIO.SLENGTH(sn.constant) > 0 THEN
  98. PutS(sn.constant);
  99. ELSE
  100. PutI(i);
  101. END;
  102. END PutSI;
  103. (* PutSet Enumerate bitset
  104. ----------------------------------------------------------------------*)
  105. PROCEDURE PutSet (s: BITSET; offset: CARDINAL);
  106. CONST
  107. MaxLine = 76;
  108. VAR
  109. first: BOOLEAN;
  110. i, l, len: CARDINAL;
  111. sn: CRT.SymbolNode;
  112. BEGIN
  113. i := 0; first := TRUE; len := 20;
  114. WHILE (i < Sets.size) & (offset + i <= ORD(CRT.maxT)) DO
  115. IF i IN s THEN
  116. IF first THEN first := FALSE ELSE PutS(", "); INC(len, 2) END;
  117. CRT.GetSym(offset + i, sn); l := FileIO.SLENGTH(sn.constant);
  118. IF l > 0 THEN
  119. IF len + l > MaxLine THEN
  120. PutS('$ ');
  121. len := 20;
  122. END;
  123. PutS(sn.constant); INC(len, l);
  124. IF offset > 0 THEN Put("-"); PutI(offset); INC(len, 3) END;
  125. ELSE
  126. IF len + l > MaxLine THEN
  127. PutS('$ ');
  128. len := 20;
  129. END;
  130. PutI(i); INC(len, i DIV 10 + 1);
  131. END;
  132. END;
  133. INC(i)
  134. END
  135. END PutSet;
  136. (* PutSet1 Enumerate long set
  137. ----------------------------------------------------------------------*)
  138. PROCEDURE PutSet1 (s: CRT.Set);
  139. VAR
  140. i: INTEGER;
  141. first: BOOLEAN;
  142. BEGIN
  143. i := 0; first := TRUE;
  144. WHILE i <= CRT.maxT DO
  145. IF Sets.In(s, i) THEN
  146. IF first THEN first := FALSE ELSE PutS(", ") END;
  147. PutSI(i)
  148. END;
  149. INC(i)
  150. END
  151. END PutSet1;
  152. (* Alternatives Count alternatives of gp
  153. ----------------------------------------------------------------------*)
  154. PROCEDURE Alternatives (gp: INTEGER): INTEGER;
  155. VAR
  156. gn: CRT.GraphNode;
  157. n: INTEGER;
  158. BEGIN
  159. n := 0;
  160. WHILE gp > 0 DO
  161. CRT.GetNode(gp, gn); gp := gn.p2; INC(n);
  162. END;
  163. RETURN n;
  164. END Alternatives;
  165. (* CopyFramePart Copy from file <fram> to file <syn> until <stopStr>
  166. ----------------------------------------------------------------------*)
  167. PROCEDURE CopyFramePart (stopStr: ARRAY OF CHAR; VAR leftMarg: CARDINAL);
  168. BEGIN
  169. CRA.CopyFramePart(stopStr, leftMarg, fram, syn);
  170. END CopyFramePart;
  171. TYPE
  172. IndentProcType = PROCEDURE (INTEGER);
  173. (* CopySourcePart Copy sequence <pos> from input file to file <syn>
  174. ----------------------------------------------------------------------*)
  175. PROCEDURE CopySourcePart (pos: CRT.Position; indent: INTEGER;
  176. indentProc: IndentProcType);
  177. VAR
  178. lastCh, ch: CHAR;
  179. extra, col, i: INTEGER;
  180. bp: INT32;
  181. nChars: CARDINAL;
  182. BEGIN
  183. IF pos.beg >= FileIO.Long0 THEN
  184. bp := pos.beg; nChars := pos.len;
  185. col := pos.col - 1; ch := " "; extra := 0;
  186. WHILE (nChars > 0) & ((ch = " ") OR (ch = CHR(9))) DO
  187. (* skip leading white space *)
  188. ch := CRS.CharAt(bp); INC(bp); DEC(nChars); INC(col);
  189. END;
  190. indentProc(indent);
  191. LOOP
  192. WHILE (ch = FileIO.CR) OR (ch = FileIO.LF) DO
  193. (* Write blank lines with the correct number of leading blanks *)
  194. FileIO.WriteLn(syn);
  195. lastCh := ch;
  196. IF nChars > 0
  197. THEN ch := CRS.CharAt(bp); INC(bp); DEC(nChars);
  198. ELSE EXIT
  199. END;
  200. IF (ch = FileIO.LF) & (lastCh = FileIO.CR) THEN
  201. extra := 1 (* must be MS-DOS format *);
  202. IF nChars > 0
  203. THEN ch := CRS.CharAt(bp); INC(bp); DEC(nChars);
  204. ELSE EXIT
  205. END
  206. END;
  207. IF (ch # FileIO.CR) & (ch # FileIO.LF) THEN
  208. (* we have something on this line *)
  209. indentProc(indent);
  210. i := col - 1 - extra;
  211. WHILE ((ch = " ") OR (ch = CHR(9))) & (i > 0) DO
  212. (* skip at most "col-1" white space chars at start of line *)
  213. IF nChars > 0
  214. THEN ch := CRS.CharAt(bp); INC(bp); DEC(nChars);
  215. ELSE EXIT
  216. END;
  217. DEC(i);
  218. END;
  219. END;
  220. END;
  221. (* Handle extra blanks *)
  222. i := 0;
  223. WHILE ch = " " DO
  224. IF nChars > 0
  225. THEN ch := CRS.CharAt(bp); INC(bp); DEC(nChars);
  226. ELSE EXIT
  227. END;
  228. INC(i);
  229. END;
  230. IF (ch # FileIO.CR) & (ch # FileIO.LF) & (ch # FileIO.EOF) THEN
  231. IF i > 0 THEN PutB(i) END;
  232. FileIO.Write(syn, ch);
  233. IF nChars > 0
  234. THEN ch := CRS.CharAt(bp); INC(bp); DEC(nChars);
  235. ELSE EXIT
  236. END;
  237. END;
  238. END;
  239. END;
  240. END CopySourcePart;
  241. (* GenErrorMsg Generate an error message and return its number
  242. ----------------------------------------------------------------------*)
  243. PROCEDURE GenErrorMsg (errTyp, errSym: INTEGER; VAR errNr: INTEGER);
  244. VAR
  245. i: INTEGER;
  246. name: CRT.Name;
  247. sn: CRT.SymbolNode;
  248. BEGIN
  249. INC(errorNr); errNr := errorNr;
  250. CRT.GetSym(errSym, sn); name := sn.name;
  251. i := 0;
  252. WHILE name[i] # 0C DO
  253. IF name[i] = '"' THEN name[i] := "'" END;
  254. INC(i)
  255. END;
  256. IF errNr = 0
  257. THEN FileIO.WriteString(err, " ");
  258. ELSE FileIO.WriteString(err, "|");
  259. END;
  260. FileIO.WriteInt(err, errNr, 3); FileIO.WriteString(err, ': Msg("');
  261. CASE errTyp OF
  262. tErr : FileIO.WriteString(err, name);
  263. FileIO.WriteString(err, " expected")
  264. | altErr : FileIO.WriteString(err, "invalid ");
  265. FileIO.WriteString(err, name)
  266. | syncErr: FileIO.WriteString(err, "this symbol not expected in ");
  267. FileIO.WriteString(err, name)
  268. END;
  269. FileIO.WriteString(err, '")');
  270. FileIO.WriteLn(err);
  271. END GenErrorMsg;
  272. (* NewCondSet Generate a new condition set, if set not yet exists
  273. ----------------------------------------------------------------------*)
  274. PROCEDURE NewCondSet (set: CRT.Set): INTEGER;
  275. VAR
  276. i: INTEGER;
  277. BEGIN
  278. i := 1; (*skip symSet[0]*)
  279. WHILE i <= maxSS DO
  280. IF Sets.Equal(set, symSet[i]) THEN RETURN i END;
  281. INC(i)
  282. END;
  283. INC(maxSS);
  284. IF maxSS > symSetSize THEN CRT.Restriction(5, symSetSize) END;
  285. symSet[maxSS] := set;
  286. RETURN maxSS
  287. END NewCondSet;
  288. (* GenCond Generate code to check if sym is in set
  289. ----------------------------------------------------------------------*)
  290. PROCEDURE GenCond (set: CRT.Set; indent: INTEGER);
  291. VAR
  292. i, n: INTEGER;
  293. PROCEDURE Small (s: CRT.Set): BOOLEAN;
  294. BEGIN
  295. i := Sets.size;
  296. WHILE i <= CRT.maxT DO
  297. IF Sets.In(s, i) THEN RETURN FALSE END;
  298. INC(i)
  299. END;
  300. RETURN TRUE
  301. END Small;
  302. BEGIN
  303. n := Sets.Elements(set, i);
  304. IF n = 0 THEN PutS(" FALSE") (*this branch should never be taken*)
  305. ELSIF n <= maxTerm THEN
  306. i := 0;
  307. WHILE i <= CRT.maxT DO
  308. IF Sets.In(set, i) THEN
  309. PutS(" (sym = "); PutSI(i); Put(")"); DEC(n);
  310. IF n > 0 THEN
  311. PutS(" OR");
  312. IF CRT.ddt["N"] THEN PutLn; IndentProc(indent) END
  313. END
  314. END;
  315. INC(i)
  316. END
  317. ELSIF Small(set) THEN
  318. PutS(" (sym < "); PutI2(Sets.size);
  319. PutS(") (* prevent range error *) AND$");
  320. IndentProc(indent); PutS(" (sym IN BITSET{");
  321. PutSet(set[0], 0); PutS("}) ")
  322. ELSE PutS(" In(symSet["); PutI(NewCondSet(set)); PutS("], sym)")
  323. END;
  324. END GenCond;
  325. (* GenCode Generate code for graph gp in production curSy
  326. ----------------------------------------------------------------------*)
  327. PROCEDURE GenCode (gp, indent: INTEGER; checked: CRT.Set);
  328. VAR
  329. gn, gn2: CRT.GraphNode;
  330. sn: CRT.SymbolNode;
  331. s1, s2: CRT.Set;
  332. gp2, errNr, alts, indent1, addInd, errSemNod: INTEGER;
  333. FirstCase, equal, OldNewLine: BOOLEAN;
  334. altStart: INT32;
  335. BEGIN
  336. WHILE gp > 0 DO
  337. CRT.GetNode(gp, gn);
  338. CASE gn.typ OF
  339. CRT.nt:
  340. IndentProc(indent);
  341. CRT.GetSym(gn.p1, sn); PutS(sn.name);
  342. IF gn.pos.beg >= FileIO.Long0 THEN
  343. Put("("); NewLine := FALSE;
  344. indent1 := indent + VAL(INTEGER, FileIO.SLENGTH(sn.name)) + 1;
  345. CopySourcePart(gn.pos, indent1, IndentProc);
  346. (* was CopySourcePart(gn.pos, 0, IndentProc); ++++ *)
  347. Put(")")
  348. END;
  349. PutS(";$")
  350. | CRT.t:
  351. CRT.GetSym(gn.p1, sn); IndentProc(indent);
  352. IF Sets.In(checked, gn.p1) THEN
  353. PutS("Get;$");
  354. ELSE
  355. PutS("Expect("); PutSI(gn.p1); PutS(");$");
  356. END
  357. | CRT.wt:
  358. CRT.CompExpected(ABS(gn.next), curSy, s1);
  359. CRT.GetSet(0, s2); Sets.Unite(s1, s2);
  360. CRT.GetSym(gn.p1, sn); IndentProc(indent);
  361. PutS("ExpectWeak("); PutSI(gn.p1); PutS(", ");
  362. PutI(NewCondSet(s1)); PutS(");$")
  363. | CRT.any:
  364. IndentProc(indent); PutS("Get;$")
  365. | CRT.eps: (* nothing *)
  366. | CRT.sem:
  367. CopySourcePart(gn.pos, indent, IndentProc); PutS(";$");
  368. | CRT.sync:
  369. CRT.GetSet(gn.p1, s1);
  370. GenErrorMsg(syncErr, curSy, errNr);
  371. IndentProc(indent);
  372. PutS("WHILE ~ ("); GenCond(s1, indent + 9); PutS(") DO SynError(");
  373. PutI(errNr); PutS("); Get END;$")
  374. | CRT.alt:
  375. CRT.CompFirstSet(gp, s1); equal := Sets.Equal(s1, checked);
  376. alts := Alternatives(gp);
  377. OldNewLine := NewLine; altStart := FileIO.GetPos(syn);
  378. IF alts > maxAlter THEN
  379. IndentProc(indent); PutS("CASE sym OF$")
  380. END;
  381. gp2 := gp;
  382. IF alts > maxAlter THEN addInd := 4 ELSE addInd := 2 END;
  383. errSemNod := -1; FirstCase := TRUE;
  384. WHILE gp2 # 0 DO
  385. CRT.GetNode(gp2, gn2);
  386. CRT.CompExpected(gn2.p1, curSy, s1);
  387. IndentProc(indent);
  388. IF alts > maxAlter THEN
  389. IF FirstCase
  390. THEN FirstCase := FALSE; PutS(" ")
  391. ELSE PutS("| ") END;
  392. PutSet1(s1); PutS(" :$");
  393. ELSIF gp2 = gp
  394. THEN PutS("IF"); GenCond(s1, indent + 2); PutS(" THEN$")
  395. ELSIF (gn2.p2 = 0) & equal THEN PutS("ELSE$")
  396. ELSE PutS("ELSIF"); GenCond(s1, indent + 5); PutS(" THEN$")
  397. END;
  398. Sets.Unite(s1, checked);
  399. GenCode(gn2.p1, indent + addInd, s1); NewLine := TRUE;
  400. gp2 := gn2.p2;
  401. END;
  402. IF ~ equal THEN
  403. GenErrorMsg(altErr, curSy, errNr);
  404. IndentProc(indent);
  405. PutS("ELSE SynError("); PutI(errNr); PutS(");$");
  406. END;
  407. IndentProc(indent); PutS("END;$");
  408. | CRT.iter:
  409. CRT.GetNode(gn.p1, gn2);
  410. IndentProc(indent); PutS("WHILE");
  411. IF gn2.typ = CRT.wt THEN
  412. CRT.CompExpected(ABS(gn2.next), curSy, s1);
  413. CRT.CompExpected(ABS(gn.next), curSy, s2);
  414. CRT.GetSym(gn2.p1, sn);
  415. PutS(" WeakSeparator("); PutSI(gn2.p1); PutS(", ");
  416. PutI(NewCondSet(s1));
  417. PutS(", "); PutI(NewCondSet(s2)); Put(")");
  418. Sets.Clear(s1); (*for inner structure*)
  419. IF gn2.next > 0 THEN gp2 := gn2.next ELSE gp2 := 0 END
  420. ELSE
  421. gp2 := gn.p1;
  422. CRT.CompFirstSet(gp2, s1); GenCond(s1, indent + 5)
  423. END;
  424. PutS(" DO$");
  425. GenCode(gp2, indent + 2, s1);
  426. IndentProc(indent); PutS("END;$");
  427. | CRT.opt:
  428. CRT.CompFirstSet(gn.p1, s1);
  429. IF Sets.Equal(checked, s1) THEN
  430. GenCode(gn.p1, indent, checked);
  431. ELSE
  432. IndentProc(indent); PutS("IF");
  433. GenCond(s1, indent + 2); PutS(" THEN$");
  434. GenCode(gn.p1, indent + 2, s1);
  435. IndentProc(indent); PutS("END;$");
  436. END
  437. END; (*CASE*)
  438. IF (gn.typ # CRT.eps) & (gn.typ # CRT.sem) & (gn.typ # CRT.sync) THEN
  439. Sets.Clear(checked)
  440. END;
  441. gp := gn.next;
  442. END; (* WHILE gp > 0 *)
  443. END GenCode;
  444. (* GenPragmaCode Generate code for pragmas
  445. ----------------------------------------------------------------------*)
  446. PROCEDURE GenPragmaCode (leftMarg: CARDINAL; gramName : ARRAY OF CHAR);
  447. VAR
  448. i: INTEGER;
  449. sn: CRT.SymbolNode;
  450. FirstCase: BOOLEAN;
  451. BEGIN
  452. i := CRT.maxT + 1;
  453. IF i > CRT.maxP THEN RETURN END;
  454. FirstCase := TRUE;
  455. PutS("CASE sym OF$"); PutB(leftMarg);
  456. LOOP
  457. CRT.GetSym(i, sn);
  458. IF FirstCase THEN FirstCase := FALSE; PutS(" ") ELSE PutS("| ") END;
  459. PutSI(i); PutS(": "); NewLine := FALSE;
  460. CopySourcePart(sn.semPos, leftMarg + 6, Indent);
  461. IF i = CRT.maxP THEN EXIT END;
  462. INC(i); PutLn; PutB(leftMarg);
  463. END; (* LOOP *)
  464. PutLn; PutB(leftMarg); PutS("END;$");
  465. PutB(leftMarg); PutS(gramName); PutS("S.nextPos := ");
  466. PutS(gramName); PutS("S.pos;$");
  467. PutB(leftMarg); PutS(gramName); PutS("S.nextCol := ");
  468. PutS(gramName); PutS("S.col;$");
  469. PutB(leftMarg); PutS(gramName); PutS("S.nextLine := ");
  470. PutS(gramName); PutS("S.line;$");
  471. PutB(leftMarg); PutS(gramName); PutS("S.nextLen := ");
  472. PutS(gramName); PutS("S.len;");
  473. END GenPragmaCode;
  474. (* GenProcedureHeading Generate procedure heading
  475. ----------------------------------------------------------------------*)
  476. PROCEDURE GenProcedureHeading (sn: CRT.SymbolNode);
  477. BEGIN
  478. PutS("PROCEDURE "); PutS(sn.name);
  479. IF sn.attrPos.beg >= FileIO.Long0 THEN
  480. (* was PutS(" ("); CopySourcePart(sn.attrPos, 0, PutB); Put(")") ++ *)
  481. PutS(" ("); NewLine := FALSE;
  482. CopySourcePart(sn.attrPos, 13 + FileIO.SLENGTH(sn.name), Indent);
  483. Put(")")
  484. END;
  485. Put(";")
  486. END GenProcedureHeading;
  487. (* GenForwardRefs Generate forward references for one-pass compilers
  488. ----------------------------------------------------------------------*)
  489. PROCEDURE GenForwardRefs;
  490. VAR
  491. sp: INTEGER;
  492. sn: CRT.SymbolNode;
  493. BEGIN
  494. IF CRT.ddt["M"] THEN
  495. PutS("(* ----- FORWARD not needed in multipass compilers$$")
  496. END;
  497. sp := CRT.firstNt;
  498. WHILE sp <= CRT.lastNt DO (* for all nonterminals *)
  499. CRT.GetSym(sp, sn); GenProcedureHeading(sn); PutS(" FORWARD;$");
  500. INC(sp)
  501. END;
  502. FileIO.WriteLn(syn);
  503. IF CRT.ddt["M"] THEN
  504. PutS("----- *)$$")
  505. END;
  506. END GenForwardRefs;
  507. (* GenProductions Generate code for all productions
  508. ----------------------------------------------------------------------*)
  509. PROCEDURE GenProductions;
  510. VAR
  511. sn: CRT.SymbolNode;
  512. checked: CRT.Set;
  513. BEGIN
  514. curSy := CRT.firstNt; NewLine := TRUE; (* Bug fix PDT*)
  515. WHILE curSy <= CRT.lastNt DO (* for all nonterminals *)
  516. CRT.GetSym(curSy, sn); GenProcedureHeading(sn); FileIO.WriteLn(syn);
  517. IF sn.semPos.beg >= FileIO.Long0 THEN
  518. CopySourcePart(sn.semPos, 2, IndentProc); PutLn
  519. END;
  520. PutB(2); PutS("BEGIN$");
  521. (* may like to add PutS(" (* "); PutS(sn.name); PutS(" *)$"); *)
  522. Sets.Clear(checked);
  523. GenCode(sn.struct, 4, checked);
  524. PutB(2); PutS("END "); PutS(sn.name); PutS(";$$");
  525. INC(curSy);
  526. END;
  527. END GenProductions;
  528. (* GenSetInits Initialise all sets
  529. ----------------------------------------------------------------------*)
  530. PROCEDURE InitSets;
  531. VAR
  532. i, j: INTEGER;
  533. BEGIN
  534. CRT.GetSet(0, symSet[0]);
  535. NewLine := FALSE; i := 0;
  536. WHILE i <= maxSS DO
  537. IF i # 0 THEN PutLn END;
  538. j := 0;
  539. WHILE j <= CRT.maxT DIV Sets.size DO
  540. IF j # 0 THEN PutLn END;
  541. Indent(2); PutS("symSet["); PutI2(i); PutS(", ");PutI(j);
  542. PutS("] := BITSET{");
  543. PutSet(symSet[i, j], j * Sets.size); PutS("};");
  544. INC(j);
  545. END;
  546. INC(i)
  547. END
  548. END InitSets;
  549. (* GenCompiler Generate the target compiler
  550. ----------------------------------------------------------------------*)
  551. PROCEDURE GenCompiler;
  552. VAR
  553. Digits, len, pos, LeftMargin: CARDINAL;
  554. errNr, i: INTEGER;
  555. checked: CRT.Set;
  556. gn: CRT.GraphNode;
  557. sn: CRT.SymbolNode;
  558. gramName: ARRAY [0 .. 31] OF CHAR;
  559. fGramName, fn, ParserFrame: ARRAY [0 .. 63] OF CHAR;
  560. endPos, SS: INT32;
  561. BEGIN
  562. FileIO.Concat(CRS.directory, "parser.frm", ParserFrame);
  563. FileIO.Open(fram, ParserFrame, FALSE);
  564. IF ~ FileIO.Okay THEN
  565. FileIO.SearchFile(fram, "CRFRAMES", "parser.frm", FALSE);
  566. IF ~ FileIO.Okay THEN
  567. FileIO.WriteLn(FileIO.StdOut);
  568. FileIO.WriteString(FileIO.StdOut, "'parser.frm' not found.");
  569. FileIO.WriteString(FileIO.StdOut, "- Aborted.");
  570. FileIO.QuitExecution
  571. END
  572. END;
  573. LeftMargin := 0;
  574. CRT.GetNode(CRT.root, gn); CRT.GetSym(gn.p1, sn);
  575. FileIO.Extract(sn.name, 0, 7, gramName);
  576. FileIO.Concat(CRS.directory, gramName, fGramName);
  577. (*----- write *.ERR -----*)
  578. FileIO.Concat(fGramName, FileIO.ErrExt, fn);
  579. FileIO.Open(err, fn, TRUE);
  580. (* ++
  581. FileIO.WriteLn(FileIO.StdOut);
  582. FileIO.WriteString(FileIO.StdOut, " ");
  583. FileIO.WriteString(FileIO.StdOut, fn);
  584. ++ *)
  585. i := 0;
  586. WHILE i <= CRT.maxT DO GenErrorMsg(tErr, i, errNr); INC(i) END;
  587. IF (CRT.ddt["N"] OR CRT.symNames) AND ~ CRT.ddt["D"] THEN
  588. (*----- write *G.DEF -----*)
  589. FileIO.Concat(fGramName, "G", fn);
  590. FileIO.Concat(fn, FileIO.DefExt, fn);
  591. FileIO.Open(syn, fn, TRUE);
  592. (* ++
  593. FileIO.WriteLn(FileIO.StdOut);
  594. FileIO.WriteString(FileIO.StdOut, " ");
  595. FileIO.WriteString(FileIO.StdOut, fn);
  596. ++ *)
  597. PutS("DEFINITION MODULE "); PutS(gramName); PutS("G;$$");
  598. PutS("CONST");
  599. i := 0; pos := CRA.MaxSourceLineLength + 1;
  600. REPEAT
  601. CRT.GetSym(i, sn); len := FileIO.SLENGTH(sn.constant);
  602. IF len > 0 THEN
  603. errNr := i; Digits := 1;
  604. WHILE errNr >= 10 DO INC(Digits); errNr := errNr DIV 10 END;
  605. INC(len, 3 + Digits + 1);
  606. IF pos + len > CRA.MaxSourceLineLength THEN
  607. PutLn; pos := 0
  608. END;
  609. PutS(" ");
  610. PutS(sn.constant); PutS(" = "); PutI(i); Put(";");
  611. INC(pos, len + 2);
  612. END;
  613. INC(i);
  614. UNTIL i > CRT.maxP;
  615. PutS("$$END "); PutS(gramName); PutS("G.$");
  616. FileIO.Close(syn);
  617. (*----- write *G.MOD -----*)
  618. FileIO.Concat(fGramName, "G", fn);
  619. FileIO.Concat(fn, FileIO.ModExt, fn);
  620. FileIO.Open(syn, fn, TRUE);
  621. (* ++
  622. FileIO.WriteLn(FileIO.StdOut);
  623. FileIO.WriteString(FileIO.StdOut, " ");
  624. FileIO.WriteString(FileIO.StdOut, fn);
  625. ++ *)
  626. PutS("IMPLEMENTATION MODULE "); PutS(gramName); PutS("G;$");
  627. PutS("END "); PutS(gramName); PutS("G.$");
  628. FileIO.Close(syn);
  629. END; (* IF CRT.ddt["N"] OR CRT.symNames *)
  630. (*----- write *P.MOD -----*)
  631. FileIO.Concat(fGramName, "P", fn);
  632. FileIO.Concat(fn, FileIO.ModExt, fn);
  633. FileIO.Open(syn, fn, TRUE);
  634. (* ++
  635. FileIO.WriteLn(FileIO.StdOut);
  636. FileIO.WriteString(FileIO.StdOut, " ");
  637. FileIO.WriteString(FileIO.StdOut, fn);
  638. ++ *)
  639. CopyFramePart("-->modulename", LeftMargin); PutS(gramName); Put("P");
  640. IF CRT.ddt["N"] OR CRT.symNames THEN CRA.ImportSymConsts(PutS) END;
  641. CopyFramePart("-->scanner", LeftMargin);
  642. PutS(gramName); Put("S");
  643. CopyFramePart("-->declarations", LeftMargin);
  644. CopySourcePart(CRT.semDeclPos, 0, PutB);
  645. CopyFramePart("-->constants", LeftMargin);
  646. PutS("maxT = "); PutI(CRT.maxT); Put(";");
  647. IF CRT.maxP > CRT.maxT THEN
  648. PutLn; PutB(LeftMargin); PutS("maxP = ");
  649. PutI(CRT.maxP); Put(";");
  650. END;
  651. CopyFramePart("-->symSetSize", LeftMargin);
  652. SS := FileIO.GetPos(syn);
  653. FileIO.WriteInt(syn, 999, 3);
  654. CopyFramePart("-->error", LeftMargin);
  655. PutS(gramName); PutS("S.Error(errNo, ");
  656. PutS(gramName); PutS("S.line, ");
  657. PutS(gramName); PutS("S.col, ");
  658. PutS(gramName); PutS("S.pos);");
  659. CopyFramePart("-->error", LeftMargin);
  660. PutS(gramName); PutS("S.Error(errNo, ");
  661. PutS(gramName); PutS("S.nextLine, ");
  662. PutS(gramName); PutS("S.nextCol, ");
  663. PutS(gramName); PutS("S.nextPos);");
  664. CopyFramePart("-->scanner", LeftMargin);
  665. PutS(gramName); Put("S");
  666. CopyFramePart("-->pragmas", LeftMargin);
  667. GenPragmaCode(LeftMargin, gramName);
  668. FOR i := 1 TO 13 DO
  669. CopyFramePart("-->scanner", LeftMargin);
  670. PutS(gramName); Put("S");
  671. END;
  672. CopyFramePart("-->productions", LeftMargin);
  673. GenForwardRefs; GenProductions;
  674. CopyFramePart("-->parseRoot", LeftMargin);
  675. PutS(gramName); PutS("S.Reset; Get;$");
  676. Sets.Clear(checked); GenCode(CRT.root, LeftMargin, checked);
  677. CopyFramePart("-->initialization", LeftMargin);
  678. InitSets;
  679. CopyFramePart("-->modulename", LeftMargin);
  680. PutS(gramName); Put("P");
  681. CopyFramePart("-->definition", LeftMargin);
  682. endPos := FileIO.GetPos(syn); (* end position of the file *)
  683. FileIO.SetPos(syn, SS); (* fix up array declaration *)
  684. IF maxSS < 0 THEN maxSS := 0 END;
  685. FileIO.WriteInt(syn, maxSS, 3);
  686. FileIO.SetPos(syn, endPos); (* set file pointer to end of file *)
  687. FileIO.Close(syn);
  688. IF ~ CRT.ddt["D"] THEN
  689. (*----- write *P.DEF -----*)
  690. FileIO.Concat(fGramName, "P", fn);
  691. FileIO.Concat(fn, FileIO.DefExt, fn);
  692. FileIO.Open(syn, fn, TRUE);
  693. (* ++
  694. FileIO.WriteLn(FileIO.StdOut);
  695. FileIO.WriteString(FileIO.StdOut, " ");
  696. FileIO.WriteString(FileIO.StdOut, fn);
  697. ++ *)
  698. CopyFramePart("-->modulename", LeftMargin);
  699. PutS(gramName); Put("P");
  700. CopyFramePart("-->modulename", LeftMargin);
  701. PutS(gramName); PutS("P.$");
  702. FileIO.Close(syn);
  703. END;
  704. FileIO.Close(fram); FileIO.Close(err);
  705. END GenCompiler;
  706. (* WriteStatistics Write statistics about compilation to list file
  707. ----------------------------------------------------------------------*)
  708. PROCEDURE WriteStatistics;
  709. PROCEDURE WriteNumbers (used, available: INTEGER);
  710. BEGIN
  711. FileIO.WriteInt(CRS.lst, used + 1, 6);
  712. FileIO.WriteString(CRS.lst, " (limit ");
  713. FileIO.WriteInt(CRS.lst, available, 5);
  714. FileIO.Write(CRS.lst, ")"); FileIO.WriteLn(CRS.lst);
  715. END WriteNumbers;
  716. BEGIN
  717. FileIO.WriteString(CRS.lst, "Statistics:"); FileIO.WriteLn(CRS.lst);
  718. FileIO.WriteLn(CRS.lst);
  719. FileIO.WriteString(CRS.lst, " nr of terminals: ");
  720. WriteNumbers(CRT.maxT, CRT.maxTerminals);
  721. FileIO.WriteString(CRS.lst, " nr of non-terminals:");
  722. WriteNumbers(CRT.lastNt-CRT.firstNt, CRT.maxNt);
  723. FileIO.WriteString(CRS.lst, " nr of pragmas: ");
  724. WriteNumbers(CRT.maxSymbols-CRT.lastNt-2, CRT.maxSymbols-CRT.maxT-1);
  725. FileIO.WriteString(CRS.lst, " nr of symbolnodes: ");
  726. WriteNumbers(CRT.maxSymbols-CRT.firstNt+CRT.maxT, CRT.maxSymbols);
  727. FileIO.WriteString(CRS.lst, " nr of graphnodes: ");
  728. WriteNumbers(CRT.nNodes, CRT.maxNodes);
  729. FileIO.WriteString(CRS.lst, " nr of conditionsets:");
  730. WriteNumbers(maxSS, symSetSize);
  731. FileIO.WriteString(CRS.lst, " nr of charactersets:");
  732. WriteNumbers(CRT.maxC, CRT.maxClasses);
  733. FileIO.WriteLn(CRS.lst); FileIO.WriteLn(CRS.lst);
  734. END WriteStatistics;
  735. BEGIN (* CRX *)
  736. errorNr := -1; maxSS := 0; (*symSet[0] reserved for allSyncSyms*)
  737. NewLine := TRUE; IndDisp := 0;
  738. END CRX.