SimpleMod2.atg 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. COMPILER SimpleMod2
  2. (* Simplified Modula-2 without PROCEDURE / FUNCTION
  3. - program module only, no DEFINITION / IMPLEMENTATION split
  4. - no local modules, no EXPORT, no PRIORITY
  5. - no ProcedureDeclaration, FormalParameters, ProcedureType,
  6. ProcedureCall, ActualParameters, FORWARD, RETURN
  7. - statements: assignment, IF, CASE, WHILE, REPEAT, LOOP/EXIT, FOR, WITH
  8. - symbol table (SymTab) with static type checking:
  9. 200 = duplicate identifier, 201 = undeclared identifier,
  10. 202 = MODULE / END name mismatch,
  11. 210 = incompatible assignment (incl. assignment to a constant),
  12. 211 = arithmetic operand must be numeric,
  13. 212 = boolean operand required,
  14. 213 = incompatible comparison / CASE label mismatch,
  15. 214 = BOOLEAN condition required,
  16. 215 = not a RECORD type, 216 = unknown field,
  17. 217 = not an ARRAY type, 218 = array index must be integer,
  18. 219 = not a POINTER type,
  19. 220 = FOR needs integer variable and bounds,
  20. 221 = not a type name, 222 = set operand mismatch,
  21. 223 = cyclical type definition, 224 = ordinal type required
  22. - type rules (single pass, declare-before-use):
  23. . INTEGER, CARDINAL and subranges form one integer family;
  24. no mixed INTEGER/REAL arithmetic; INTEGER assigns to REAL
  25. . each TYPE name gets an alias descriptor, so self-references
  26. (POINTER TO Person) resolve; A = A is caught as cyclical
  27. . record fields live in the type descriptor; WITH pushes them
  28. as an inner scope, so unqualified field access works there
  29. . string literal of length 1 is CHAR, longer ones are string
  30. type (assignable to ARRAY types only)
  31. . unknown types (InvalidType) suppress follow-on errors
  32. - backend (CodeGen): pretty-prints a complete, ready-to-compile
  33. Modula-2 program module to gen/<ModName>.mod (directory gen/
  34. must exist). Comments are dropped; layout is regenerated. *)
  35. IMPORT SymTab, CodeGen;
  36. CHARACTERS
  37. eol = CHR(13) .
  38. letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  39. digit = "0123456789" .
  40. hexDigit = digit + "ABCDEF" .
  41. noQuote1 = ANY - "'" - eol .
  42. noQuote2 = ANY - '"' - eol .
  43. IGNORE CHR(9) .. CHR(13)
  44. COMMENTS
  45. FROM "(*" TO "*)" NESTED
  46. TOKENS
  47. ident = letter { letter | digit } .
  48. integer = digit { digit }
  49. | digit { digit } CONTEXT("..")
  50. | digit { hexDigit } "H" .
  51. real = digit { digit } "." { digit }
  52. [ "E" [ "+" | "-" ] digit { digit } ] .
  53. string = "'" { noQuote1 } "'"
  54. | '"' { noQuote2 } '"' .
  55. PRODUCTIONS
  56. SimpleMod2 (. VAR m1, m2: SymTab.Name; .)
  57. = "MODULE" (. CodeGen.Emit("MODULE ") .)
  58. GetIdent<m1> (. SymTab.Init; CodeGen.OpenModule(m1);
  59. CodeGen.Emit("MODULE ");
  60. CodeGen.Emit(m1);
  61. IF ~SymTab.Enter(m1, SymTab.KindModule)
  62. THEN SemError(200) END .)
  63. ";" (. CodeGen.Emit(";"); CodeGen.Brk; .)
  64. { Import } Block GetIdent<m2> (. IF ~SymTab.Equal(m1, m2)
  65. THEN SemError(202) END .)
  66. "." (. CodeGen.Emit(".");
  67. CodeGen.Close;
  68. SymTab.PrintTable; .) .
  69. Import (. VAR n: SymTab.Name; .)
  70. = "FROM" (. CodeGen.Emit("FROM ") .)
  71. GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
  72. THEN SemError(200) END .)
  73. "IMPORT" (. CodeGen.Emit(" IMPORT ") .)
  74. ImportList ";" (. CodeGen.Emit(";"); CodeGen.Brk; .)
  75. | "IMPORT" (. CodeGen.Emit("IMPORT ") .)
  76. ImportList ";" (. CodeGen.Emit(";"); CodeGen.Brk; .) .
  77. ImportList (. VAR n: SymTab.Name; .)
  78. = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
  79. THEN SemError(200) END .)
  80. { "," (. CodeGen.Emit(", ") .)
  81. GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
  82. THEN SemError(200) END .) } .
  83. Block = { Declaration }
  84. [ "BEGIN" (. CodeGen.Emit("BEGIN");
  85. CodeGen.Ind; CodeGen.Brk; .)
  86. StatSeq ]
  87. "END" (. CodeGen.Ded; CodeGen.Brk;
  88. CodeGen.Emit("END ") .) .
  89. Declaration = "CONST" (. CodeGen.Emit("CONST"); CodeGen.Ind; .)
  90. { (. CodeGen.Brk; .)
  91. ConstDecl ";" (. CodeGen.Emit(";") .) }
  92. (. CodeGen.Ded; CodeGen.Brk; .)
  93. | "TYPE" (. CodeGen.Emit("TYPE"); CodeGen.Ind; .)
  94. { (. CodeGen.Brk; .)
  95. TypeDecl ";" (. CodeGen.Emit(";") .) }
  96. (. CodeGen.Ded; CodeGen.Brk; .)
  97. | "VAR" (. CodeGen.Emit("VAR"); CodeGen.Ind; .)
  98. { (. CodeGen.Brk; .)
  99. VarDecl ";" (. CodeGen.Emit(";") .) }
  100. (. CodeGen.Ded; CodeGen.Brk; .) .
  101. ConstDecl (. VAR n: SymTab.Name;
  102. t: SymTab.TypeIndex; .)
  103. = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindConst)
  104. THEN SemError(200) END .)
  105. "=" (. CodeGen.Emit(" = ") .)
  106. ConstExpr<t> (. SymTab.SetSymType(n, t); .) .
  107. ConstExpr <VAR t: SymTab.TypeIndex>
  108. = Expr<t> .
  109. TypeDecl (. VAR n: SymTab.Name;
  110. t0, t1: SymTab.TypeIndex; .)
  111. = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindType)
  112. THEN SemError(200) END;
  113. t0 := SymTab.NewAlias();
  114. SymTab.SetSymType(n, t0); .)
  115. "=" (. CodeGen.Emit(" = ") .)
  116. Type<t1> (. IF t1 = t0 THEN SemError(223);
  117. SymTab.SetTarget(t0,
  118. SymTab.InvalidType)
  119. ELSE SymTab.SetTarget(t0, t1) END; .) .
  120. VarDecl (. VAR t: SymTab.TypeIndex; .)
  121. = VarIdents ":" (. CodeGen.Emit(" : ") .)
  122. Type<t> (. SymTab.FixPending(t); .) .
  123. VarIdents (. VAR n: SymTab.Name; .)
  124. = GetIdent<n> (. IF ~SymTab.EnterPending(n,
  125. SymTab.KindVar)
  126. THEN SemError(200) END .)
  127. { "," (. CodeGen.Emit(", ") .)
  128. GetIdent<n> (. IF ~SymTab.EnterPending(n,
  129. SymTab.KindVar)
  130. THEN SemError(200) END .) } .
  131. QualIdent <VAR t: SymTab.TypeIndex>
  132. (. VAR n, m: SymTab.Name; .)
  133. = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  134. SemError(201);
  135. t := SymTab.InvalidType
  136. ELSIF (SymTab.SymKind(n) #
  137. SymTab.KindType)
  138. & (SymTab.SymKind(n) #
  139. SymTab.KindPredef)
  140. & (SymTab.SymKind(n) #
  141. SymTab.KindImport) THEN
  142. SemError(221);
  143. t := SymTab.InvalidType
  144. ELSE t := SymTab.SymType(n) END; .)
  145. { "." (. CodeGen.Emit(".");
  146. t := SymTab.InvalidType; .)
  147. GetIdent<m> } .
  148. (* Types: ProcedureType removed; subrange factored for LL(1) *)
  149. Type <VAR t: SymTab.TypeIndex>
  150. = SimpleType<t> | ArrayType<t> | RecordType<t>
  151. | SetType<t> | PointerType<t> .
  152. SimpleType <VAR t: SymTab.TypeIndex>
  153. (. VAR t1, t2: SymTab.TypeIndex; .)
  154. = QualIdent<t> [ "[" (. CodeGen.Emit("[") .)
  155. ConstExpr<t1> (. IF (t1 # SymTab.InvalidType)
  156. & (SymTab.ClassOf(t1) #
  157. SymTab.ClInt)
  158. & (SymTab.ClassOf(t1) #
  159. SymTab.ClChar)
  160. & (SymTab.ClassOf(t1) #
  161. SymTab.ClEnum) THEN
  162. SemError(224) END; .)
  163. ".." (. CodeGen.Emit("..") .)
  164. ConstExpr<t2> (. IF (t2 # SymTab.InvalidType)
  165. & (SymTab.ClassOf(t2) #
  166. SymTab.ClInt)
  167. & (SymTab.ClassOf(t2) #
  168. SymTab.ClChar)
  169. & (SymTab.ClassOf(t2) #
  170. SymTab.ClEnum) THEN
  171. SemError(224) END; .)
  172. "]" (. CodeGen.Emit("]") .)
  173. (. t := SymTab.NewSub(t1); .) ]
  174. | "[" (. CodeGen.Emit("[") .)
  175. ConstExpr<t1> (. IF (t1 # SymTab.InvalidType)
  176. & (SymTab.ClassOf(t1) #
  177. SymTab.ClInt)
  178. & (SymTab.ClassOf(t1) #
  179. SymTab.ClChar)
  180. & (SymTab.ClassOf(t1) #
  181. SymTab.ClEnum) THEN
  182. SemError(224) END; .)
  183. ".." (. CodeGen.Emit("..") .)
  184. ConstExpr<t2> (. IF (t2 # SymTab.InvalidType)
  185. & (SymTab.ClassOf(t2) #
  186. SymTab.ClInt)
  187. & (SymTab.ClassOf(t2) #
  188. SymTab.ClChar)
  189. & (SymTab.ClassOf(t2) #
  190. SymTab.ClEnum) THEN
  191. SemError(224) END; .)
  192. "]" (. CodeGen.Emit("]") .)
  193. (. t := SymTab.NewSub(t1); .)
  194. | Enum<t> .
  195. Enum <VAR t: SymTab.TypeIndex>
  196. (. VAR n: SymTab.Name; .)
  197. = "(" (. CodeGen.Emit("(");
  198. t := SymTab.NewEnum(); .)
  199. GetIdent<n> (. IF ~SymTab.Enter(n,
  200. SymTab.KindConst)
  201. THEN SemError(200) END;
  202. SymTab.SetSymType(n, t); .)
  203. { "," (. CodeGen.Emit(", ") .)
  204. GetIdent<n> (. IF ~SymTab.Enter(n,
  205. SymTab.KindConst)
  206. THEN SemError(200) END;
  207. SymTab.SetSymType(n, t); .) }
  208. ")" (. CodeGen.Emit(")") .) .
  209. ArrayType <VAR t: SymTab.TypeIndex>
  210. (. VAR s, s2, e: SymTab.TypeIndex; .)
  211. = "ARRAY" (. CodeGen.Emit("ARRAY ") .)
  212. SimpleType<s> (. IF (s # SymTab.InvalidType)
  213. & (SymTab.ClassOf(s) #
  214. SymTab.ClInt)
  215. & (SymTab.ClassOf(s) #
  216. SymTab.ClChar)
  217. & (SymTab.ClassOf(s) #
  218. SymTab.ClEnum) THEN
  219. SemError(224) END; .)
  220. { "," (. CodeGen.Emit(", ") .)
  221. SimpleType<s2> (. IF (s2 # SymTab.InvalidType)
  222. & (SymTab.ClassOf(s2) #
  223. SymTab.ClInt)
  224. & (SymTab.ClassOf(s2) #
  225. SymTab.ClChar)
  226. & (SymTab.ClassOf(s2) #
  227. SymTab.ClEnum) THEN
  228. SemError(224) END; .) }
  229. "OF" (. CodeGen.Emit(" OF ") .)
  230. Type<e> (. t := SymTab.NewArray(e); .) .
  231. RecordType <VAR t: SymTab.TypeIndex>
  232. = "RECORD" (. CodeGen.Emit("RECORD");
  233. CodeGen.Ind; CodeGen.Brk;
  234. t := SymTab.NewRecord(); .)
  235. FieldSeq<t>
  236. "END" (. CodeGen.Ded; CodeGen.Brk;
  237. CodeGen.Emit("END") .) .
  238. FieldSeq <rt: SymTab.TypeIndex>
  239. = Field<rt> { ";" (. CodeGen.Emit(";"); CodeGen.Brk; .)
  240. Field<rt> } .
  241. Field <rt: SymTab.TypeIndex>
  242. (. VAR et: SymTab.TypeIndex; .)
  243. = [ FieldIdents<rt> ":" (. CodeGen.Emit(" : ") .)
  244. Type<et> (. SymTab.FixPendingF(rt, et); .) ] .
  245. FieldIdents <rt: SymTab.TypeIndex>
  246. (. VAR n: SymTab.Name; .)
  247. = GetIdent<n> (. IF ~SymTab.FieldPending(rt, n)
  248. THEN SemError(200) END .)
  249. { "," (. CodeGen.Emit(", ") .)
  250. GetIdent<n> (. IF ~SymTab.FieldPending(rt, n)
  251. THEN SemError(200) END .) } .
  252. SetType <VAR t: SymTab.TypeIndex>
  253. (. VAR s: SymTab.TypeIndex; .)
  254. = "SET" (. CodeGen.Emit("SET ") .)
  255. "OF" (. CodeGen.Emit("OF ") .)
  256. SimpleType<s> (. IF (s # SymTab.InvalidType)
  257. & (SymTab.ClassOf(s) #
  258. SymTab.ClInt)
  259. & (SymTab.ClassOf(s) #
  260. SymTab.ClChar)
  261. & (SymTab.ClassOf(s) #
  262. SymTab.ClEnum) THEN
  263. SemError(224) END;
  264. t := SymTab.NewSet(s); .) .
  265. PointerType <VAR t: SymTab.TypeIndex>
  266. (. VAR b: SymTab.TypeIndex; .)
  267. = "POINTER" (. CodeGen.Emit("POINTER ") .)
  268. "TO" (. CodeGen.Emit("TO ") .)
  269. Type<b> (. t := SymTab.NewPtr(b); .) .
  270. (* Statements: ProcedureCall and RETURN removed *)
  271. StatSeq = Stat { ";" (. CodeGen.Emit(";") .)
  272. (. CodeGen.Brk; .)
  273. Stat } .
  274. Stat = [ Assign | IfStat | CaseStat | WhileStat
  275. | RepeatStat | LoopStat | ForStat | WithStat
  276. | "EXIT" (. CodeGen.Emit("EXIT") .) ] .
  277. Assign (. VAR dt, et: SymTab.TypeIndex;
  278. dk: INTEGER; .)
  279. = Design<dt, dk> ":=" (. CodeGen.Emit(" := ") .)
  280. Expr<et> (. IF (dt # SymTab.InvalidType)
  281. & (dk # SymTab.KindVar)
  282. & (dk # SymTab.KindField)
  283. & (dk # SymTab.KindImport) THEN
  284. SemError(210)
  285. ELSIF ~SymTab.Assignable(et, dt) THEN
  286. SemError(210) END; .) .
  287. IfStat (. VAR t: SymTab.TypeIndex; .)
  288. = "IF" (. CodeGen.Emit("IF ") .)
  289. Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
  290. SemError(214) END; .)
  291. "THEN" (. CodeGen.Emit(" THEN");
  292. CodeGen.Brk; CodeGen.Ind; .)
  293. StatSeq
  294. { "ELSIF" (. CodeGen.Ded; CodeGen.Brk;
  295. CodeGen.Emit("ELSIF ") .)
  296. Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
  297. SemError(214) END; .)
  298. "THEN" (. CodeGen.Emit(" THEN");
  299. CodeGen.Brk; CodeGen.Ind; .)
  300. StatSeq }
  301. [ "ELSE" (. CodeGen.Ded; CodeGen.Brk;
  302. CodeGen.Emit("ELSE");
  303. CodeGen.Ind; CodeGen.Brk; .)
  304. StatSeq ]
  305. "END" (. CodeGen.Ded; CodeGen.Brk;
  306. CodeGen.Emit("END") .) .
  307. CaseStat (. VAR st: SymTab.TypeIndex; .)
  308. = "CASE" (. CodeGen.Emit("CASE ") .)
  309. Expr<st>
  310. "OF" (. CodeGen.Emit(" OF");
  311. CodeGen.Brk; CodeGen.Ind; .)
  312. Case<st> { "|" (. CodeGen.Brk; CodeGen.Emit("| ") .)
  313. Case<st> }
  314. [ "ELSE" (. CodeGen.Ded; CodeGen.Brk;
  315. CodeGen.Emit("ELSE ");
  316. CodeGen.Ind; CodeGen.Brk; .)
  317. StatSeq ]
  318. "END" (. CodeGen.Ded; CodeGen.Brk;
  319. CodeGen.Emit("END") .) .
  320. Case <sel: SymTab.TypeIndex>
  321. = [ LabelList<sel> ":" (. CodeGen.Emit(" : ") .)
  322. StatSeq ] .
  323. LabelList <sel: SymTab.TypeIndex>
  324. = Labels<sel> { "," (. CodeGen.Emit(", ") .)
  325. Labels<sel> } .
  326. Labels <sel: SymTab.TypeIndex>
  327. (. VAR t, t2: SymTab.TypeIndex; .)
  328. = ConstExpr<t> (. IF ~SymTab.EqCheck(t, sel) THEN
  329. SemError(213) END; .)
  330. [ ".." (. CodeGen.Emit("..") .)
  331. ConstExpr<t2> (. IF ~SymTab.EqCheck(t2, sel) THEN
  332. SemError(213) END; .) ] .
  333. WhileStat (. VAR t: SymTab.TypeIndex; .)
  334. = "WHILE" (. CodeGen.Emit("WHILE ") .)
  335. Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
  336. SemError(214) END; .)
  337. "DO" (. CodeGen.Emit(" DO");
  338. CodeGen.Brk; CodeGen.Ind; .)
  339. StatSeq
  340. "END" (. CodeGen.Ded; CodeGen.Brk;
  341. CodeGen.Emit("END") .) .
  342. RepeatStat (. VAR t: SymTab.TypeIndex; .)
  343. = "REPEAT" (. CodeGen.Emit("REPEAT");
  344. CodeGen.Brk; CodeGen.Ind; .)
  345. StatSeq
  346. "UNTIL" (. CodeGen.Ded; CodeGen.Brk;
  347. CodeGen.Emit("UNTIL ") .)
  348. Expr<t> (. IF ~SymTab.BoolCheck(t) THEN
  349. SemError(214) END; .) .
  350. LoopStat = "LOOP" (. CodeGen.Emit("LOOP");
  351. CodeGen.Brk; CodeGen.Ind; .)
  352. StatSeq
  353. "END" (. CodeGen.Ded; CodeGen.Brk;
  354. CodeGen.Emit("END") .) .
  355. ForStat (. VAR n: SymTab.Name;
  356. lo, hi, by: SymTab.TypeIndex; .)
  357. = "FOR" (. CodeGen.Emit("FOR ") .)
  358. GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  359. SemError(201)
  360. ELSIF (SymTab.SymKind(n) #
  361. SymTab.KindVar)
  362. & (SymTab.SymKind(n) #
  363. SymTab.KindField) THEN
  364. SemError(220)
  365. ELSIF (SymTab.SymType(n) #
  366. SymTab.InvalidType)
  367. & ~SymTab.IsIntFamily(
  368. SymTab.SymType(n)) THEN
  369. SemError(220) END; .)
  370. ":=" (. CodeGen.Emit(" := ") .)
  371. Expr<lo> (. IF (lo # SymTab.InvalidType)
  372. & ~SymTab.IsIntFamily(lo) THEN
  373. SemError(220) END; .)
  374. "TO" (. CodeGen.Emit(" TO ") .)
  375. Expr<hi> (. IF (hi # SymTab.InvalidType)
  376. & ~SymTab.IsIntFamily(hi) THEN
  377. SemError(220) END; .)
  378. [ "BY" (. CodeGen.Emit(" BY ") .)
  379. ConstExpr<by> (. IF (by # SymTab.InvalidType)
  380. & ~SymTab.IsIntFamily(by) THEN
  381. SemError(220) END; .) ]
  382. "DO" (. CodeGen.Emit(" DO");
  383. CodeGen.Brk; CodeGen.Ind; .)
  384. StatSeq
  385. "END" (. CodeGen.Ded; CodeGen.Brk;
  386. CodeGen.Emit("END") .) .
  387. WithStat (. VAR dt: SymTab.TypeIndex;
  388. dk: INTEGER;
  389. pushed: BOOLEAN; .)
  390. = "WITH" (. CodeGen.Emit("WITH ") .)
  391. Design<dt, dk> (. pushed := FALSE;
  392. IF dt # SymTab.InvalidType THEN
  393. pushed :=
  394. SymTab.PushRecord(dt);
  395. IF ~pushed THEN
  396. SemError(215)
  397. END
  398. END; .)
  399. "DO" (. CodeGen.Emit(" DO");
  400. CodeGen.Brk; CodeGen.Ind; .)
  401. StatSeq
  402. "END" (. IF pushed THEN
  403. SymTab.PopScope
  404. END;
  405. CodeGen.Ded; CodeGen.Brk;
  406. CodeGen.Emit("END") .) .
  407. (* Expressions: Designator without ActualParameters.
  408. Only record fields resolve qualified access; WITH pushes an
  409. inner scope so field names also work unqualified in its body. *)
  410. Design <VAR t: SymTab.TypeIndex; VAR k: INTEGER>
  411. (. VAR n, m: SymTab.Name;
  412. it: SymTab.TypeIndex; .)
  413. = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  414. SemError(201);
  415. t := SymTab.InvalidType; k := -1
  416. ELSE t := SymTab.SymType(n);
  417. k := SymTab.SymKind(n) END; .)
  418. { "." (. CodeGen.Emit(".") .)
  419. GetIdent<m> (. IF t = SymTab.InvalidType THEN
  420. ELSIF SymTab.ClassOf(t) #
  421. SymTab.ClRecord THEN
  422. SemError(215);
  423. t := SymTab.InvalidType
  424. ELSIF ~SymTab.FieldExists(t, m) THEN
  425. SemError(216);
  426. t := SymTab.InvalidType
  427. ELSE t := SymTab.FieldType(t, m)
  428. END; .)
  429. | "[" (. CodeGen.Emit("[") .)
  430. Expr<it> (. IF t = SymTab.InvalidType THEN
  431. ELSIF SymTab.ClassOf(t) #
  432. SymTab.ClArray THEN
  433. SemError(217);
  434. t := SymTab.InvalidType
  435. ELSIF (it #
  436. SymTab.InvalidType)
  437. & ~SymTab.IsIntFamily(it) THEN
  438. SemError(218);
  439. t := SymTab.InvalidType
  440. ELSE t :=
  441. SymTab.ArrayElem(t) END; .)
  442. { "," (. CodeGen.Emit(", ") .)
  443. Expr<it> (. IF (it # SymTab.InvalidType)
  444. & ~SymTab.IsIntFamily(it) THEN
  445. SemError(218) END; .) }
  446. "]" (. CodeGen.Emit("]") .)
  447. | "^" (. CodeGen.Emit("^") .)
  448. (. IF t = SymTab.InvalidType THEN
  449. ELSIF SymTab.ClassOf(t) #
  450. SymTab.ClPtr THEN
  451. SemError(219);
  452. t := SymTab.InvalidType
  453. ELSE t := SymTab.PtrBase(t)
  454. END; .) } .
  455. Expr <VAR t: SymTab.TypeIndex>
  456. (. VAR t2: SymTab.TypeIndex;
  457. op: INTEGER; .)
  458. = SimExpr<t> [ Rel<op> SimExpr<t2>
  459. (. IF op = SymTab.OpIn THEN
  460. IF SymTab.InCheck(t, t2) THEN t := SymTab.BoolType()
  461. ELSE SemError(222); t := SymTab.InvalidType END
  462. ELSE
  463. IF SymTab.RelCheck(t, t2, op) THEN
  464. t := SymTab.BoolType()
  465. ELSE SemError(213); t := SymTab.InvalidType END
  466. END; .) ] .
  467. Rel <VAR op: INTEGER>
  468. = "=" (. CodeGen.Emit(" = "); op := SymTab.OpEq; .)
  469. | "#" (. CodeGen.Emit(" # "); op := SymTab.OpNeq1; .)
  470. | "<>" (. CodeGen.Emit(" <> "); op := SymTab.OpNeq2; .)
  471. | "<" (. CodeGen.Emit(" < "); op := SymTab.OpLt; .)
  472. | "<=" (. CodeGen.Emit(" <= "); op := SymTab.OpLe; .)
  473. | ">" (. CodeGen.Emit(" > "); op := SymTab.OpGt; .)
  474. | ">=" (. CodeGen.Emit(" >= "); op := SymTab.OpGe; .)
  475. | "IN" (. CodeGen.Emit(" IN "); op := SymTab.OpIn; .) .
  476. SimExpr <VAR t: SymTab.TypeIndex>
  477. (. VAR t2, res2: SymTab.TypeIndex;
  478. op: INTEGER; .)
  479. = [ "+" (. CodeGen.Emit("+") .)
  480. | "-" (. CodeGen.Emit("-") .) ]
  481. Term<t> { AddOp<op> Term<t2>
  482. (. IF op = SymTab.OpOr THEN
  483. IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
  484. t := SymTab.BoolType()
  485. ELSE SemError(212); t := SymTab.InvalidType END
  486. ELSE
  487. IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN t := res2
  488. ELSE SemError(211); t := SymTab.InvalidType END
  489. END; .) } .
  490. AddOp <VAR op: INTEGER>
  491. = "+" (. CodeGen.Emit(" + "); op := SymTab.OpAdd; .)
  492. | "-" (. CodeGen.Emit(" - "); op := SymTab.OpSub; .)
  493. | "OR" (. CodeGen.Emit(" OR "); op := SymTab.OpOr; .) .
  494. Term <VAR t: SymTab.TypeIndex>
  495. (. VAR t2, res2: SymTab.TypeIndex;
  496. op: INTEGER; .)
  497. = Fact<t> { MulOp<op> Fact<t2>
  498. (. IF op = SymTab.OpAnd THEN
  499. IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
  500. t := SymTab.BoolType()
  501. ELSE SemError(212); t := SymTab.InvalidType END
  502. ELSE
  503. IF SymTab.ArithCheck(t, t2,
  504. (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  505. res2) THEN t := res2
  506. ELSE SemError(211); t := SymTab.InvalidType END
  507. END; .) } .
  508. MulOp <VAR op: INTEGER>
  509. = "*" (. CodeGen.Emit(" * "); op := SymTab.OpTimes; .)
  510. | "/" (. CodeGen.Emit(" / "); op := SymTab.OpSlash; .)
  511. | "DIV" (. CodeGen.Emit(" DIV "); op := SymTab.OpDiv; .)
  512. | "MOD" (. CodeGen.Emit(" MOD "); op := SymTab.OpMod; .)
  513. | "AND" (. CodeGen.Emit(" AND "); op := SymTab.OpAnd; .)
  514. | "&" (. CodeGen.Emit(" & "); op := SymTab.OpAnd; .) .
  515. Fact <VAR t: SymTab.TypeIndex>
  516. (. VAR s: ARRAY [0 .. 255] OF CHAR;
  517. t2, et, dt, st: SymTab.TypeIndex;
  518. dk: INTEGER; .)
  519. = integer (. LexString(s); CodeGen.Emit(s);
  520. t := SymTab.IntType(); .)
  521. | real (. LexString(s); CodeGen.Emit(s);
  522. t := SymTab.RealType(); .)
  523. | string (. LexString(s); CodeGen.Emit(s);
  524. IF SymTab.StrLen(s) <= 3 THEN
  525. t := SymTab.CharType()
  526. ELSE t := SymTab.NewStr() END; .)
  527. | Design<dt, dk> (. t := dt; .)
  528. | "(" (. CodeGen.Emit("(") .)
  529. Expr<et> ")" (. CodeGen.Emit(")"); t := et; .)
  530. | ( "NOT" (. CodeGen.Emit("NOT ") .)
  531. | "~" (. CodeGen.Emit("~") .) )
  532. Fact<t2> (. IF SymTab.BoolCheck(t2) THEN
  533. t := SymTab.BoolType()
  534. ELSE SemError(212);
  535. t := SymTab.InvalidType END; .)
  536. | SetLit<st> (. t := st; .) .
  537. SetLit <VAR t: SymTab.TypeIndex>
  538. (. VAR first, et: SymTab.TypeIndex; .)
  539. = "{" (. CodeGen.Emit("{");
  540. t := SymTab.SetFor(SymTab.IntType()); .)
  541. [ Elem<et> (. first := et; t := SymTab.SetFor(et); .)
  542. { "," (. CodeGen.Emit(", ") .)
  543. Elem<et> (. IF ~SymTab.SetElemCheck(first, et) THEN
  544. SemError(222) END; .) } ]
  545. "}" (. CodeGen.Emit("}") .) .
  546. Elem <VAR t: SymTab.TypeIndex>
  547. (. VAR t2: SymTab.TypeIndex; .)
  548. = Expr<t> [ ".." (. CodeGen.Emit("..") .)
  549. Expr<t2> (. IF ~SymTab.SetElemCheck(t, t2) THEN
  550. SemError(222) END; .) ] .
  551. GetIdent <VAR n: SymTab.Name>
  552. = ident (. LexName(n); CodeGen.Emit(n); .) .
  553. END SimpleMod2.