M2comp.atg 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. COMPILER M2comp
  2. (* Step 2 — Coco/R lexer/parser + SymTab semantic analysis (no codegen).
  3. Lexer/scanner and parser are FULLY generated by Coco/R (CR):
  4. M2comp.atg --CR--> M2compS (scanner) + M2compP (parser)
  5. + M2comp (driver from compiler.frm)
  6. Static checks (SymTab): 200 duplicate, 201 undeclared, 202 name
  7. mismatch, 210 bad assignment, 211 arithmetic, 212 boolean operand,
  8. 213 comparison, 214 condition, 215 not a record, 216 unknown field,
  9. 217 not an array, 218 bad index, 219 not a pointer, 220 FOR misuse,
  10. 221 not a type, 222 set mismatch, 223 cyclical type, 224 ordinal
  11. required, 230 unsupported (EXIT outside LOOP, open array outside
  12. formal), 232 bad RETURN, 233 invalid call. 231 unused (no FORWARD).
  13. Kowarsch rules kept from step 1: local MODULEs in Wirth form,
  14. unary minus takes a Factor (3.3), abbreviated arrays (3.1),
  15. no octal B/C (2.1). "~" never added (2.2); "<>" still accepted. *)
  16. IMPORT SymTab, AST;
  17. CHARACTERS
  18. eol = CHR(13) .
  19. letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  20. digit = "0123456789" .
  21. hexDigit = digit + "ABCDEF" .
  22. noQuote1 = ANY - "'" - eol .
  23. noQuote2 = ANY - '"' - eol .
  24. IGNORE CHR(9) .. CHR(13)
  25. COMMENTS
  26. FROM "(*" TO "*)" NESTED
  27. TOKENS
  28. ident = letter { letter | digit } .
  29. integer = digit { digit }
  30. | digit { digit } CONTEXT("..")
  31. | digit { hexDigit } "H" .
  32. real = digit { digit } "." { digit }
  33. [ "E" [ "+" | "-" ] digit { digit } ] .
  34. string = "'" { noQuote1 } "'"
  35. | '"' { noQuote2 } '"' .
  36. PRODUCTIONS
  37. (* NOTE: Coco/R numbers tokens by first occurrence; M2comp.mod's Msg
  38. table is regenerated from M2comp.err on every build (via
  39. compiler.frm). After grammar edits, rebuild and check that
  40. the messages still name the right tokens. *)
  41. M2comp
  42. = Module "." .
  43. Module (. VAR m1, m2: SymTab.Name;
  44. d, bd, bs, rt: AST.Node;
  45. im: AST.Node; .)
  46. = (. SymTab.Init; d := NIL; .)
  47. "MODULE"
  48. GetIdent<m1>
  49. ";"
  50. { Import<im> (. d := AST.Append(d, im); .) }
  51. Block<bd, bs> (. d := AST.Append(d, bd);
  52. rt := AST.MkModule(m1, d,
  53. AST.MkBlock(NIL, bs));
  54. AST.SetRoot(rt); .)
  55. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  56. SemError(202) END;
  57. SymTab.PrintTable;
  58. AST.DumpTree(
  59. AST.GetRoot()); .) .
  60. Import<VAR n: AST.Node> (. VAR mod: SymTab.Name;
  61. h: AST.Node;
  62. m: SymTab.Name; .)
  63. = (. mod[0] := 0C; .)
  64. [ "FROM"
  65. GetIdent<m> (. IF ~SymTab.Enter(m,
  66. SymTab.KindImport)
  67. THEN SemError(200) END;
  68. mod := m; .) ]
  69. "IMPORT"
  70. IdentList<h>
  71. ";" (. n := AST.MkImport(mod, h); .) .
  72. IdentList<VAR h: AST.Node> (. VAR n: SymTab.Name; .)
  73. = GetIdent<n> (. IF ~SymTab.Enter(n,
  74. SymTab.KindImport)
  75. THEN SemError(200) END;
  76. h := AST.MkImpName(n); .)
  77. { ","
  78. GetIdent<n> (. IF ~SymTab.Enter(n,
  79. SymTab.KindImport)
  80. THEN SemError(200) END;
  81. h := AST.Append(h,
  82. AST.MkImpName(n)); .) } .
  83. GetIdent<VAR n: SymTab.Name>
  84. = ident (. LexName(n); .) .
  85. Block<VAR d: AST.Node; VAR s: AST.Node>
  86. (. VAR dn: AST.Node; .)
  87. = (. d := NIL; s := NIL; .)
  88. { Declaration<dn> (. d := AST.Append(d, dn); .) }
  89. [ "BEGIN"
  90. StatSeq<s> ]
  91. "END" .
  92. Declaration<VAR n: AST.Node> (. VAR cn: AST.Node; .)
  93. = "CONST" (. n := NIL; .)
  94. { ConstDecl<cn> ";" (. n := AST.Append(n, cn); .) }
  95. | "TYPE" (. n := NIL; .)
  96. { TypeDecl<cn> ";" (. n := AST.Append(n, cn); .) }
  97. | "VAR" (. n := NIL; .)
  98. { VarDecl<cn> ";" (. n := AST.Append(n, cn); .) }
  99. | ProcDecl<n>
  100. ";"
  101. | ModuleDecl<n>
  102. ";" .
  103. ConstDecl<VAR n: AST.Node> (. VAR nm: SymTab.Name;
  104. t: SymTab.TypeIndex;
  105. en: AST.Node;
  106. cv: INTEGER;
  107. ok: BOOLEAN; .)
  108. = GetIdent<nm> (. IF ~SymTab.Enter(nm,
  109. SymTab.KindConst)
  110. THEN SemError(200) END; .)
  111. "="
  112. ConstExpr<t, en> (. SymTab.SetSymType(nm, t);
  113. ok := SymTab.ConstFold(en,
  114. cv);
  115. SymTab.NoteConst(nm, cv,
  116. ok);
  117. n := AST.MkConst(nm, en,
  118. t); .) .
  119. ConstExpr<VAR t: SymTab.TypeIndex; VAR e: AST.Node>
  120. (. VAR vD: BOOLEAN; .)
  121. = Expr<t, vD, e> .
  122. TypeDecl<VAR n: AST.Node> (. VAR nm: SymTab.Name;
  123. t0, t1: SymTab.TypeIndex; .)
  124. = GetIdent<nm> (. IF ~SymTab.Enter(nm,
  125. SymTab.KindType)
  126. THEN SemError(200) END;
  127. t0 := SymTab.NewAlias();
  128. SymTab.SetSymType(nm, t0); .)
  129. "="
  130. Type<t1> (. IF t1 = t0 THEN SemError(223);
  131. SymTab.SetTarget(t0,
  132. SymTab.InvalidType)
  133. ELSE SymTab.SetTarget(t0, t1) END;
  134. n := AST.MkTypeDecl(nm,
  135. t1); .) .
  136. VarDecl<VAR n: AST.Node> (. VAR t: SymTab.TypeIndex;
  137. h: AST.Node; .)
  138. = VarIdents<h> ":"
  139. Type<t> (. IF SymTab.IsOpen(t) THEN
  140. SemError(230) END;
  141. AST.SetChainType(h, t);
  142. SymTab.FixPending(t);
  143. n := h; .) .
  144. VarIdents<VAR h: AST.Node> (. VAR nm: SymTab.Name; .)
  145. = GetIdent<nm> (. IF ~SymTab.EnterPending(nm,
  146. SymTab.KindVar)
  147. THEN SemError(200) END;
  148. h := AST.MkVar(nm,
  149. SymTab.InvalidType); .)
  150. { ","
  151. GetIdent<nm> (. IF ~SymTab.EnterPending(nm,
  152. SymTab.KindVar)
  153. THEN SemError(200) END;
  154. h := AST.Append(h,
  155. AST.MkVar(nm,
  156. SymTab.InvalidType)); .) } .
  157. ProcDecl<VAR n: AST.Node> (. VAR m1, m2: SymTab.Name;
  158. rt, ret: SymTab.TypeIndex;
  159. p, bd, bs: AST.Node;
  160. pn: INTEGER; .)
  161. = (. ret := SymTab.InvalidType;
  162. p := NIL; .)
  163. "PROCEDURE"
  164. GetIdent<m1> (. IF ~SymTab.EnterProc(m1) THEN
  165. SemError(200) END;
  166. pn := SymTab.ProcNum(m1);
  167. SymTab.OpenProcScope; .)
  168. [ FormalParams<p> ]
  169. [ ":"
  170. QualIdent<rt> (. ret := rt;
  171. SymTab.SetProcRet(rt);
  172. IF (rt #
  173. SymTab.InvalidType)
  174. & ((SymTab.ClassOf(rt) =
  175. SymTab.ClArray)
  176. OR (SymTab.ClassOf(
  177. rt) =
  178. SymTab.ClRecord)) THEN
  179. SemError(230) END; .) ]
  180. ";"
  181. Block<bd, bs> (. n := AST.MkProc(m1, ret, p,
  182. AST.MkBlock(bd, bs));
  183. n^.num := pn; .)
  184. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  185. SemError(202) END;
  186. SymTab.CloseProc; .) .
  187. FormalParams<VAR p: AST.Node> (. VAR ps: AST.Node; .)
  188. = "(" (. p := NIL; .)
  189. [ FPSection<ps> (. p := AST.Append(p, ps); .)
  190. { ";" FPSection<ps> (. p := AST.Append(p, ps); .) } ]
  191. ")" .
  192. FPSection<VAR p: AST.Node> (. VAR isV: BOOLEAN;
  193. t: SymTab.TypeIndex; .)
  194. = (. isV := FALSE; .)
  195. [ "VAR" (. isV := TRUE; .) ]
  196. FPIdents<isV, p> ":"
  197. Type<t> (. IF SymTab.IsOpen(t) & ~isV THEN
  198. SemError(230)
  199. ELSIF ~isV
  200. & (t #
  201. SymTab.InvalidType)
  202. & ((SymTab.ClassOf(t) =
  203. SymTab.ClArray)
  204. OR (SymTab.ClassOf(t) =
  205. SymTab.ClRecord)) THEN
  206. SemError(230) END;
  207. AST.SetChainType(p, t);
  208. IF ~SymTab.FixParamPending(t) THEN
  209. SemError(200) END; .) .
  210. FPIdents<isV: BOOLEAN; VAR p: AST.Node>
  211. (. VAR n: SymTab.Name; .)
  212. = GetIdent<n> (. IF ~SymTab.EnterParamPending(n,
  213. isV) THEN
  214. SemError(200) END;
  215. p := AST.MkParam(n,
  216. SymTab.InvalidType,
  217. isV); .)
  218. { ","
  219. GetIdent<n> (. IF ~SymTab.EnterParamPending(n,
  220. isV) THEN
  221. SemError(200) END;
  222. p := AST.Append(p,
  223. AST.MkParam(n,
  224. SymTab.InvalidType,
  225. isV)); .) } .
  226. ModuleDecl<VAR n: AST.Node> (. VAR m1, m2: SymTab.Name;
  227. d, bd, bs: AST.Node;
  228. im, en: AST.Node; .)
  229. = "MODULE" (* local module, Wirth form *)
  230. (. d := NIL; .)
  231. GetIdent<m1> (. IF ~SymTab.EnterModule(m1) THEN
  232. SemError(200) END; .)
  233. [ Priority ]
  234. ";"
  235. { Import<im> (. d := AST.Append(d, im); .) }
  236. [ Export<en> (. d := AST.Append(d, en); .) ]
  237. Block<bd, bs> (. d := AST.Append(d, bd);
  238. n := AST.MkModule(m1, d,
  239. AST.MkBlock(NIL, bs)); .)
  240. GetIdent<m2> (. IF ~SymTab.Equal(m1, m2) THEN
  241. SemError(202) END;
  242. IF ~SymTab.ExitModule() THEN
  243. SemError(201) END; .) .
  244. Priority (. VAR t: SymTab.TypeIndex;
  245. vD: BOOLEAN;
  246. en: AST.Node; .)
  247. = "["
  248. Expr<t, vD, en>
  249. "]" .
  250. Export<VAR n: AST.Node> (. VAR nm: SymTab.Name;
  251. h: AST.Node; .)
  252. = "EXPORT"
  253. [ "QUALIFIED" ]
  254. GetIdent<nm> (. IF ~SymTab.ModuleAddExp(nm) THEN
  255. SemError(200) END;
  256. h := AST.MkImpName(nm); .)
  257. { ","
  258. GetIdent<nm> (. IF ~SymTab.ModuleAddExp(nm) THEN
  259. SemError(200) END;
  260. h := AST.Append(h,
  261. AST.MkImpName(nm)); .) }
  262. ";" (. n := AST.MkExport(h); .) .
  263. Type<VAR t: SymTab.TypeIndex>
  264. (. VAR c: CARDINAL;
  265. e, s: SymTab.TypeIndex;
  266. los, his: SymTab.BoundsArr;
  267. fh: AST.Node;
  268. i: CARDINAL; .)
  269. = BoundedBase<t>
  270. | "ARRAY" (* abbreviated form only (3.1);
  271. nested ARRAY OF ARRAY long form
  272. flagged in step 4 sizing *)
  273. (. c := 0; i := 0;
  274. WHILE i <= 7 DO
  275. los[i] := 0;
  276. his[i] := -1;
  277. INC(i)
  278. END; .)
  279. [ IdxList<c, los, his> ]
  280. "OF"
  281. Type<e> (. t := SymTab.WrapArrayB(e, los,
  282. his, c); .)
  283. | "RECORD" (. t := SymTab.NewRecord(); .)
  284. FieldSeq<t, fh>
  285. "END"
  286. | "SET"
  287. "OF"
  288. QualIdent<s> (. IF (s # SymTab.InvalidType)
  289. & (SymTab.ClassOf(s) #
  290. SymTab.ClInt)
  291. & (SymTab.ClassOf(s) #
  292. SymTab.ClChar)
  293. & (SymTab.ClassOf(s) #
  294. SymTab.ClEnum) THEN
  295. SemError(224) END;
  296. t := SymTab.NewSet(s); .)
  297. | "POINTER"
  298. "TO"
  299. Type<e> (. t := SymTab.NewPtr(e); .) .
  300. BoundedBase<VAR t: SymTab.TypeIndex>
  301. (. VAR t1, t2: SymTab.TypeIndex;
  302. vD, vD2: BOOLEAN;
  303. en, en2: AST.Node;
  304. lo, hi: INTEGER; .)
  305. = QualIdent<t>
  306. [ "["
  307. Expr<t1, vD, en> (. IF (t1 # SymTab.InvalidType)
  308. & (SymTab.ClassOf(t1) #
  309. SymTab.ClInt)
  310. & (SymTab.ClassOf(t1) #
  311. SymTab.ClChar)
  312. & (SymTab.ClassOf(t1) #
  313. SymTab.ClEnum) THEN
  314. SemError(224) END; .)
  315. ".."
  316. Expr<t2, vD2, en2> (. IF (t2 # SymTab.InvalidType)
  317. & (SymTab.ClassOf(t2) #
  318. SymTab.ClInt)
  319. & (SymTab.ClassOf(t2) #
  320. SymTab.ClChar)
  321. & (SymTab.ClassOf(t2) #
  322. SymTab.ClEnum) THEN
  323. SemError(224) END;
  324. IF (t1 = SymTab.InvalidType)
  325. OR (t2 =
  326. SymTab.InvalidType) THEN
  327. t := SymTab.NewSub(t1)
  328. ELSIF SymTab.ConstFold(en,
  329. lo)
  330. & SymTab.ConstFold(en2,
  331. hi) THEN
  332. t := SymTab.NewSubB(t1,
  333. lo, hi)
  334. ELSE
  335. SemError(230);
  336. t := SymTab.NewSub(t1)
  337. END; .)
  338. "]" ]
  339. | "["
  340. Expr<t1, vD, en> (. IF (t1 # SymTab.InvalidType)
  341. & (SymTab.ClassOf(t1) #
  342. SymTab.ClInt)
  343. & (SymTab.ClassOf(t1) #
  344. SymTab.ClChar)
  345. & (SymTab.ClassOf(t1) #
  346. SymTab.ClEnum) THEN
  347. SemError(224) END; .)
  348. ".."
  349. Expr<t2, vD2, en2> (. IF (t2 # SymTab.InvalidType)
  350. & (SymTab.ClassOf(t2) #
  351. SymTab.ClInt)
  352. & (SymTab.ClassOf(t2) #
  353. SymTab.ClChar)
  354. & (SymTab.ClassOf(t2) #
  355. SymTab.ClEnum) THEN
  356. SemError(224) END;
  357. IF (t1 = SymTab.InvalidType)
  358. OR (t2 =
  359. SymTab.InvalidType) THEN
  360. t := SymTab.NewSub(t1)
  361. ELSIF SymTab.ConstFold(en,
  362. lo)
  363. & SymTab.ConstFold(en2,
  364. hi) THEN
  365. t := SymTab.NewSubB(t1,
  366. lo, hi)
  367. ELSE
  368. SemError(230);
  369. t := SymTab.NewSub(t1)
  370. END; .)
  371. "]" .
  372. IdxList<VAR c: CARDINAL; VAR los, his: SymTab.BoundsArr>
  373. (. VAR s: SymTab.TypeIndex;
  374. lo, hi: INTEGER;
  375. ok: BOOLEAN; .)
  376. = IndexType<s, lo, hi, ok> (. c := 1;
  377. los[0] := lo; his[0] := hi; .)
  378. { "," IndexType<s, lo, hi, ok> (. IF c <= 7 THEN
  379. los[c] := lo;
  380. his[c] := hi
  381. END;
  382. INC(c); .) } .
  383. IndexType<VAR t: SymTab.TypeIndex; VAR lo, hi: INTEGER;
  384. VAR ok: BOOLEAN> (. VAR t1, t2: SymTab.TypeIndex;
  385. vD, vD2: BOOLEAN;
  386. en, en2: AST.Node;
  387. l2, h2: INTEGER; .)
  388. = QualIdent<t> (. ok := SymTab.IndexBounds(t,
  389. lo, hi); .)
  390. [ "["
  391. Expr<t1, vD, en> (. IF (t1 # SymTab.InvalidType)
  392. & (SymTab.ClassOf(t1) #
  393. SymTab.ClInt)
  394. & (SymTab.ClassOf(t1) #
  395. SymTab.ClChar)
  396. & (SymTab.ClassOf(t1) #
  397. SymTab.ClEnum) THEN
  398. SemError(224) END; .)
  399. ".."
  400. Expr<t2, vD2, en2> (. IF (t2 # SymTab.InvalidType)
  401. & (SymTab.ClassOf(t2) #
  402. SymTab.ClInt)
  403. & (SymTab.ClassOf(t2) #
  404. SymTab.ClChar)
  405. & (SymTab.ClassOf(t2) #
  406. SymTab.ClEnum) THEN
  407. SemError(224) END;
  408. IF (t1 = SymTab.InvalidType)
  409. OR (t2 =
  410. SymTab.InvalidType) THEN
  411. t := SymTab.NewSub(t1)
  412. ELSIF SymTab.ConstFold(en,
  413. l2)
  414. & SymTab.ConstFold(en2,
  415. h2) THEN
  416. t := SymTab.NewSubB(t1,
  417. l2, h2);
  418. lo := l2; hi := h2;
  419. ok := TRUE
  420. ELSE
  421. t := SymTab.NewSub(t1);
  422. ok := FALSE
  423. END; .)
  424. "]" ]
  425. (. IF (t # SymTab.InvalidType)
  426. & ~ok THEN
  427. SemError(230) END; .)
  428. | "["
  429. Expr<t1, vD, en> (. IF (t1 # SymTab.InvalidType)
  430. & (SymTab.ClassOf(t1) #
  431. SymTab.ClInt)
  432. & (SymTab.ClassOf(t1) #
  433. SymTab.ClChar)
  434. & (SymTab.ClassOf(t1) #
  435. SymTab.ClEnum) THEN
  436. SemError(224) END;
  437. ok := FALSE; .)
  438. ".."
  439. Expr<t2, vD2, en2> (. IF (t2 # SymTab.InvalidType)
  440. & (SymTab.ClassOf(t2) #
  441. SymTab.ClInt)
  442. & (SymTab.ClassOf(t2) #
  443. SymTab.ClChar)
  444. & (SymTab.ClassOf(t2) #
  445. SymTab.ClEnum) THEN
  446. SemError(224) END;
  447. IF (t1 = SymTab.InvalidType)
  448. OR (t2 =
  449. SymTab.InvalidType) THEN
  450. t := SymTab.NewSub(t1)
  451. ELSIF SymTab.ConstFold(en,
  452. lo)
  453. & SymTab.ConstFold(en2,
  454. hi) THEN
  455. t := SymTab.NewSubB(t1,
  456. lo, hi);
  457. ok := TRUE
  458. ELSE
  459. SemError(230);
  460. t := SymTab.NewSub(t1)
  461. END; .)
  462. "]" .
  463. FieldSeq<rt: SymTab.TypeIndex; VAR h: AST.Node>
  464. (. VAR fn: AST.Node; .)
  465. = Field<rt, fn> (. h := fn; .)
  466. { ";"
  467. Field<rt, fn> (. h := AST.Append(h, fn); .) } .
  468. Field<rt: SymTab.TypeIndex; VAR n: AST.Node>
  469. (. VAR et: SymTab.TypeIndex;
  470. h: AST.Node; .)
  471. = (. n := NIL; .)
  472. [ FieldIdents<rt, h> ":"
  473. Type<et> (. AST.SetChainType(h, et);
  474. SymTab.FixPendingF(rt, et);
  475. n := h; .) ] .
  476. FieldIdents<rt: SymTab.TypeIndex; VAR h: AST.Node>
  477. (. VAR nm: SymTab.Name; .)
  478. = GetIdent<nm> (. IF ~SymTab.FieldPending(rt, nm)
  479. THEN SemError(200) END;
  480. h := AST.MkMember(nm,
  481. SymTab.InvalidType); .)
  482. { ","
  483. GetIdent<nm> (. IF ~SymTab.FieldPending(rt, nm)
  484. THEN SemError(200) END;
  485. h := AST.Append(h,
  486. AST.MkMember(nm,
  487. SymTab.InvalidType)); .) } .
  488. QualIdent<VAR t: SymTab.TypeIndex>
  489. (. VAR n, m: SymTab.Name;
  490. modHead: BOOLEAN; .)
  491. = (. modHead := FALSE; .)
  492. GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  493. SemError(201);
  494. t := SymTab.InvalidType
  495. ELSIF SymTab.SymKind(n)
  496. = SymTab.KindModule THEN
  497. t := SymTab.InvalidType;
  498. modHead := TRUE
  499. ELSIF (SymTab.SymKind(n) #
  500. SymTab.KindType)
  501. & (SymTab.SymKind(n) #
  502. SymTab.KindPredef)
  503. & (SymTab.SymKind(n) #
  504. SymTab.KindImport) THEN
  505. SemError(221);
  506. t := SymTab.InvalidType
  507. ELSE t := SymTab.SymType(n) END; .)
  508. { "."
  509. GetIdent<m> (. IF modHead THEN
  510. modHead := FALSE;
  511. IF SymTab.ExpKind(n, m)
  512. = SymTab.KindType THEN
  513. t := SymTab.ExpType(n, m)
  514. ELSIF SymTab.SelfKind(n, m)
  515. = SymTab.KindType THEN
  516. t := SymTab.SelfType(n, m)
  517. ELSE
  518. IF SymTab.ExpKind(n, m) < 0 THEN
  519. IF SymTab.SelfKind(n, m)
  520. < 0 THEN
  521. SemError(201)
  522. ELSE SemError(221)
  523. END
  524. ELSE SemError(221)
  525. END;
  526. t := SymTab.InvalidType
  527. END
  528. ELSIF t #
  529. SymTab.InvalidType THEN
  530. SemError(221);
  531. t := SymTab.InvalidType
  532. END; .) } .
  533. StatSeq<VAR s: AST.Node> (. VAR st: AST.Node; .)
  534. = Stat<st> (. s := st; .)
  535. { ";"
  536. Stat<st> (. s := AST.Append(s, st); .) } .
  537. Stat<VAR s: AST.Node>
  538. = (. s := NIL; .)
  539. [ AssignOrCall<s>
  540. | IfStat<s>
  541. | WhileStat<s>
  542. | RepeatStat<s>
  543. | LoopStat<s>
  544. | ForStat<s>
  545. | ReturnStat<s>
  546. | "EXIT" (. IF ~SymTab.InLoop() THEN
  547. SemError(230) END;
  548. s := AST.MkExit(); .) ] .
  549. AssignOrCall<VAR s: AST.Node> (. VAR dt, et: SymTab.TypeIndex;
  550. dk, pn: INTEGER;
  551. ev: BOOLEAN;
  552. nn: CARDINAL;
  553. hadP: BOOLEAN;
  554. dn, en, ah: AST.Node; .)
  555. = Designator<dt, dk, pn, dn>
  556. ( ":="
  557. Expr<et, ev, en> (. IF dt = SymTab.InvalidType THEN
  558. (* cascade *)
  559. ELSIF (dk # SymTab.KindVar)
  560. & (dk # SymTab.KindParam)
  561. & (dk # SymTab.KindVarPar)
  562. & (dk # SymTab.KindField) THEN
  563. SemError(210)
  564. ELSIF ~SymTab.Assignable(et,
  565. dt) THEN
  566. SemError(210) END;
  567. s := AST.MkAssign(dn, en); .)
  568. | (. hadP := FALSE; nn := 0;
  569. ah := NIL;
  570. IF dk = SymTab.KindProc THEN
  571. SymTab.CallBeginNum(pn)
  572. ELSE
  573. SymTab.CallBeginNum(-1)
  574. END;
  575. IF (dk # SymTab.KindProc)
  576. & (dk # -1) THEN
  577. SemError(233) END; .)
  578. [ ActParams<ah, nn> (. hadP := TRUE; .) ]
  579. (. IF ~SymTab.CallEndNum(nn) THEN
  580. SemError(233) END;
  581. s := AST.MkCall(dn, ah, pn); .) ) .
  582. Designator<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  583. VAR pn: INTEGER; VAR dn: AST.Node>
  584. (. VAR n, m: SymTab.Name;
  585. it, it2: SymTab.TypeIndex;
  586. iv, iv2: BOOLEAN;
  587. ek, sk, p2: INTEGER;
  588. modHead, wasMod: BOOLEAN;
  589. en, en2, ih: AST.Node; .)
  590. = GetIdent<n> (. modHead := FALSE;
  591. IF ~SymTab.Lookup(n) THEN
  592. SemError(201);
  593. t := SymTab.InvalidType;
  594. k := -1; pn := -1
  595. ELSIF SymTab.SymKind(n)
  596. = SymTab.KindModule THEN
  597. t := SymTab.InvalidType;
  598. k := SymTab.KindModule;
  599. pn := -1; modHead := TRUE
  600. ELSE
  601. t := SymTab.SymType(n);
  602. k := SymTab.SymKind(n);
  603. IF k = SymTab.KindProc THEN
  604. pn := SymTab.ProcNum(n)
  605. ELSE pn := -1
  606. END
  607. END;
  608. dn := AST.MkName(n, t);
  609. dn^.aux := k; .)
  610. { "." GetIdent<m> (. wasMod := modHead;
  611. IF modHead THEN
  612. modHead := FALSE;
  613. ek := SymTab.ExpKind(n, m);
  614. sk := SymTab.SelfKind(n, m);
  615. IF ek = SymTab.KindType THEN
  616. t := SymTab.ExpType(n,
  617. m);
  618. k := SymTab.KindType
  619. ELSIF sk =
  620. SymTab.KindType THEN
  621. t := SymTab.SelfType(n,
  622. m);
  623. k := SymTab.KindType
  624. ELSIF ek =
  625. SymTab.KindProc THEN
  626. t := SymTab.ProcRetByNum(
  627. SymTab.ExpProc(
  628. n, m));
  629. k := SymTab.KindProc;
  630. pn := SymTab.ExpProc(
  631. n, m)
  632. ELSIF sk =
  633. SymTab.KindProc THEN
  634. p2 := SymTab.SelfProc(
  635. n, m);
  636. t := SymTab.ProcRetByNum(
  637. p2);
  638. k := SymTab.KindProc;
  639. pn := p2
  640. ELSIF ek >= 0 THEN
  641. t := SymTab.ExpType(n,
  642. m);
  643. k := ek; pn := -1
  644. ELSIF sk >= 0 THEN
  645. t := SymTab.SelfType(n,
  646. m);
  647. k := sk; pn := -1
  648. ELSE
  649. SemError(201);
  650. t := SymTab.InvalidType;
  651. k := -1; pn := -1
  652. END
  653. ELSIF t =
  654. SymTab.InvalidType THEN
  655. (* cascade *)
  656. ELSIF SymTab.ClassOf(t) #
  657. SymTab.ClRecord THEN
  658. SemError(215);
  659. t := SymTab.InvalidType;
  660. k := -1; pn := -1
  661. ELSIF ~SymTab.FieldExists(t,
  662. m) THEN
  663. SemError(216);
  664. t := SymTab.InvalidType;
  665. k := -1; pn := -1
  666. ELSE
  667. t := SymTab.FieldType(t,
  668. m);
  669. k := SymTab.KindField;
  670. pn := -1
  671. END;
  672. dn := AST.MkField(dn, m, t);
  673. dn^.aux := k;
  674. IF wasMod THEN
  675. dn^.tag := n
  676. END; .)
  677. | "[" Expr<it, iv, en> (. IF t = SymTab.InvalidType THEN
  678. (* cascade *)
  679. ELSIF SymTab.ClassOf(t) #
  680. SymTab.ClArray THEN
  681. SemError(217);
  682. t := SymTab.InvalidType;
  683. k := -1; pn := -1
  684. ELSIF (it #
  685. SymTab.InvalidType)
  686. & ~SymTab.IsIntFamily(
  687. it) THEN
  688. SemError(218);
  689. t := SymTab.InvalidType;
  690. k := -1; pn := -1
  691. ELSE t := SymTab.ArrayElem(
  692. t);
  693. pn := -1
  694. END;
  695. ih := en; .)
  696. { "," Expr<it2, iv2, en2> (. IF t = SymTab.InvalidType THEN
  697. (* cascade *)
  698. ELSIF SymTab.ClassOf(t) #
  699. SymTab.ClArray THEN
  700. SemError(217);
  701. t := SymTab.InvalidType;
  702. k := -1; pn := -1
  703. ELSIF (it2 #
  704. SymTab.InvalidType)
  705. & ~SymTab.IsIntFamily(
  706. it2) THEN
  707. SemError(218)
  708. ELSE t := SymTab.ArrayElem(
  709. t) END;
  710. ih := AST.Append(ih, en2); .) }
  711. "]" (. dn := AST.MkIndex(dn, ih,
  712. t);
  713. dn^.aux := k; .)
  714. | "^" (. IF t = SymTab.InvalidType THEN
  715. (* cascade *)
  716. ELSIF SymTab.ClassOf(t) #
  717. SymTab.ClPtr THEN
  718. SemError(219);
  719. t := SymTab.InvalidType;
  720. k := -1; pn := -1
  721. ELSE t := SymTab.PtrBase(t);
  722. pn := -1
  723. END;
  724. dn := AST.MkDeref(dn, t);
  725. dn^.aux := k; .) } .
  726. ActParams<VAR h: AST.Node; VAR n: CARDINAL>
  727. (. VAR at: SymTab.TypeIndex;
  728. av: BOOLEAN;
  729. ae: AST.Node; .)
  730. = "(" (. h := NIL; n := 0; .)
  731. [ Expr<at, av, ae> (. IF ~SymTab.CallActual(at,
  732. av) THEN
  733. SemError(233) END;
  734. h := AST.Append(h, ae);
  735. n := 1; .)
  736. { "," Expr<at, av, ae> (. IF ~SymTab.CallActual(at,
  737. av) THEN
  738. SemError(233) END;
  739. h := AST.Append(h, ae);
  740. INC(n); .) } ]
  741. ")" .
  742. IfStat<VAR s: AST.Node> (. VAR t: SymTab.TypeIndex;
  743. vD: BOOLEAN;
  744. cn, th, el, p: AST.Node; .)
  745. = "IF"
  746. Expr<t, vD, cn> (. IF ~SymTab.BoolCheck(t) THEN
  747. SemError(214) END; .)
  748. "THEN"
  749. StatSeq<th> (. s := AST.MkIf(cn, th, NIL); .)
  750. { "ELSIF"
  751. Expr<t, vD, cn> (. IF ~SymTab.BoolCheck(t) THEN
  752. SemError(214) END; .)
  753. "THEN"
  754. StatSeq<th> (. th := AST.MkIf(cn, th, NIL);
  755. p := s;
  756. WHILE p^.extra # NIL DO
  757. p := p^.extra
  758. END;
  759. p^.extra := th; .) }
  760. [ "ELSE"
  761. StatSeq<el> (. p := s;
  762. WHILE p^.extra # NIL DO
  763. p := p^.extra
  764. END;
  765. p^.extra := el; .) ]
  766. "END" .
  767. WhileStat<VAR s: AST.Node> (. VAR t: SymTab.TypeIndex;
  768. vD: BOOLEAN;
  769. cn, bd: AST.Node; .)
  770. = "WHILE"
  771. Expr<t, vD, cn> (. IF ~SymTab.BoolCheck(t) THEN
  772. SemError(214) END; .)
  773. "DO"
  774. StatSeq<bd> (. s := AST.MkWhile(cn, bd); .)
  775. "END" .
  776. RepeatStat<VAR s: AST.Node> (. VAR t: SymTab.TypeIndex;
  777. vD: BOOLEAN;
  778. cn, bd: AST.Node; .)
  779. = "REPEAT"
  780. StatSeq<bd>
  781. "UNTIL"
  782. Expr<t, vD, cn> (. IF ~SymTab.BoolCheck(t) THEN
  783. SemError(214) END;
  784. s := AST.MkRepeat(bd, cn); .) .
  785. LoopStat<VAR s: AST.Node> (. VAR bd: AST.Node; .)
  786. = "LOOP" (. SymTab.LoopEnter; .)
  787. StatSeq<bd>
  788. "END" (. SymTab.LoopExit;
  789. s := AST.MkLoop(bd); .) .
  790. ForStat<VAR s: AST.Node> (. VAR n: SymTab.Name;
  791. lo, hi, by: SymTab.TypeIndex;
  792. lv, lv2, lv3: BOOLEAN;
  793. ln, hn, bn, bd: AST.Node; .)
  794. = "FOR"
  795. GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  796. SemError(201)
  797. ELSIF (SymTab.SymKind(n) #
  798. SymTab.KindVar)
  799. & (SymTab.SymKind(n) #
  800. SymTab.KindParam)
  801. & (SymTab.SymKind(n) #
  802. SymTab.KindVarPar)
  803. & (SymTab.SymKind(n) #
  804. SymTab.KindField) THEN
  805. SemError(220)
  806. ELSIF (SymTab.SymType(n) #
  807. SymTab.InvalidType)
  808. & ~SymTab.IsIntFamily(
  809. SymTab.SymType(n)) THEN
  810. SemError(220) END; .)
  811. ":="
  812. Expr<lo, lv, ln> (. IF (lo # SymTab.InvalidType)
  813. & ~SymTab.IsIntFamily(lo) THEN
  814. SemError(220) END; .)
  815. "TO"
  816. Expr<hi, lv2, hn> (. IF (hi # SymTab.InvalidType)
  817. & ~SymTab.IsIntFamily(hi) THEN
  818. SemError(220) END;
  819. bn := NIL; .)
  820. [ "BY"
  821. Expr<by, lv3, bn> (. IF (by # SymTab.InvalidType)
  822. & ~SymTab.IsIntFamily(by) THEN
  823. SemError(220) END; .) ]
  824. "DO"
  825. StatSeq<bd> (. s := AST.MkFor(n, ln, hn, bn,
  826. bd); .)
  827. "END" .
  828. ReturnStat<VAR s: AST.Node> (. VAR et: SymTab.TypeIndex;
  829. ev, hasE: BOOLEAN;
  830. en, e0: AST.Node; .)
  831. = (. hasE := FALSE; e0 := NIL; .)
  832. "RETURN"
  833. [ Expr<et, ev, en> (. hasE := TRUE; e0 := en; .) ]
  834. (. IF ~SymTab.InProc() THEN SemError(232)
  835. ELSIF SymTab.InFunction() & ~hasE THEN SemError(232)
  836. ELSIF ~SymTab.InFunction() & hasE THEN
  837. SemError(232) END;
  838. s := AST.MkReturn(e0); .) .
  839. Expr<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
  840. VAR e: AST.Node>
  841. (. VAR t2: SymTab.TypeIndex;
  842. v2: BOOLEAN;
  843. op: INTEGER;
  844. e2: AST.Node; .)
  845. = SimExpr<t, v, e>
  846. [ Relation<op> SimExpr<t2, v2, e2>
  847. (. v := FALSE;
  848. IF op = SymTab.OpIn THEN
  849. IF SymTab.InCheck(t, t2) THEN
  850. t := SymTab.BoolType()
  851. ELSE SemError(222); t := SymTab.InvalidType END
  852. ELSE
  853. IF SymTab.RelCheck(t, t2, op) THEN
  854. t := SymTab.BoolType()
  855. ELSE SemError(213); t := SymTab.InvalidType END
  856. END;
  857. e := AST.MkBin(op, e, e2, t); .) ] .
  858. Relation<VAR op: INTEGER>
  859. = "=" (. op := SymTab.OpEq; .)
  860. | "#" (. op := SymTab.OpNeq1; .)
  861. | "<>" (. op := SymTab.OpNeq2; .)
  862. | "<" (. op := SymTab.OpLt; .)
  863. | "<=" (. op := SymTab.OpLe; .)
  864. | ">" (. op := SymTab.OpGt; .)
  865. | ">=" (. op := SymTab.OpGe; .)
  866. | "IN" (. op := SymTab.OpIn; .) .
  867. SimExpr<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
  868. VAR e: AST.Node>
  869. (. VAR t2, res2: SymTab.TypeIndex;
  870. v2: BOOLEAN;
  871. op: INTEGER;
  872. e2: AST.Node; .)
  873. = ( "+" Term<t, v, e> (. IF ~SymTab.UnaryCheck(t,
  874. res2) THEN
  875. SemError(211);
  876. t := SymTab.InvalidType
  877. ELSE t := res2 END;
  878. v := FALSE;
  879. e := AST.MkUn(AST.opPos,
  880. e, t); .)
  881. | "-" Fact<t, v, e> (. IF ~SymTab.UnaryCheck(t,
  882. res2) THEN
  883. SemError(211);
  884. t := SymTab.InvalidType
  885. ELSE t := res2 END;
  886. v := FALSE;
  887. e := AST.MkUn(AST.opNeg,
  888. e, t); .)
  889. | Term<t, v, e> )
  890. { AddOp<op> Term<t2, v2, e2>
  891. (. v := FALSE;
  892. IF op = SymTab.OpOr THEN
  893. IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
  894. t := SymTab.BoolType()
  895. ELSE SemError(212); t := SymTab.InvalidType END
  896. ELSE
  897. IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
  898. t := res2
  899. ELSE SemError(211); t := SymTab.InvalidType END
  900. END;
  901. e := AST.MkBin(op, e, e2, t); .) } .
  902. AddOp<VAR op: INTEGER>
  903. = "+" (. op := SymTab.OpAdd; .)
  904. | "-" (. op := SymTab.OpSub; .)
  905. | "OR" (. op := SymTab.OpOr; .) .
  906. Term<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
  907. VAR e: AST.Node>
  908. (. VAR t2, res2: SymTab.TypeIndex;
  909. v2: BOOLEAN;
  910. op: INTEGER;
  911. e2: AST.Node; .)
  912. = Fact<t, v, e>
  913. { MulOp<op> Fact<t2, v2, e2>
  914. (. v := FALSE;
  915. IF op = SymTab.OpAnd THEN
  916. IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
  917. t := SymTab.BoolType()
  918. ELSE SemError(212); t := SymTab.InvalidType END
  919. ELSE
  920. IF SymTab.ArithCheck(t, t2,
  921. (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  922. res2) THEN t := res2
  923. ELSE SemError(211); t := SymTab.InvalidType END
  924. END;
  925. e := AST.MkBin(op, e, e2, t); .) } .
  926. MulOp<VAR op: INTEGER>
  927. = "*" (. op := SymTab.OpTimes; .)
  928. | "/" (. op := SymTab.OpSlash; .)
  929. | "DIV" (. op := SymTab.OpDiv; .)
  930. | "MOD" (. op := SymTab.OpMod; .)
  931. | "AND" (. op := SymTab.OpAnd; .) .
  932. Fact<VAR t: SymTab.TypeIndex; VAR v: BOOLEAN;
  933. VAR e: AST.Node>
  934. (. VAR s: ARRAY [0 .. 255] OF CHAR;
  935. t2, et, dt: SymTab.TypeIndex;
  936. dk, pn: INTEGER;
  937. nn: CARDINAL;
  938. hadP, ce, pushed: BOOLEAN;
  939. ev, v2: BOOLEAN;
  940. dn, ah, en: AST.Node;
  941. iv: INTEGER;
  942. ok: BOOLEAN; .)
  943. = integer (. LexString(s);
  944. t := SymTab.IntType();
  945. v := FALSE;
  946. ok := AST.ParseInt(s, iv);
  947. IF ~ok THEN iv := 0 END;
  948. e := AST.MkInt(iv, t); .)
  949. | real (. LexString(s);
  950. t := SymTab.RealType();
  951. v := FALSE;
  952. e := AST.MkReal(s, t); .)
  953. | string (. LexString(s);
  954. IF SymTab.StrLen(s) <= 3 THEN
  955. t := SymTab.CharType();
  956. e := AST.MkChar(
  957. ORD(s[1]), t)
  958. ELSE t := SymTab.NewStr();
  959. e := AST.MkStr(s, t)
  960. END;
  961. v := FALSE; .)
  962. | Designator<dt, dk, pn, dn> (. hadP := FALSE; nn := 0;
  963. IF dk = SymTab.KindProc THEN
  964. SymTab.CallBeginNum(pn);
  965. pushed := TRUE
  966. ELSE pushed := FALSE
  967. END; .)
  968. [ (. IF ~pushed THEN
  969. SymTab.CallBeginNum(-1);
  970. pushed := TRUE
  971. END; .)
  972. ActParams<ah, nn> (. hadP := TRUE; .) ]
  973. (. IF pushed THEN
  974. ce := SymTab.CallEndNum(nn)
  975. END;
  976. IF hadP THEN
  977. v := FALSE;
  978. IF dk # SymTab.KindProc THEN
  979. SemError(233);
  980. t := SymTab.InvalidType
  981. ELSIF SymTab.ProcRetByNum(
  982. pn) =
  983. SymTab.InvalidType THEN
  984. SemError(233);
  985. t := SymTab.InvalidType
  986. ELSIF ~ce THEN
  987. SemError(233);
  988. t := SymTab.InvalidType
  989. ELSE t :=
  990. SymTab.ProcRetByNum(pn)
  991. END;
  992. e := AST.MkCallExpr(dn, ah,
  993. pn, t)
  994. ELSE
  995. IF dk = SymTab.KindProc THEN
  996. SemError(233);
  997. t := SymTab.InvalidType;
  998. v := FALSE;
  999. e := AST.MkName("?", t)
  1000. ELSE
  1001. t := dt;
  1002. v := (dt #
  1003. SymTab.InvalidType)
  1004. & ((dk =
  1005. SymTab.KindVar)
  1006. OR (dk =
  1007. SymTab.KindParam)
  1008. OR (dk =
  1009. SymTab.KindVarPar)
  1010. OR (dk =
  1011. SymTab.KindField));
  1012. e := dn
  1013. END
  1014. END; .)
  1015. | "(" Expr<et, ev, en> ")" (. t := et; v := FALSE;
  1016. e := en; .)
  1017. | "NOT" Fact<t2, v2, en> (. IF SymTab.BoolCheck(t2) THEN
  1018. t := SymTab.BoolType()
  1019. ELSE SemError(212);
  1020. t := SymTab.InvalidType END;
  1021. v := FALSE;
  1022. e := AST.MkUn(AST.opNot, en,
  1023. t); .) .
  1024. END M2comp.