CRA.mod 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. IMPLEMENTATION MODULE CRA;
  2. (* CRA Automaton and Scanner Generation
  3. === ================================
  4. (1) ConvertToStates translates a top-down graph into a NFA.
  5. MatchDFA tries to match literal strings against the DFA
  6. (2) MakeDeterministic converts the NFA into a DFA
  7. (3) WriteScanner generates the scanner source file
  8. ----------------------------------------------------------------*)
  9. (* IMPORT ProgArgs; for gpm version *)
  10. IMPORT CRS, CRT, FileIO, Sets, Storage;
  11. IMPORT SYSTEM (* for TSIZE only *);
  12. CONST
  13. maxStates = 500;
  14. cr = 15C;
  15. TYPE
  16. Action = POINTER TO ActionNode;
  17. Target = POINTER TO TargetNode;
  18. State = RECORD (* state of finite automaton *)
  19. firstAction: Action; (* to first action of this state *)
  20. endOf: INTEGER; (* nr. of recognized token if state is final *)
  21. ctx: BOOLEAN; (* TRUE: state reached by contextTrans *)
  22. END;
  23. ActionNode = RECORD (* action of finite automaton *)
  24. typ: INTEGER; (* type of action symbol: char, class *)
  25. sym: INTEGER; (* action symbol *)
  26. tc: INTEGER; (* transition code: normTrans, contextTrans *)
  27. target: Target; (* states after transition with input symbol *)
  28. next: Action;
  29. END;
  30. TargetNode = RECORD (* state after transition with input symbol *)
  31. state: INTEGER; (* target state *)
  32. next: Target;
  33. END;
  34. Comment = POINTER TO CommentNode;
  35. CommentNode = RECORD (* info about a comment syntax *)
  36. start,stop: ARRAY [0 .. 1] OF CHAR;
  37. nested: BOOLEAN;
  38. next: Comment;
  39. END;
  40. Melted = POINTER TO MeltedNode;
  41. MeltedNode = RECORD (* info about melted states *)
  42. set: CRT.Set; (* set of old states *)
  43. state: INTEGER; (* new state *)
  44. next: Melted;
  45. END;
  46. VAR
  47. state: ARRAY [0 .. maxStates] OF State;
  48. lastSimState: INTEGER; (* last non melted state *)
  49. lastState: INTEGER; (* last allocated state *)
  50. rootState: INTEGER; (* start state of DFA *)
  51. firstMelted: Melted; (* list of melted states *)
  52. firstComment: Comment; (* list of comments *)
  53. scanner, (* generated scanner *)
  54. out: FileIO.File; (* current output file *)
  55. fram: FileIO.File; (* scanner frame *)
  56. dirtyDFA, (* DFA may become non-deterministic *)
  57. NewLine: BOOLEAN;
  58. PROCEDURE SemErr (nr: INTEGER);
  59. BEGIN
  60. CRS.Error(nr + 100, CRS.line, CRS.col, CRS.pos)
  61. END SemErr;
  62. PROCEDURE Put (ch: CHAR);
  63. BEGIN
  64. FileIO.Write(out, ch)
  65. END Put;
  66. PROCEDURE PutLn;
  67. BEGIN
  68. FileIO.WriteLn(out)
  69. END PutLn;
  70. PROCEDURE PutB (n: INTEGER);
  71. BEGIN
  72. FileIO.WriteText(out, "", n);
  73. END PutB;
  74. PROCEDURE Indent (n: INTEGER);
  75. BEGIN
  76. IF NewLine THEN PutB(n) ELSE NewLine := TRUE END;
  77. END Indent;
  78. PROCEDURE PutS (s: ARRAY OF CHAR);
  79. VAR
  80. i: CARDINAL;
  81. BEGIN
  82. i := 0;
  83. WHILE (i <= HIGH(s)) & (s[i] # 0C) DO
  84. IF s[i] = "$"
  85. THEN FileIO.WriteLn(out)
  86. ELSE FileIO.Write(out, s[i])
  87. END;
  88. INC(i)
  89. END
  90. END PutS;
  91. PROCEDURE PutI (i: INTEGER);
  92. BEGIN
  93. FileIO.WriteInt(out, i, 1)
  94. END PutI;
  95. PROCEDURE PutI2 (i, n: INTEGER);
  96. BEGIN
  97. FileIO.WriteInt(out, i, n)
  98. END PutI2;
  99. PROCEDURE PutC (ch: CHAR);
  100. BEGIN
  101. CASE ch OF
  102. 0C .. 37C, 177C .. 377C :
  103. PutS("CHR("); PutI(ORD(ch)); Put(")")
  104. | '"' :
  105. Put("'"); Put(ch); Put("'")
  106. ELSE Put('"'); Put(ch); Put('"')
  107. END
  108. END PutC;
  109. PROCEDURE PutSN (i: INTEGER);
  110. VAR
  111. sn: CRT.SymbolNode;
  112. BEGIN
  113. CRT.GetSym(i, sn);
  114. IF FileIO.SLENGTH(sn.constant) > 0 THEN
  115. PutS(sn.constant);
  116. ELSE
  117. PutI(i);
  118. END;
  119. END PutSN;
  120. PROCEDURE PutSE (i: INTEGER);
  121. BEGIN
  122. PutS("sym := "); PutSN(i); PutS("; ");
  123. END PutSE;
  124. PROCEDURE PutRange (s: CRT.Set; indent:CARDINAL);
  125. VAR
  126. lo, hi: ARRAY [0 .. 31] OF CHAR;
  127. top, i: INTEGER;
  128. s1: CRT.Set;
  129. BEGIN
  130. (*----- fill lo and hi *)
  131. top := -1; i := 0;
  132. WHILE i < 256 (*PDT*) DO
  133. IF Sets.In(s, i) THEN
  134. INC(top); lo[top] := CHR(i); INC(i);
  135. WHILE (i < 256 (*PDT*) ) & Sets.In(s, i) DO INC(i) END;
  136. hi[top] := CHR(i - 1)
  137. ELSE INC(i)
  138. END
  139. END;
  140. (*----- print ranges *)
  141. IF (top = 1) & (lo[0] = 0C) & (hi[1] = 377C (*PDT*))
  142. & (CHR(ORD(hi[0]) + 2) = lo[1]) THEN
  143. Sets.Fill(s1); Sets.Differ(s1, s);
  144. PutS("~ "); PutRange(s1, indent);
  145. ELSE
  146. PutS("(");
  147. i := 0;
  148. WHILE i <= top DO
  149. IF hi[i] = lo[i] THEN PutS("(ch = "); PutC(lo[i])
  150. ELSIF lo[i] = 0C THEN PutS("(ch <= "); PutC(hi[i])
  151. ELSIF hi[i] = 377C (*PDT*) THEN PutS("(ch >= "); PutC(lo[i])
  152. ELSE PutS("(ch >= "); PutC(lo[i]); PutS(") & (ch <= ");
  153. PutC(hi[i])
  154. END;
  155. Put(")");
  156. IF i < top THEN PutS(" OR$"); PutB(indent) END;
  157. INC(i)
  158. END;
  159. PutS(")");
  160. END
  161. END PutRange;
  162. PROCEDURE PutChCond (ch: CHAR);
  163. BEGIN
  164. PutS("(ch = "); PutC(ch); Put(")")
  165. END PutChCond;
  166. (* PrintSymbol Print a symbol for tracing
  167. -------------------------------------------------------------------------*)
  168. PROCEDURE PrintSymbol (typ, val, width: INTEGER);
  169. VAR
  170. name: CRT.Name;
  171. len: INTEGER;
  172. BEGIN
  173. IF typ = CRT.class THEN
  174. CRT.GetClassName(val, name); PutS(name);
  175. len := FileIO.SLENGTH(name)
  176. ELSIF (val >= VAL(INTEGER, ORD(" "))) & (val < 127) & (val # 34) THEN
  177. Put('"'); Put(CHR(val)); Put('"'); len := 3
  178. ELSE
  179. PutS("CHR("); PutI2(val, 2); Put(")"); len := 7
  180. END;
  181. WHILE len < width DO Put(" "); INC(len) END
  182. END PrintSymbol;
  183. (* PrintStates List the automaton for tracing
  184. -------------------------------------------------------------------------*)
  185. PROCEDURE PrintStates;
  186. VAR
  187. action: Action;
  188. first: BOOLEAN;
  189. s, i: INTEGER;
  190. targ: Target;
  191. set: CRT.Set;
  192. name: CRT.Name;
  193. BEGIN
  194. out := CRS.lst;
  195. PutS("$-------- states ---------$");
  196. s := rootState;
  197. WHILE s <= lastState DO
  198. action := state[s].firstAction; first := TRUE;
  199. IF state[s].endOf = CRT.noSym THEN PutS(" ")
  200. ELSE PutS("E("); PutI2(state[s].endOf, 2); Put(")")
  201. END;
  202. PutI2(s, 3); Put(":"); IF action = NIL THEN PutS(" $") END;
  203. WHILE action # NIL DO
  204. IF first
  205. THEN Put(" "); first := FALSE
  206. ELSE PutS(" ")
  207. END;
  208. PrintSymbol(action^.typ, action^.sym, 0); Put(" ");
  209. targ := action^.target;
  210. WHILE targ # NIL DO
  211. PutI(targ^.state); Put(" "); targ := targ^.next;
  212. END;
  213. IF action^.tc = CRT.contextTrans
  214. THEN PutS(" context$")
  215. ELSE PutS(" $")
  216. END;
  217. action := action^.next
  218. END;
  219. INC(s)
  220. END;
  221. PutS("$-------- character classes ---------$");
  222. i := 0;
  223. WHILE i <= CRT.maxC DO
  224. CRT.GetClass(i, set); CRT.GetClassName(i, name);
  225. FileIO.WriteText(out, name, 10);
  226. FileIO.WriteString(out, ": "); Sets.Print(out, set, 80, 13);
  227. FileIO.WriteLn(out);
  228. INC(i)
  229. END
  230. END PrintStates;
  231. (* AddAction Add a action to the action list of a state
  232. ------------------------------------------------------------------------*)
  233. PROCEDURE AddAction (act: Action; VAR head: Action);
  234. VAR
  235. a,lasta: Action;
  236. BEGIN
  237. a := head; lasta := NIL;
  238. LOOP
  239. IF (a = NIL) OR (act^.typ < a^.typ) THEN
  240. (*collecting classes at the front improves performance*)
  241. act^.next := a;
  242. IF lasta = NIL THEN head := act ELSE lasta^.next := act END;
  243. EXIT;
  244. END;
  245. lasta := a; a := a^.next;
  246. END;
  247. END AddAction;
  248. (* DetachAction Detach action a from list L
  249. ------------------------------------------------------------------------*)
  250. PROCEDURE DetachAction (a: Action; VAR L: Action);
  251. BEGIN
  252. IF L = a THEN L := a^.next
  253. ELSIF L # NIL THEN DetachAction(a, L^.next)
  254. END
  255. END DetachAction;
  256. PROCEDURE TheAction (state: State; ch: CHAR): Action;
  257. VAR
  258. a: Action;
  259. set: CRT.Set;
  260. BEGIN
  261. a := state.firstAction;
  262. WHILE a # NIL DO
  263. IF a^.typ = CRT.char THEN
  264. IF VAL(INTEGER, ORD(ch)) = a^.sym THEN RETURN a END
  265. ELSIF a^.typ = CRT.class THEN
  266. CRT.GetClass(a^.sym, set);
  267. IF Sets.In(set, ORD(ch)) THEN RETURN a END
  268. END;
  269. a := a^.next
  270. END;
  271. RETURN NIL
  272. END TheAction;
  273. PROCEDURE AddTargetList (VAR lista, listb: Target);
  274. VAR
  275. p,t: Target;
  276. PROCEDURE AddTarget (t: Target; VAR list: Target);
  277. VAR
  278. p,lastp: Target;
  279. BEGIN
  280. p := list; lastp := NIL;
  281. LOOP
  282. IF (p = NIL) OR (t^.state < p^.state) THEN EXIT END;
  283. IF p^.state = t^.state THEN
  284. Storage.DEALLOCATE(t, SYSTEM.TSIZE(TargetNode)); RETURN
  285. END;
  286. lastp := p; p := p^.next
  287. END;
  288. t^.next := p;
  289. IF lastp=NIL THEN list := t ELSE lastp^.next := t END
  290. END AddTarget;
  291. BEGIN
  292. p := lista;
  293. WHILE p # NIL DO
  294. Storage.ALLOCATE(t, SYSTEM.TSIZE(TargetNode));
  295. t^.state := p^.state; AddTarget(t, listb);
  296. p := p^.next
  297. END
  298. END AddTargetList;
  299. (* NewMelted Generate new info about a melted state
  300. ------------------------------------------------------------------------*)
  301. PROCEDURE NewMelted (set: CRT.Set; s: INTEGER): Melted;
  302. VAR
  303. melt: Melted;
  304. BEGIN
  305. Storage.ALLOCATE(melt, SYSTEM.TSIZE(MeltedNode));
  306. melt^.set := set; melt^.state := s;
  307. melt^.next := firstMelted; firstMelted := melt;
  308. RETURN melt
  309. END NewMelted;
  310. (* NewState Return a new state node
  311. ------------------------------------------------------------------------*)
  312. PROCEDURE NewState (): INTEGER;
  313. BEGIN
  314. INC(lastState);
  315. IF lastState > maxStates THEN CRT.Restriction(7, maxStates) END;
  316. state[lastState].firstAction := NIL;
  317. state[lastState].endOf := CRT.noSym;
  318. state[lastState].ctx := FALSE;
  319. RETURN lastState
  320. END NewState;
  321. (* NewTransition Generate transition (gn.state, gn.p1) --> toState
  322. ------------------------------------------------------------------------*)
  323. PROCEDURE NewTransition (from: INTEGER; gn: CRT.GraphNode;
  324. toState: INTEGER);
  325. VAR
  326. a: Action;
  327. t: Target;
  328. BEGIN
  329. IF toState = rootState THEN SemErr(21) END;
  330. Storage.ALLOCATE(t, SYSTEM.TSIZE(TargetNode));
  331. t^.state := toState; t^.next := NIL;
  332. Storage.ALLOCATE(a, SYSTEM.TSIZE(ActionNode));
  333. a^.typ := gn.typ; a^.sym := gn.p1; a^.tc := gn.p2;
  334. a^.target := t;
  335. AddAction(a, state[from].firstAction)
  336. END NewTransition;
  337. (* NewComment Define new comment
  338. -------------------------------------------------------------------------*)
  339. PROCEDURE NewComment (from, to: INTEGER; nested: BOOLEAN);
  340. VAR
  341. com: Comment;
  342. PROCEDURE MakeStr (gp: INTEGER; VAR s: ARRAY OF CHAR);
  343. VAR
  344. i, n: INTEGER;
  345. gn: CRT.GraphNode;
  346. set: CRT.Set;
  347. BEGIN
  348. i := 0;
  349. WHILE gp # 0 DO
  350. CRT.GetNode(gp, gn);
  351. IF gn.typ = CRT.char THEN
  352. IF i < 2 THEN s[i] := CHR(gn.p1) END; INC(i)
  353. ELSIF gn.typ = CRT.class THEN
  354. CRT.GetClass(gn.p1, set);
  355. IF Sets.Elements(set, n) # 1 THEN SemErr(26) END;
  356. IF i < 2 THEN s[i] := CHR(n) END; INC(i)
  357. ELSE SemErr(22)
  358. END;
  359. gp := gn.next
  360. END;
  361. IF (i = 0) OR (i > 2) THEN SemErr(25) ELSIF i < 2 THEN s[i] := 0C END
  362. END MakeStr;
  363. BEGIN
  364. Storage.ALLOCATE(com, SYSTEM.TSIZE(CommentNode));
  365. MakeStr(from, com^.start); MakeStr(to, com^.stop);
  366. com^.nested := nested;
  367. com^.next := firstComment; firstComment := com
  368. END NewComment;
  369. (* DeleteTargetList Delete a target list
  370. -------------------------------------------------------------------------*)
  371. PROCEDURE DeleteTargetList (list: Target);
  372. BEGIN
  373. IF list # NIL THEN
  374. DeleteTargetList(list^.next);
  375. Storage.DEALLOCATE(list, SYSTEM.TSIZE(TargetNode))
  376. END;
  377. END DeleteTargetList;
  378. (* DeleteActionList Delete an action list
  379. -------------------------------------------------------------------------*)
  380. PROCEDURE DeleteActionList (action: Action);
  381. BEGIN
  382. IF action # NIL THEN
  383. DeleteActionList(action^.next);
  384. DeleteTargetList(action^.target);
  385. Storage.DEALLOCATE(action, SYSTEM.TSIZE(ActionNode))
  386. END
  387. END DeleteActionList;
  388. (* MakeSet Expand action symbol into symbol set
  389. -------------------------------------------------------------------------*)
  390. PROCEDURE MakeSet (p: Action; VAR set: CRT.Set);
  391. BEGIN
  392. IF p^.typ = CRT.class THEN
  393. CRT.GetClass(p^.sym, set)
  394. ELSE Sets.Clear(set); Sets.Incl(set, p^.sym)
  395. END
  396. END MakeSet;
  397. (* ChangeAction Change the action symbol to set
  398. -------------------------------------------------------------------------*)
  399. PROCEDURE ChangeAction (a: Action; set: CRT.Set);
  400. VAR
  401. nr: INTEGER;
  402. BEGIN
  403. IF Sets.Elements(set, nr) = 1 THEN a^.typ := CRT.char; a^.sym := nr
  404. ELSE
  405. nr := CRT.ClassWithSet(set);
  406. IF nr < 0 THEN nr := CRT.NewClass("##", set) END;
  407. a^.typ := CRT.class; a^.sym := nr
  408. END
  409. END ChangeAction;
  410. (* CombineShifts Combine shifts with different symbols into same state
  411. -------------------------------------------------------------------------*)
  412. PROCEDURE CombineShifts;
  413. VAR
  414. s: INTEGER;
  415. a, b, c: Action;
  416. seta, setb: CRT.Set;
  417. BEGIN
  418. s := rootState;
  419. WHILE s <= lastState DO
  420. a := state[s].firstAction;
  421. WHILE a # NIL DO
  422. b := a^.next;
  423. WHILE b # NIL DO
  424. IF (a^.target^.state = b^.target^.state) & (a^.tc = b^.tc) THEN
  425. MakeSet(a, seta); MakeSet(b, setb); Sets.Unite(seta, setb);
  426. ChangeAction(a, seta);
  427. c := b; b := b^.next; DetachAction(c, a)
  428. ELSE b := b^.next
  429. END
  430. END;
  431. a := a^.next
  432. END;
  433. INC(s)
  434. END
  435. END CombineShifts;
  436. (* DeleteRedundantStates Delete unused and equal states
  437. -------------------------------------------------------------------------*)
  438. PROCEDURE DeleteRedundantStates;
  439. VAR
  440. action: Action;
  441. s, s2, next: INTEGER;
  442. used: ARRAY [0 .. maxStates DIV Sets.size] OF BITSET (*KJG*);
  443. newStateNr: ARRAY [0 .. maxStates] OF INTEGER;
  444. PROCEDURE FindUsedStates (s: INTEGER);
  445. VAR
  446. action: Action;
  447. BEGIN
  448. IF Sets.In(used, s) THEN RETURN END;
  449. Sets.Incl(used, s);
  450. action := state[s].firstAction;
  451. WHILE action # NIL DO
  452. FindUsedStates(action^.target^.state);
  453. action := action^.next
  454. END
  455. END FindUsedStates;
  456. BEGIN
  457. Sets.Clear(used); FindUsedStates(rootState);
  458. (*---------- combine equal final states ------------*)
  459. s := rootState + 1; (*root state cannot be final*)
  460. WHILE s <= lastState DO
  461. IF Sets.In(used, s) & (state[s].endOf # CRT.noSym) THEN
  462. IF (state[s].firstAction = NIL) & ~ state[s].ctx THEN
  463. s2 := s + 1;
  464. WHILE s2 <= lastState DO
  465. IF Sets.In(used, s2) & (state[s].endOf = state[s2].endOf) THEN
  466. IF (state[s2].firstAction = NIL) AND ~ state[s2].ctx THEN
  467. Sets.Excl(used, s2); newStateNr[s2] := s
  468. END
  469. END;
  470. INC(s2)
  471. END
  472. END
  473. END;
  474. INC(s)
  475. END;
  476. s := rootState;
  477. (* + 1 ? PDT - was rootState, but Oberon had .next ie +1
  478. seems to work both ways?? *);
  479. WHILE s <= lastState DO
  480. IF Sets.In(used, s) THEN
  481. action := state[s].firstAction;
  482. WHILE action # NIL DO
  483. IF ~ Sets.In(used, action^.target^.state) THEN
  484. action^.target^.state := newStateNr[action^.target^.state]
  485. END;
  486. action := action^.next
  487. END
  488. END;
  489. INC(s)
  490. END;
  491. (*-------- delete unused states --------*)
  492. s := rootState + 1; next := s;
  493. WHILE s <= lastState DO
  494. IF Sets.In(used, s) THEN
  495. IF next < s THEN state[next] := state[s] END;
  496. newStateNr[s] := next; INC(next)
  497. ELSE
  498. DeleteActionList(state[s].firstAction)
  499. END;
  500. INC(s)
  501. END;
  502. lastState := next - 1;
  503. s := rootState;
  504. WHILE s <= lastState DO
  505. action := state[s].firstAction;
  506. WHILE action # NIL DO
  507. action^.target^.state := newStateNr[action^.target^.state];
  508. action := action^.next
  509. END;
  510. INC(s)
  511. END
  512. END DeleteRedundantStates;
  513. (* ConvertToStates Convert the TDG in gp into a subautomaton of the DFA
  514. ------------------------------------------------------------------------*)
  515. PROCEDURE ConvertToStates (gp0, sp: INTEGER);
  516. (*note: gn.line is abused as a state number!*)
  517. VAR
  518. stepped, visited: CRT.MarkList;
  519. PROCEDURE NumberNodes (gp, snr: INTEGER);
  520. VAR
  521. gn: CRT.GraphNode;
  522. BEGIN
  523. IF gp = 0 THEN RETURN END; (*end of graph*)
  524. CRT.GetNode(gp, gn);
  525. IF gn.line >= 0 THEN RETURN END; (*already visited*)
  526. IF snr < rootState THEN snr := NewState() END;
  527. gn.line := snr; CRT.PutNode(gp, gn);
  528. IF CRT.DelGraph(gp) THEN state[snr].endOf := sp END;
  529. (*snr is end state*)
  530. CASE gn.typ OF
  531. CRT.class, CRT.char:
  532. NumberNodes(ABS(gn.next), rootState - 1);
  533. | CRT.opt:
  534. NumberNodes(ABS(gn.next), rootState - 1); NumberNodes(gn.p1, snr)
  535. | CRT.iter:
  536. NumberNodes(ABS(gn.next), snr); NumberNodes(gn.p1, snr)
  537. | CRT.alt:
  538. NumberNodes(gn.p1, snr); NumberNodes(gn.p2, snr)
  539. END;
  540. END NumberNodes;
  541. PROCEDURE TheState (gp: INTEGER): INTEGER;
  542. VAR
  543. s: INTEGER;
  544. gn: CRT.GraphNode;
  545. BEGIN
  546. IF gp = 0 THEN s := NewState(); state[s].endOf := sp; RETURN s
  547. ELSE CRT.GetNode(gp, gn); RETURN gn.line
  548. END
  549. END TheState;
  550. PROCEDURE Step (from, gp: INTEGER);
  551. VAR
  552. gn: CRT.GraphNode;
  553. next : INTEGER;
  554. BEGIN
  555. IF gp = 0 THEN RETURN END;
  556. Sets.Incl(stepped, gp);
  557. CRT.GetNode(gp, gn);
  558. CASE gn.typ OF
  559. CRT.class, CRT.char:
  560. NewTransition(from, gn, TheState(ABS(gn.next)))
  561. | CRT.alt:
  562. Step(from, gn.p1); Step(from, gn.p2)
  563. | CRT.opt, CRT.iter:
  564. next := ABS(gn.next);
  565. IF NOT Sets.In(stepped, next) THEN Step(from, next) END;
  566. Step(from, gn.p1)
  567. END
  568. END Step;
  569. PROCEDURE FindTrans (gp: INTEGER; start: BOOLEAN);
  570. VAR
  571. gn: CRT.GraphNode;
  572. BEGIN
  573. IF (gp = 0) OR Sets.In(visited, gp) THEN RETURN END;
  574. Sets.Incl(visited, gp); CRT.GetNode(gp, gn);
  575. IF start THEN (* start of group of equally numbered nodes *)
  576. CRT.ClearMarkList(stepped);
  577. Step(gn.line, gp)
  578. END;
  579. CASE gn.typ OF
  580. CRT.class, CRT.char:
  581. FindTrans(ABS(gn.next), TRUE);
  582. | CRT.opt:
  583. FindTrans(ABS(gn.next), TRUE); FindTrans(gn.p1, FALSE)
  584. | CRT.iter:
  585. FindTrans(ABS(gn.next), FALSE); FindTrans(gn.p1, FALSE)
  586. | CRT.alt:
  587. FindTrans(gn.p1, FALSE); FindTrans(gn.p2, FALSE)
  588. END;
  589. END FindTrans;
  590. VAR
  591. gn: CRT.GraphNode;
  592. i: INTEGER;
  593. BEGIN
  594. IF CRT.DelGraph(gp0) THEN SemErr(20) END;
  595. FOR i := 0 TO CRT.nNodes DO
  596. CRT.GetNode(i, gn); gn.line := -1; CRT.PutNode(i, gn)
  597. END;
  598. NumberNodes(gp0, rootState);
  599. CRT.ClearMarkList(visited);
  600. FindTrans(gp0, TRUE)
  601. END ConvertToStates;
  602. PROCEDURE MatchDFA (str: ARRAY OF CHAR; sp: INTEGER;
  603. VAR matchedSp: INTEGER);
  604. VAR
  605. s, to: INTEGER (* State *);
  606. a: Action;
  607. gn: CRT.GraphNode;
  608. i, len: INTEGER;
  609. weakMatch: BOOLEAN;
  610. BEGIN (* s with quotes *)
  611. s := rootState; i := 1; len := FileIO.SLENGTH(str) - 1;
  612. weakMatch := FALSE;
  613. LOOP (* try to match str against existing DFA *)
  614. IF i = len THEN EXIT END;
  615. a := TheAction(state[s], str[i]);
  616. IF a = NIL THEN EXIT END;
  617. IF a^.typ = CRT.class THEN weakMatch := TRUE END;
  618. s := a^.target^.state; INC(i)
  619. END;
  620. IF weakMatch & ((i # len) OR (state[s].endOf = CRT.noSym)) THEN
  621. s := rootState; i := 1; dirtyDFA := TRUE
  622. END;
  623. WHILE i < len DO (* make new DFA for str[i..len-1] *)
  624. to := NewState();
  625. gn.typ := CRT.char; gn.p1 := ORD(str[i]); gn.p2 := CRT.normTrans;
  626. NewTransition(s, gn, to); (* PDT Tue 01-11-94 *)
  627. s := to; INC(i)
  628. END;
  629. matchedSp := state[s].endOf;
  630. IF state[s].endOf = CRT.noSym THEN state[s].endOf := sp END
  631. END MatchDFA;
  632. (* SplitActions Generate unique actions from two overlapping actions
  633. -----------------------------------------------------------------------*)
  634. PROCEDURE SplitActions (a, b: Action);
  635. VAR
  636. c: Action;
  637. seta, setb, setc: CRT.Set;
  638. PROCEDURE CombineTransCodes (t1, t2: INTEGER; VAR result: INTEGER);
  639. BEGIN
  640. IF t1 = CRT.contextTrans THEN result := t1 ELSE result := t2 END
  641. END CombineTransCodes;
  642. BEGIN
  643. MakeSet(a, seta); MakeSet(b, setb);
  644. IF Sets.Equal(seta, setb) THEN
  645. AddTargetList(b^.target, a^.target);
  646. DeleteTargetList(b^.target);
  647. CombineTransCodes(a^.tc, b^.tc, a^.tc);
  648. DetachAction(b, a);
  649. Storage.DEALLOCATE(b, SYSTEM.TSIZE(ActionNode))
  650. ELSIF Sets.Includes(seta, setb) THEN
  651. setc := seta; Sets.Differ(setc, setb);
  652. AddTargetList(a^.target, b^.target);
  653. CombineTransCodes(a^.tc, b^.tc, b^.tc);
  654. ChangeAction(a, setc)
  655. ELSIF Sets.Includes(setb, seta) THEN
  656. setc := setb; Sets.Differ(setc, seta);
  657. AddTargetList(b^.target, a^.target);
  658. CombineTransCodes(a^.tc, b^.tc, a^.tc);
  659. ChangeAction(b, setc)
  660. ELSE
  661. Sets.Intersect(seta, setb, setc);
  662. Sets.Differ(seta, setc);
  663. Sets.Differ(setb, setc);
  664. ChangeAction(a, seta);
  665. ChangeAction(b, setb);
  666. Storage.ALLOCATE(c, SYSTEM.TSIZE(ActionNode));
  667. c^.target := NIL;
  668. CombineTransCodes(a^.tc, b^.tc, c^.tc);
  669. AddTargetList(a^.target, c^.target);
  670. AddTargetList(b^.target, c^.target);
  671. ChangeAction(c, setc);
  672. AddAction(c, a)
  673. END
  674. END SplitActions;
  675. (* MakeUnique Make all actions in this state unique
  676. -------------------------------------------------------------------------*)
  677. PROCEDURE MakeUnique (s: INTEGER; VAR changed: BOOLEAN);
  678. VAR
  679. a, b: Action;
  680. PROCEDURE Overlap (a, b: Action): BOOLEAN;
  681. VAR
  682. seta, setb: CRT.Set;
  683. BEGIN
  684. IF a^.typ = CRT.char THEN
  685. IF b^.typ = CRT.char
  686. THEN RETURN a^.sym = b^.sym
  687. ELSE CRT.GetClass(b^.sym, setb); RETURN Sets.In(setb, a^.sym)
  688. END
  689. ELSE
  690. CRT.GetClass(a^.sym, seta);
  691. IF b^.typ = CRT.char
  692. THEN RETURN Sets.In(seta, b^.sym)
  693. ELSE CRT.GetClass(b^.sym, setb);
  694. RETURN ~ Sets.Different(seta, setb)
  695. END
  696. END
  697. END Overlap;
  698. BEGIN
  699. a := state[s].firstAction; changed := FALSE;
  700. WHILE a # NIL DO
  701. b := a^.next;
  702. WHILE b # NIL DO
  703. IF Overlap(a, b) THEN
  704. SplitActions(a, b); changed := TRUE; RETURN
  705. (* originally no RETURN. FST blows up if we leave RETURN out.
  706. Somewhere there is a field that is not properly set, but I
  707. have not chased this down completely Fri 08-20-1993 *)
  708. END;
  709. b := b^.next;
  710. END;
  711. a := a^.next
  712. END;
  713. END MakeUnique;
  714. (* MeltStates Melt states appearing with a shift of the same symbol
  715. -----------------------------------------------------------------------*)
  716. PROCEDURE MeltStates (s: INTEGER; VAR correct: BOOLEAN);
  717. VAR
  718. action: Action;
  719. ctx: BOOLEAN;
  720. endOf: INTEGER;
  721. melt: Melted;
  722. set: CRT.Set;
  723. s1: INTEGER;
  724. changed: BOOLEAN;
  725. PROCEDURE AddMeltedSet (nr: INTEGER; VAR set: CRT.Set);
  726. VAR
  727. m: Melted;
  728. BEGIN
  729. m := firstMelted;
  730. WHILE (m # NIL) & (m^.state # nr) DO m := m^.next END;
  731. IF m = NIL THEN CRT.Restriction(-1, 0) (* compiler error *) END;
  732. Sets.Unite(set, m^.set);
  733. END AddMeltedSet;
  734. PROCEDURE GetStateSet (t: Target; VAR set: CRT.Set; VAR endOf: INTEGER;
  735. VAR ctx: BOOLEAN);
  736. (* Modified back to match Oberon version Fri 08-20-1993
  737. This seemed to cause problems with some larger automata *)
  738. (* new bug fix Wed 11-24-1993 from ETHZ incorporated *)
  739. VAR
  740. lastS: INTEGER;
  741. BEGIN
  742. Sets.Clear(set); endOf := CRT.noSym; ctx := FALSE;
  743. lastS := lastState; (* Fri 08-20-1993 *)
  744. WHILE t # NIL DO
  745. IF t^.state <= lastSimState THEN Sets.Incl(set, t^.state);
  746. ELSE AddMeltedSet(t^.state, set);
  747. END;
  748. IF state[t^.state].endOf # CRT.noSym THEN
  749. IF (endOf = CRT.noSym) OR (endOf = state[t^.state].endOf) THEN
  750. endOf := state[t^.state].endOf; lastS := t^.state
  751. ELSE
  752. PutS("$Tokens "); PutI(endOf); PutS(" and ");
  753. PutI(state[t^.state].endOf);
  754. PutS(" cannot be distinguished.$");
  755. correct := FALSE;
  756. END;
  757. END;
  758. IF state[t^.state].ctx THEN
  759. ctx := TRUE;
  760. (* removed this test Fri 08-30-02
  761. IF state[t^.state].endOf # CRT.noSym THEN
  762. PutS("$Ambiguous CONTEXT clause.$"); correct := FALSE
  763. END
  764. *)
  765. END;
  766. t := t^.next
  767. END
  768. END GetStateSet;
  769. PROCEDURE FillWithActions (s: INTEGER; targ: Target);
  770. VAR
  771. action, a: Action;
  772. BEGIN
  773. WHILE targ # NIL DO
  774. action := state[targ^.state].firstAction;
  775. WHILE action # NIL DO
  776. Storage.ALLOCATE(a, SYSTEM.TSIZE(ActionNode));
  777. a^ := action^; a^.target := NIL;
  778. AddTargetList(action^.target, a^.target);
  779. AddAction(a, state[s].firstAction);
  780. action := action^.next
  781. END;
  782. targ := targ^.next
  783. END;
  784. END FillWithActions;
  785. PROCEDURE KnownMelted (set: CRT.Set; VAR melt: Melted): BOOLEAN;
  786. BEGIN
  787. melt := firstMelted;
  788. WHILE melt # NIL DO
  789. IF Sets.Equal(set, melt^.set) THEN RETURN TRUE END;
  790. melt := melt^.next
  791. END;
  792. RETURN FALSE
  793. END KnownMelted;
  794. BEGIN
  795. action := state[s].firstAction;
  796. WHILE action # NIL DO
  797. IF action^.target^.next # NIL THEN
  798. GetStateSet(action^.target, set, endOf, ctx);
  799. IF ~ KnownMelted(set, melt) THEN
  800. s1 := NewState();
  801. state[s1].endOf := endOf; state[s1].ctx := ctx;
  802. FillWithActions(s1, action^.target);
  803. REPEAT MakeUnique(s1, changed) UNTIL ~ changed;
  804. melt := NewMelted(set, s1);
  805. END;
  806. DeleteTargetList(action^.target^.next);
  807. action^.target^.next := NIL;
  808. action^.target^.state := melt^.state
  809. END;
  810. action := action^.next
  811. END
  812. END MeltStates;
  813. (* MakeDeterministic Make NDFA --> DFA
  814. ------------------------------------------------------------------------*)
  815. PROCEDURE MakeDeterministic (VAR correct: BOOLEAN);
  816. VAR
  817. s: INTEGER;
  818. changed: BOOLEAN;
  819. PROCEDURE FindCtxStates;
  820. (* Find states reached by a context transition *)
  821. VAR
  822. a: Action;
  823. s: INTEGER;
  824. BEGIN
  825. s := rootState;
  826. WHILE s <= lastState DO
  827. a := state[s].firstAction;
  828. WHILE a # NIL DO
  829. IF a^.tc = CRT.contextTrans THEN
  830. state[a^.target^.state].ctx := TRUE
  831. END;
  832. a := a^.next
  833. END;
  834. INC(s)
  835. END;
  836. END FindCtxStates;
  837. BEGIN
  838. out := CRS.lst;
  839. lastSimState := lastState;
  840. FindCtxStates;
  841. s := rootState;
  842. WHILE s <= lastState DO
  843. REPEAT MakeUnique(s, changed) UNTIL ~ changed;
  844. INC(s)
  845. END;
  846. correct := TRUE;
  847. s := rootState;
  848. WHILE s <= lastState DO MeltStates(s, correct); INC(s) END;
  849. DeleteRedundantStates;
  850. CombineShifts;
  851. (* ==== IF CRT.ddt["A"] THEN PrintStates END ==== *)
  852. END MakeDeterministic;
  853. (* GenComment Generate a procedure to scan comments
  854. -------------------------------------------------------------------------*)
  855. PROCEDURE GenComment (leftMarg: CARDINAL; com: Comment);
  856. PROCEDURE GenBody (leftMarg: CARDINAL);
  857. BEGIN
  858. PutB(leftMarg); PutS("LOOP$");
  859. PutB(leftMarg + 2); PutS("IF ");
  860. PutChCond(com^.stop[0]); PutS(" THEN$");
  861. IF FileIO.SLENGTH(com^.stop) = 1 THEN
  862. PutB(leftMarg + 4);
  863. PutS("DEC(level); oldEols := curLine - startLine; NextCh;$");
  864. PutB(leftMarg + 4); PutS("IF level = 0 THEN RETURN TRUE END;$");
  865. ELSE
  866. PutB(leftMarg + 4); PutS("NextCh;$");
  867. PutB(leftMarg + 4); PutS("IF ");
  868. PutChCond(com^.stop[1]); PutS(" THEN$");
  869. PutB(leftMarg + 6); PutS("DEC(level); NextCh;$");
  870. PutB(leftMarg + 6); PutS("IF level = 0 THEN RETURN TRUE END$");
  871. PutB(leftMarg + 4); PutS("END;$");
  872. END;
  873. IF com^.nested THEN
  874. PutB(leftMarg + 2); PutS("ELSIF "); PutChCond(com^.start[0]);
  875. PutS(" THEN$");
  876. IF FileIO.SLENGTH(com^.start) = 1 THEN
  877. PutB(leftMarg + 4); PutS("INC(level); NextCh;$");
  878. ELSE
  879. PutB(leftMarg + 4); PutS("NextCh;$");
  880. PutB(leftMarg + 4); PutS("IF "); PutChCond(com^.start[1]);
  881. PutS(" THEN "); PutS("INC(level); NextCh "); PutS("END;$");
  882. END;
  883. END;
  884. PutB(leftMarg + 2); PutS("ELSIF ch = EOF THEN RETURN FALSE$");
  885. PutB(leftMarg + 2); PutS("ELSE NextCh END;$");
  886. PutB(leftMarg); PutS("END; (* LOOP *)$");
  887. END GenBody;
  888. BEGIN
  889. PutS("IF "); PutChCond(com^.start[0]); PutS(" THEN$");
  890. IF FileIO.SLENGTH(com^.start) = 1 THEN
  891. PutB(leftMarg + 2); PutS("NextCh;$");
  892. GenBody(leftMarg + 2);
  893. ELSE
  894. PutB(leftMarg + 2); PutS("NextCh;$");
  895. PutB(leftMarg + 2); PutS("IF ");
  896. PutChCond(com^.start[1]); PutS(" THEN$");
  897. PutB(leftMarg + 4); PutS("NextCh;$");
  898. GenBody(leftMarg + 4);
  899. PutB(leftMarg + 2); PutS("ELSE$");
  900. PutB(leftMarg + 4);
  901. PutS("IF (ch = CR) OR (ch = LF) THEN$");
  902. PutB(leftMarg + 6);
  903. PutS("DEC(curLine); lineStart := oldLineStart$");
  904. PutB(leftMarg + 4); PutS("END;$");
  905. PutB(leftMarg + 4);
  906. PutS("DEC(bp); ch := lastCh;$");
  907. PutB(leftMarg + 2); PutS("END;$");
  908. END;
  909. PutB(leftMarg); PutS("END;$"); PutB(leftMarg);
  910. END GenComment;
  911. (* CopyFramePart Copy from file <fram> to file <framOut> until <stopStr>
  912. -------------------------------------------------------------------------*)
  913. PROCEDURE CopyFramePart (stopStr: ARRAY OF CHAR; VAR leftMarg: CARDINAL;
  914. VAR framIn, framOut:FileIO.File);
  915. VAR
  916. ch, startCh: CHAR;
  917. slen, i: CARDINAL;
  918. temp: ARRAY [0 .. 63] OF CHAR;
  919. BEGIN
  920. startCh := stopStr[0]; FileIO.Read(framIn, ch);
  921. slen := FileIO.SLENGTH(stopStr);
  922. WHILE FileIO.Okay DO
  923. IF (ch = FileIO.EOL) OR (ch = FileIO.CR) OR (ch = FileIO.LF)
  924. THEN leftMarg := 0
  925. ELSE INC(leftMarg)
  926. END;
  927. (* ProgArgs.Assert(leftMarg <= 100); for gpm version *)
  928. IF ch = startCh
  929. THEN (* check if stopString occurs *)
  930. i := 0;
  931. WHILE (i + 1 < slen) & (ch = stopStr[i]) & FileIO.Okay DO
  932. temp[i] := ch; INC(i); FileIO.Read(framIn, ch)
  933. END;
  934. IF ch = stopStr[i] THEN DEC(leftMarg); RETURN END;
  935. (* found ==> exit , else continue *)
  936. FileIO.WriteText(framOut, temp, i);
  937. FileIO.Write(framOut, ch);
  938. INC(leftMarg, i);
  939. ELSE FileIO.Write(framOut, ch)
  940. END;
  941. FileIO.Read(framIn, ch)
  942. END;
  943. END CopyFramePart;
  944. (* ImportSymConsts Generates the import of the named symbol constants
  945. -------------------------------------------------------------------------*)
  946. PROCEDURE ImportSymConsts (putS: PutSProc);
  947. VAR
  948. i, len,
  949. oldLen, pos: INTEGER;
  950. cname: CRT.Name;
  951. gn: CRT.GraphNode;
  952. sn: CRT.SymbolNode;
  953. gramName: ARRAY [0 .. 31] OF CHAR;
  954. PROCEDURE PutImportSym;
  955. BEGIN
  956. IF pos + oldLen > MaxSourceLineLength THEN putS("$ "); pos := 2 END;
  957. putS(cname); INC(pos, oldLen + 1);
  958. (* This is not strictly correct, as the increase of 2 should be
  959. lower. I omitted it, because to separate it would be too
  960. complicated, and no unexpected side effects are likely, since it
  961. is only called again outside the loop - after which "pos" is not
  962. used again
  963. *)
  964. END PutImportSym;
  965. BEGIN
  966. (* ----- Import list of the generated Symbol Constants Module ----- *)
  967. putS(";$$FROM ");
  968. CRT.GetNode(CRT.root, gn); CRT.GetSym(gn.p1, sn);
  969. FileIO.Extract(sn.name, 0, 7, gramName);
  970. putS(gramName); putS("G IMPORT ");
  971. i := 0; pos := MaxSourceLineLength + 1; oldLen := 0;
  972. LOOP
  973. CRT.GetSym(i, sn); len := FileIO.SLENGTH(sn.constant);
  974. IF len > 0 THEN
  975. IF oldLen > 0 THEN PutImportSym; putS(", ") END;
  976. oldLen := len + 1; cname := sn.constant;
  977. END;
  978. IF i = CRT.maxP THEN EXIT END;
  979. INC(i);
  980. END; (* LOOP *)
  981. PutImportSym;
  982. END ImportSymConsts;
  983. (* GenLiterals Generate CASE for the recognition of literals
  984. -------------------------------------------------------------------------*)
  985. PROCEDURE GenLiterals (leftMarg: CARDINAL);
  986. VAR
  987. FirstLine: BOOLEAN;
  988. i, j, k: INTEGER;
  989. key: ARRAY [0 .. CRT.maxLiterals] OF CRT.Name;
  990. knr: ARRAY [0 .. CRT.maxLiterals] OF INTEGER;
  991. ch: CHAR;
  992. sn: CRT.SymbolNode;
  993. BEGIN
  994. (*-- sort literal list*)
  995. i := 0; k := 0;
  996. WHILE i <= CRT.maxT DO
  997. CRT.GetSym(i, sn);
  998. IF sn.struct = CRT.litToken THEN
  999. j := k-1;
  1000. WHILE (j >= 0) & (FileIO.Compare(sn.name, key[j]) < 0) DO
  1001. key[j + 1] := key[j]; knr[j + 1] := knr[j]; DEC(j)
  1002. END;
  1003. key[j + 1] := sn.name; knr[j + 1] := i;
  1004. INC(k); IF k > CRT.maxLiterals THEN CRT.Restriction(10, CRT.maxLiterals) END;
  1005. END;
  1006. INC(i)
  1007. END;
  1008. (*-- print CASE statement*)
  1009. IF k # 0 THEN
  1010. PutS("CASE CurrentCh(bp0) OF$"); PutB(leftMarg);
  1011. i := 0; FirstLine := TRUE;
  1012. WHILE i < k DO
  1013. ch := key[i, 1]; (*key[i, 0] = quote*)
  1014. IF i # 0 THEN PutLn; PutB(leftMarg) END;
  1015. IF FirstLine THEN
  1016. FirstLine := FALSE; PutS(" ") ELSE PutS("| ")
  1017. END;
  1018. PutC(ch); j := i;
  1019. REPEAT
  1020. IF i = j THEN
  1021. PutS(": IF") ELSE PutB(leftMarg + 6); PutS(" ELSIF")
  1022. END;
  1023. PutS(" Equal("); PutS(key[i]); PutS(") THEN ");
  1024. PutSE(knr[i]); PutLn;
  1025. INC(i);
  1026. UNTIL (i = k) OR (key[i, 1] # ch);
  1027. PutB(leftMarg + 6); PutS(" END");
  1028. END;
  1029. PutLn; PutB(leftMarg); PutS("ELSE$");
  1030. PutB(leftMarg); PutS("END")
  1031. END;
  1032. END GenLiterals;
  1033. (* WriteState Write the source text of a scanner state
  1034. -------------------------------------------------------------------------*)
  1035. PROCEDURE WriteState (leftMarg, s: INTEGER; VAR FirstState: BOOLEAN);
  1036. VAR
  1037. action: Action;
  1038. ind: INTEGER;
  1039. first, ctxEnd: BOOLEAN;
  1040. sn: CRT.SymbolNode;
  1041. endOf: INTEGER;
  1042. set: CRT.Set;
  1043. BEGIN
  1044. endOf := state[s].endOf;
  1045. IF (endOf > CRT.maxT) & (endOf # CRT.noSym) THEN
  1046. (*pragmas have been moved*)
  1047. endOf := CRT.maxT + CRT.maxSymbols - endOf
  1048. END;
  1049. (* ProgArgs.Assert(leftMarg <= 100); for gpm version *)
  1050. Indent(leftMarg);
  1051. IF FirstState THEN FirstState := FALSE; PutS(" ") ELSE PutS("| ") END;
  1052. PutI2(s, 2); PutS(": ");
  1053. first := TRUE; ctxEnd := state[s].ctx;
  1054. action := state[s].firstAction;
  1055. WHILE action # NIL DO
  1056. IF first
  1057. THEN PutS("IF "); first := FALSE; ind := leftMarg + 3;
  1058. ELSE PutB(leftMarg + 6); PutS("ELSIF "); ind := leftMarg + 6;
  1059. END;
  1060. IF action^.typ = CRT.char THEN PutChCond(CHR(action^.sym))
  1061. ELSE CRT.GetClass(action^.sym, set); PutRange(set,leftMarg + ind)
  1062. END;
  1063. PutS(" THEN");
  1064. IF action^.target^.state # s THEN
  1065. PutS(" state := "); PutI(action^.target^.state); Put(";")
  1066. END;
  1067. IF action^.tc = CRT.contextTrans
  1068. THEN PutS(" INC(apx)"); ctxEnd := FALSE
  1069. ELSIF state[s].ctx THEN PutS(" apx := Long0")
  1070. END;
  1071. PutS(" $");
  1072. action := action^.next
  1073. END;
  1074. IF state[s].firstAction # NIL THEN
  1075. PutB(leftMarg + 6); PutS("ELSE ")
  1076. END;
  1077. IF endOf = CRT.noSym THEN PutS("sym := noSYMB; ");
  1078. ELSE (*final state*)
  1079. CRT.GetSym(endOf, sn);
  1080. IF ctxEnd THEN (*cut appendix*)
  1081. PutS("bp := bp - apx - Long1;");
  1082. PutS(" DEC(nextLen, ORDL(apx)); NextCh; ")
  1083. END;
  1084. PutSE(endOf);
  1085. IF sn.struct = CRT.classLitToken THEN PutS("CheckLiteral; ") END
  1086. END;
  1087. PutS("RETURN$");
  1088. IF state[s].firstAction # NIL THEN
  1089. PutB(leftMarg + 6); PutS("END;$")
  1090. END
  1091. END WriteState;
  1092. (* WriteScanner Write the scanner source file
  1093. -------------------------------------------------------------------------*)
  1094. PROCEDURE WriteScanner (VAR ok : BOOLEAN);
  1095. CONST
  1096. ListingWidth = 78;
  1097. VAR
  1098. gramName: ARRAY [0 .. 31] OF CHAR;
  1099. fGramName, fn: ARRAY [0 .. 63] OF CHAR;
  1100. startTab: ARRAY [0 .. 255] OF INTEGER;
  1101. com: Comment;
  1102. i, j, s: INTEGER;
  1103. gn: CRT.GraphNode;
  1104. sn: CRT.SymbolNode;
  1105. PROCEDURE FillStartTab;
  1106. VAR
  1107. action: Action;
  1108. i, targetState, undefState: INTEGER;
  1109. class: CRT.Set;
  1110. BEGIN
  1111. undefState := lastState + 2;
  1112. startTab[0] := lastState + 1; (*eof*)
  1113. i := 1;
  1114. WHILE i < 256 (*PDT*) DO startTab[i] := undefState; INC(i) END;
  1115. action := state[rootState].firstAction;
  1116. WHILE action # NIL DO
  1117. targetState := action^.target^.state;
  1118. IF action^.typ = CRT.char THEN
  1119. startTab[action^.sym] := targetState
  1120. ELSE
  1121. CRT.GetClass(action^.sym, class); i := 0;
  1122. WHILE i < 256 (*PDT*) DO
  1123. IF Sets.In(class, i) THEN startTab[i] := targetState END;
  1124. INC(i)
  1125. END
  1126. END;
  1127. action := action^.next
  1128. END
  1129. END FillStartTab;
  1130. VAR
  1131. LeftMargin : CARDINAL;
  1132. FirstState: BOOLEAN;
  1133. ScannerFrame: ARRAY [0 .. 63] OF CHAR;
  1134. BEGIN
  1135. IF dirtyDFA THEN MakeDeterministic(ok) END;
  1136. FillStartTab;
  1137. FileIO.Concat(CRS.directory, "scanner.frm", ScannerFrame);
  1138. FileIO.Open(fram, ScannerFrame, FALSE);
  1139. IF ~ FileIO.Okay THEN
  1140. FileIO.SearchFile(fram, "CRFRAMES", "scanner.frm", FALSE);
  1141. IF ~ FileIO.Okay THEN
  1142. FileIO.WriteLn(FileIO.StdOut);
  1143. FileIO.WriteString(FileIO.StdOut, "'scanner.frm' not found.");
  1144. FileIO.WriteLn(FileIO.StdOut);
  1145. FileIO.WriteString(FileIO.StdOut, "Aborted.");
  1146. FileIO.QuitExecution
  1147. END
  1148. END;
  1149. LeftMargin := 0;
  1150. CRT.GetNode(CRT.root, gn); CRT.GetSym(gn.p1, sn);
  1151. FileIO.Extract(sn.name, 0, 7, gramName);
  1152. FileIO.Concat(CRS.directory, gramName, fGramName);
  1153. (*------- *S.MOD -------*)
  1154. FileIO.Concat(fGramName, "S", fn);
  1155. FileIO.Concat(fn, FileIO.ModExt, fn);
  1156. (* ++
  1157. FileIO.WriteLn(FileIO.StdOut);
  1158. FileIO.WriteString(FileIO.StdOut, " ");
  1159. FileIO.WriteString(FileIO.StdOut, fn);
  1160. ++ *)
  1161. FileIO.Open(scanner, fn, TRUE);
  1162. out := scanner;
  1163. CopyFramePart("-->modulename", LeftMargin, fram, out);
  1164. PutS(gramName); Put("S");
  1165. IF CRT.ddt["N"] OR CRT.symNames THEN ImportSymConsts(PutS) END;
  1166. CopyFramePart("-->unknownsym", LeftMargin, fram, out);
  1167. IF CRT.ddt["N"] OR CRT.symNames
  1168. THEN PutSN(CRT.maxT)
  1169. ELSE PutI(CRT.maxT)
  1170. END;
  1171. CopyFramePart("-->comment", LeftMargin, fram, out);
  1172. com := firstComment;
  1173. WHILE com # NIL DO GenComment(LeftMargin, com); com := com^.next END;
  1174. CopyFramePart("-->literals", LeftMargin, fram, out);
  1175. GenLiterals(LeftMargin);
  1176. CopyFramePart("-->GetSy1", LeftMargin, fram, out);
  1177. NewLine := FALSE;
  1178. IF ~ Sets.In(CRT.ignored, ORD(cr)) THEN
  1179. Indent(LeftMargin);
  1180. PutS("IF oldEols > 0 THEN DEC(bp);");
  1181. PutS(" DEC(oldEols); ch := CR END;$")
  1182. END;
  1183. Indent(LeftMargin); PutS("WHILE (ch = ' ')");
  1184. IF ~ Sets.Empty(CRT.ignored) THEN
  1185. PutS(" OR$"); Indent(LeftMargin + 6);
  1186. PutRange(CRT.ignored, LeftMargin + 6);
  1187. END; (* PDT *)
  1188. PutS(" DO NextCh END;");
  1189. IF firstComment # NIL THEN
  1190. PutLn; PutB(LeftMargin); PutS("IF ("); com := firstComment;
  1191. WHILE com # NIL DO
  1192. PutChCond(com^.start[0]);
  1193. IF com^.next # NIL THEN PutS(" OR ") END;
  1194. com := com^.next
  1195. END;
  1196. PutS(") & Comment() THEN Get(sym); RETURN END;");
  1197. END;
  1198. CopyFramePart("-->GetSy2", LeftMargin, fram, out);
  1199. NewLine := FALSE; s := rootState + 1; FirstState := TRUE;
  1200. (* ProgArgs.Assert(leftMarg <= 100); for gpm version *)
  1201. WHILE s <= lastState DO
  1202. WriteState(LeftMargin, s, FirstState); INC(s)
  1203. END;
  1204. PutB(LeftMargin); PutS("| "); PutI2(lastState + 1, 2);
  1205. PutS(": "); PutSE(0); PutS("ch := 0C; DEC(bp); RETURN");
  1206. CopyFramePart("-->initializations", LeftMargin, fram, out);
  1207. IF CRT.ignoreCase
  1208. THEN PutS("CurrentCh := CapChAt;$")
  1209. ELSE PutS("CurrentCh := CharAt;$")
  1210. END;
  1211. PutB(LeftMargin);
  1212. i := 0;
  1213. WHILE i < 64 (*PDT*) DO
  1214. IF i # 0 THEN PutLn; PutB(LeftMargin); END;
  1215. j := 0;
  1216. WHILE j < 4 DO
  1217. PutS("start["); PutI2(4*i + j,3); PutS("] := ");
  1218. PutI2(startTab[4*i + j],2); PutS("; "); INC(j);
  1219. END;
  1220. INC(i);
  1221. END;
  1222. CopyFramePart("-->modulename", LeftMargin, fram, out);
  1223. PutS(gramName); Put("S");
  1224. CopyFramePart("-->definition", LeftMargin, fram, out);
  1225. FileIO.Close(scanner);
  1226. (*------- *S.DEF -------*)
  1227. IF ~ CRT.ddt["D"] THEN
  1228. FileIO.Concat(fGramName, "S", fn);
  1229. FileIO.Concat(fn, FileIO.DefExt, fn);
  1230. (* ++
  1231. FileIO.WriteLn(FileIO.StdOut);
  1232. FileIO.WriteString(FileIO.StdOut, " ");
  1233. FileIO.WriteString(FileIO.StdOut, fn);
  1234. ++ *)
  1235. FileIO.Open(scanner, fn, TRUE);
  1236. out := scanner;
  1237. CopyFramePart("-->modulename", LeftMargin, fram, out);
  1238. PutS(gramName); Put("S");
  1239. CopyFramePart("-->modulename", LeftMargin, fram, out);
  1240. PutS(gramName); Put("S");
  1241. CopyFramePart("-->implementation", LeftMargin, fram, out);
  1242. FileIO.Close(scanner);
  1243. END;
  1244. FileIO.Close(fram);
  1245. END WriteScanner;
  1246. BEGIN (* CRA *)
  1247. lastState := -1; rootState := NewState();
  1248. firstMelted := NIL; firstComment := NIL;
  1249. NewLine := TRUE;
  1250. dirtyDFA := FALSE;
  1251. END CRA.