M2c.atg 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165
  1. COMPILER M2c
  2. (* Modula-2 program modules with procedures, MC64 backend
  3. (see MGen for details).
  4. - program module only, no DEFINITION / IMPLEMENTATION split
  5. - no local modules, no EXPORT, no PRIORITY
  6. - procedures: declarations (nested), value and VAR parameters,
  7. functions with RETURN, recursion, FORWARD headings;
  8. no procedure types/variables, no cones
  9. - statements: assignment, procedure call, IF, CASE, WHILE,
  10. REPEAT, LOOP/EXIT, FOR, WITH, RETURN
  11. - symbol table (SymTab) with static type checking: error codes
  12. 200/201/202 and 210-224 (as before), plus 231 (procedure
  13. forward mismatch or missing body), 232 (bad RETURN), 233
  14. (invalid procedure call); same lenient rules (single pass,
  15. declare-before-use; INTEGER, CARDINAL and subranges form one
  16. integer family; no mixed INTEGER/REAL arithmetic; INTEGER
  17. assigns to REAL; 1-character literal is CHAR; InvalidType
  18. suppresses follow-on errors)
  19. - backend (MGen): single-module MC64 image <ModName>.MC4,
  20. runnable with mcint. Procedures take table entries 1..N
  21. (0 = module body), run with ENTER frames, called via ED
  22. (global), EC (directly nested) or EE (display walk); actuals
  23. evaluate left-to-right into temps, then push reversed.
  24. Lowered: scalar globals and frame variables, CONST literals,
  25. SET masks with literals/IN/=/#; full scalar expressions;
  26. control flow via E0/E1 jumps. The rest parses and type-checks
  27. but gets error 230: ARRAY/RECORD/POINTER variables, string
  28. variables, WITH, non-literal CONST expressions and BY steps,
  29. EXIT outside LOOP, imported names used as values.
  30. - test convention (the language has no I/O): a global
  31. VAR ExitCode : INTEGER;
  32. is printed as decimal + CRLF through an embedded helper;
  33. without it the program just ends.
  34. - known semantic edges: INTEGER DIV/MOD truncate toward zero;
  35. CARDINAL past MAXINT compares as signed; AND/OR are eager;
  36. REAL widens to binary64; at most 64 procedures, 64 actuals
  37. per call, 16 names per FP-section, 8-deep nested calls. *)
  38. IMPORT SymTab, MGen;
  39. CHARACTERS
  40. eol = CHR(13) .
  41. letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
  42. digit = "0123456789" .
  43. hexDigit = digit + "ABCDEF" .
  44. noQuote1 = ANY - "'" - eol .
  45. noQuote2 = ANY - '"' - eol .
  46. IGNORE CHR(9) .. CHR(13)
  47. COMMENTS
  48. FROM "(*" TO "*)" NESTED
  49. TOKENS
  50. ident = letter { letter | digit } .
  51. integer = digit { digit }
  52. | digit { digit } CONTEXT("..")
  53. | digit { hexDigit } "H" .
  54. real = digit { digit } "." { digit }
  55. [ "E" [ "+" | "-" ] digit { digit } ] .
  56. string = "'" { noQuote1 } "'"
  57. | '"' { noQuote2 } '"' .
  58. PRODUCTIONS
  59. M2c (. VAR m1, m2: SymTab.Name; .)
  60. = "MODULE"
  61. GetIdent<m1> (. SymTab.Init; MGen.OpenModule(m1);
  62. IF ~SymTab.Enter(m1, SymTab.KindModule)
  63. THEN SemError(200) END .)
  64. ";"
  65. { Import } Block<FALSE> GetIdent<m2>
  66. (. IF ~SymTab.Equal(m1, m2)
  67. THEN SemError(202) END .)
  68. "." (. IF SymTab.AnyForward() THEN
  69. SemError(231)
  70. END;
  71. MGen.EndModule;
  72. SymTab.PrintTable; .) .
  73. Import (. VAR n: SymTab.Name; .)
  74. = "FROM"
  75. GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
  76. THEN SemError(200) END .)
  77. "IMPORT"
  78. ImportList ";"
  79. | "IMPORT"
  80. ImportList ";" .
  81. ImportList (. VAR n: SymTab.Name; .)
  82. = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
  83. THEN SemError(200) END .)
  84. { ","
  85. GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindImport)
  86. THEN SemError(200) END .) } .
  87. Block <isProc: BOOLEAN> (. VAR began: BOOLEAN; .)
  88. = (. began := FALSE; .)
  89. { Declaration }
  90. [ "BEGIN" (. began := TRUE;
  91. IF isProc THEN
  92. MGen.ProcEntry(
  93. SymTab.CurProc(),
  94. SymTab.ProcNLocals())
  95. ELSE MGen.BeginBody
  96. END; .)
  97. StatSeq ]
  98. "END" (. IF isProc THEN
  99. IF ~began THEN
  100. MGen.ProcEntry(
  101. SymTab.CurProc(),
  102. SymTab.ProcNLocals())
  103. END;
  104. IF SymTab.InFunction() THEN
  105. MGen.PushInt(0)
  106. END;
  107. MGen.Leave(SymTab.CurNPar(),
  108. SymTab.InFunction())
  109. END; .) .
  110. Declaration = "CONST"
  111. {
  112. ConstDecl ";" }
  113. | "TYPE"
  114. {
  115. TypeDecl ";" }
  116. | "VAR"
  117. {
  118. VarDecl ";" }
  119. | ProcedureDecl ";" .
  120. ConstDecl (. VAR n: SymTab.Name;
  121. t: SymTab.TypeIndex;
  122. lx: MGen.LitStr;
  123. cls: INTEGER; .)
  124. = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindConst)
  125. THEN SemError(200) END .)
  126. "=" (. MGen.NoEmitEnter; .)
  127. ConstExpr<t, lx> (. SymTab.SetSymType(n, t);
  128. cls := SymTab.ClassOf(t);
  129. IF cls = SymTab.ClStr THEN
  130. SemError(230)
  131. ELSIF ~MGen.IsLit(lx) THEN
  132. SemError(230)
  133. END;
  134. MGen.DeclConst(n, lx, t);
  135. MGen.NoEmitExit; .) .
  136. ConstExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr>
  137. (. VAR vD: BOOLEAN;
  138. vnD: SymTab.Name; .)
  139. = Expr<t, lx, vD, vnD> .
  140. TypeDecl (. VAR n: SymTab.Name;
  141. t0, t1: SymTab.TypeIndex; .)
  142. = GetIdent<n> (. IF ~SymTab.Enter(n, SymTab.KindType)
  143. THEN SemError(200) END;
  144. t0 := SymTab.NewAlias();
  145. SymTab.SetSymType(n, t0); .)
  146. "="
  147. Type<t1> (. IF t1 = t0 THEN SemError(223);
  148. SymTab.SetTarget(t0,
  149. SymTab.InvalidType)
  150. ELSE SymTab.SetTarget(t0, t1) END; .) .
  151. VarDecl (. VAR t: SymTab.TypeIndex;
  152. i: CARDINAL;
  153. nm: SymTab.Name;
  154. cls: INTEGER; .)
  155. = VarIdents ":"
  156. Type<t> (. cls := SymTab.ClassOf(t);
  157. IF (cls # SymTab.ClInt)
  158. & (cls # SymTab.ClReal)
  159. & (cls # SymTab.ClBool)
  160. & (cls # SymTab.ClChar)
  161. & (cls # SymTab.ClEnum)
  162. & (cls # SymTab.ClSet) THEN
  163. SemError(230)
  164. END;
  165. i := 0;
  166. WHILE i < SymTab.PendCount() DO
  167. SymTab.PendName(i, nm);
  168. IF SymTab.SymDepth(nm) = 0 THEN
  169. MGen.DeclVar(nm)
  170. END;
  171. INC(i)
  172. END;
  173. SymTab.FixPending(t); .) .
  174. VarIdents (. VAR n: SymTab.Name; .)
  175. = GetIdent<n> (. IF ~SymTab.EnterPending(n,
  176. SymTab.KindVar)
  177. THEN SemError(200) END .)
  178. { ","
  179. GetIdent<n> (. IF ~SymTab.EnterPending(n,
  180. SymTab.KindVar)
  181. THEN SemError(200) END .) } .
  182. ProcedureDecl (. VAR n, m: SymTab.Name;
  183. rt: SymTab.TypeIndex;
  184. hasR, ok: BOOLEAN;
  185. endL: INTEGER; .)
  186. = "PROCEDURE" (. hasR := FALSE; .)
  187. GetIdent<n> (. IF SymTab.IsForward(n) THEN
  188. SymTab.ReuseProc(n)
  189. ELSIF ~SymTab.EnterProc(n) THEN
  190. SemError(200)
  191. END;
  192. SymTab.OpenProcScope;
  193. endL := MGen.NewLabel();
  194. MGen.Jmp(endL); .)
  195. [ "(" FormalParams ")" ]
  196. [ ":" QualIdent<rt> (. hasR := TRUE; .) ]
  197. (. IF hasR THEN
  198. ok := SymTab.SetProcRet(rt)
  199. ELSE
  200. ok := SymTab.SetProcRet(
  201. SymTab.InvalidType)
  202. END;
  203. IF ~ok THEN SemError(231) END;
  204. IF ~SymTab.VerifyProc() THEN
  205. SemError(231)
  206. END; .)
  207. ";"
  208. ( Block<TRUE> GetIdent<m> (. IF ~SymTab.Equal(n, m) THEN
  209. SemError(202) END;
  210. MGen.DefLabel(endL);
  211. SymTab.CloseProc; .)
  212. | "FORWARD" (. SymTab.SetForward;
  213. SymTab.CloseProc;
  214. MGen.DefLabel(endL); .) ) .
  215. FormalParams = FPSection { ";" FPSection } .
  216. FPSection (. VAR isV: BOOLEAN;
  217. nn, i: CARDINAL;
  218. pn: ARRAY [0 .. 15] OF SymTab.Name;
  219. n: SymTab.Name;
  220. t: SymTab.TypeIndex; .)
  221. = (. isV := FALSE; nn := 0; .)
  222. [ "VAR" (. isV := TRUE; .) ]
  223. GetIdent<n> (. IF nn <= HIGH(pn) THEN
  224. MGen.CopyName(n, pn[nn])
  225. END;
  226. INC(nn); .)
  227. { "," GetIdent<n> (. IF nn <= HIGH(pn) THEN
  228. MGen.CopyName(n, pn[nn])
  229. END;
  230. INC(nn); .) }
  231. ":" Type<t> (. i := 0;
  232. WHILE i < nn DO
  233. IF i <= HIGH(pn) THEN
  234. IF ~SymTab.EnterParam(
  235. pn[i], isV, t) THEN
  236. SemError(200)
  237. END
  238. END;
  239. INC(i)
  240. END; .) .
  241. QualIdent <VAR t: SymTab.TypeIndex>
  242. (. VAR n, m: SymTab.Name; .)
  243. = GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  244. SemError(201);
  245. t := SymTab.InvalidType
  246. ELSIF (SymTab.SymKind(n) #
  247. SymTab.KindType)
  248. & (SymTab.SymKind(n) #
  249. SymTab.KindPredef)
  250. & (SymTab.SymKind(n) #
  251. SymTab.KindImport) THEN
  252. SemError(221);
  253. t := SymTab.InvalidType
  254. ELSE t := SymTab.SymType(n) END; .)
  255. { "."
  256. GetIdent<m> (. t := SymTab.InvalidType; .) } .
  257. (* Types: ProcedureType removed; subrange factored for LL(1) *)
  258. Type <VAR t: SymTab.TypeIndex>
  259. = SimpleType<t> | ArrayType<t> | RecordType<t>
  260. | SetType<t> | PointerType<t> .
  261. SimpleType <VAR t: SymTab.TypeIndex>
  262. (. VAR t1, t2: SymTab.TypeIndex;
  263. lx1, lx2: MGen.LitStr;
  264. vD: BOOLEAN;
  265. vnD: SymTab.Name; .)
  266. = QualIdent<t> [ "["
  267. (. MGen.NoEmitEnter; .)
  268. ConstExpr<t1, lx1> (. IF (t1 # SymTab.InvalidType)
  269. & (SymTab.ClassOf(t1) #
  270. SymTab.ClInt)
  271. & (SymTab.ClassOf(t1) #
  272. SymTab.ClChar)
  273. & (SymTab.ClassOf(t1) #
  274. SymTab.ClEnum) THEN
  275. SemError(224) END; .)
  276. ".."
  277. ConstExpr<t2, lx2> (. IF (t2 # SymTab.InvalidType)
  278. & (SymTab.ClassOf(t2) #
  279. SymTab.ClInt)
  280. & (SymTab.ClassOf(t2) #
  281. SymTab.ClChar)
  282. & (SymTab.ClassOf(t2) #
  283. SymTab.ClEnum) THEN
  284. SemError(224) END; .)
  285. "]"
  286. (. t := SymTab.NewSub(t1);
  287. MGen.NoEmitExit; .) ]
  288. | "[" (. MGen.NoEmitEnter; .)
  289. ConstExpr<t1, lx1> (. IF (t1 # SymTab.InvalidType)
  290. & (SymTab.ClassOf(t1) #
  291. SymTab.ClInt)
  292. & (SymTab.ClassOf(t1) #
  293. SymTab.ClChar)
  294. & (SymTab.ClassOf(t1) #
  295. SymTab.ClEnum) THEN
  296. SemError(224) END; .)
  297. ".."
  298. ConstExpr<t2, lx2> (. IF (t2 # SymTab.InvalidType)
  299. & (SymTab.ClassOf(t2) #
  300. SymTab.ClInt)
  301. & (SymTab.ClassOf(t2) #
  302. SymTab.ClChar)
  303. & (SymTab.ClassOf(t2) #
  304. SymTab.ClEnum) THEN
  305. SemError(224) END; .)
  306. "]" (. t := SymTab.NewSub(t1);
  307. MGen.NoEmitExit; .)
  308. | Enum<t> .
  309. Enum <VAR t: SymTab.TypeIndex>
  310. (. VAR n: SymTab.Name;
  311. ord: INTEGER; .)
  312. = "(" (. t := SymTab.NewEnum();
  313. ord := 0; .)
  314. GetIdent<n> (. IF ~SymTab.Enter(n,
  315. SymTab.KindConst)
  316. THEN SemError(200) END;
  317. SymTab.SetSymType(n, t);
  318. MGen.DeclConstInt(n, ord);
  319. INC(ord); .)
  320. { ","
  321. GetIdent<n> (. IF ~SymTab.Enter(n,
  322. SymTab.KindConst)
  323. THEN SemError(200) END;
  324. SymTab.SetSymType(n, t);
  325. MGen.DeclConstInt(n, ord);
  326. INC(ord); .) }
  327. ")" .
  328. ArrayType <VAR t: SymTab.TypeIndex>
  329. (. VAR s, s2, e: SymTab.TypeIndex; .)
  330. = "ARRAY"
  331. SimpleType<s> (. IF (s # SymTab.InvalidType)
  332. & (SymTab.ClassOf(s) #
  333. SymTab.ClInt)
  334. & (SymTab.ClassOf(s) #
  335. SymTab.ClChar)
  336. & (SymTab.ClassOf(s) #
  337. SymTab.ClEnum) THEN
  338. SemError(224) END; .)
  339. { ","
  340. SimpleType<s2> (. IF (s2 # SymTab.InvalidType)
  341. & (SymTab.ClassOf(s2) #
  342. SymTab.ClInt)
  343. & (SymTab.ClassOf(s2) #
  344. SymTab.ClChar)
  345. & (SymTab.ClassOf(s2) #
  346. SymTab.ClEnum) THEN
  347. SemError(224) END; .) }
  348. "OF"
  349. Type<e> (. t := SymTab.NewArray(e); .) .
  350. RecordType <VAR t: SymTab.TypeIndex>
  351. = "RECORD" (. t := SymTab.NewRecord(); .)
  352. FieldSeq<t>
  353. "END" .
  354. FieldSeq <rt: SymTab.TypeIndex>
  355. = Field<rt> { ";"
  356. Field<rt> } .
  357. Field <rt: SymTab.TypeIndex>
  358. (. VAR et: SymTab.TypeIndex; .)
  359. = [ FieldIdents<rt> ":"
  360. Type<et> (. SymTab.FixPendingF(rt, et); .) ] .
  361. FieldIdents <rt: SymTab.TypeIndex>
  362. (. VAR n: SymTab.Name; .)
  363. = GetIdent<n> (. IF ~SymTab.FieldPending(rt, n)
  364. THEN SemError(200) END .)
  365. { ","
  366. GetIdent<n> (. IF ~SymTab.FieldPending(rt, n)
  367. THEN SemError(200) END .) } .
  368. SetType <VAR t: SymTab.TypeIndex>
  369. (. VAR s: SymTab.TypeIndex; .)
  370. = "SET"
  371. "OF"
  372. SimpleType<s> (. IF (s # SymTab.InvalidType)
  373. & (SymTab.ClassOf(s) #
  374. SymTab.ClInt)
  375. & (SymTab.ClassOf(s) #
  376. SymTab.ClChar)
  377. & (SymTab.ClassOf(s) #
  378. SymTab.ClEnum) THEN
  379. SemError(224) END;
  380. t := SymTab.NewSet(s); .) .
  381. PointerType <VAR t: SymTab.TypeIndex>
  382. (. VAR b: SymTab.TypeIndex; .)
  383. = "POINTER"
  384. "TO"
  385. Type<b> (. t := SymTab.NewPtr(b); .) .
  386. (* Statements: RETURN added; calls via AssignOrCall *)
  387. StatSeq = Stat { ";"
  388. Stat } .
  389. Stat (. VAR lx: INTEGER; .)
  390. = [ AssignOrCall | IfStat | CaseStat | WhileStat
  391. | RepeatStat | LoopStat | ForStat | WithStat | ReturnStat
  392. | "EXIT" (. IF MGen.TopLoop(lx) THEN
  393. MGen.Jmp(lx)
  394. ELSE SemError(230) END; .) ] .
  395. AssignOrCall (. VAR dt, et: SymTab.TypeIndex;
  396. dk: INTEGER;
  397. bn: SymTab.Name;
  398. lxD, lxe: MGen.LitStr;
  399. vE: BOOLEAN;
  400. vnE: SymTab.Name;
  401. sfx: BOOLEAN;
  402. okC: BOOLEAN;
  403. isR, conv,
  404. storable: BOOLEAN; .)
  405. = (. sfx := FALSE; .)
  406. DesignHead<dt, dk, bn, FALSE, lxD>
  407. ( DesignTail<dt, dk, bn, FALSE, lxD, sfx> ":="
  408. (. storable :=
  409. (dk = SymTab.KindVar)
  410. OR (dk = SymTab.KindParam)
  411. OR (dk = SymTab.KindVarPar);
  412. IF storable THEN
  413. MGen.StoreSetup(bn)
  414. END; .)
  415. Expr<et, lxe, vE, vnE> (. IF (dt # SymTab.InvalidType)
  416. & (dk # SymTab.KindVar)
  417. & (dk # SymTab.KindParam)
  418. & (dk # SymTab.KindVarPar)
  419. & (dk # SymTab.KindField)
  420. & (dk # SymTab.KindImport) THEN
  421. SemError(210)
  422. ELSIF ~SymTab.Assignable(et, dt) THEN
  423. SemError(210) END;
  424. IF dk = SymTab.KindImport THEN
  425. SemError(230)
  426. END;
  427. isR := (dt # SymTab.InvalidType)
  428. & (SymTab.ClassOf(dt)
  429. = SymTab.ClReal);
  430. conv := isR
  431. & SymTab.IsIntFamily(et);
  432. IF storable THEN
  433. IF conv THEN
  434. MGen.IntToReal
  435. END;
  436. MGen.StoreFinish(bn)
  437. ELSE MGen.Drop
  438. END; .)
  439. | CallTail<bn, sfx, FALSE, okC, FALSE>
  440. | (. MGen.ActBegin(bn);
  441. IF MGen.ActEnd(bn, FALSE, FALSE) # 0 THEN
  442. SemError(233)
  443. END; .) ) .
  444. CallTail <pn: SymTab.Name; sfx: BOOLEAN; inExpr: BOOLEAN;
  445. VAR ok: BOOLEAN; hasDead: BOOLEAN>
  446. (. VAR t: SymTab.TypeIndex;
  447. lx: MGen.LitStr;
  448. v: BOOLEAN;
  449. vn: SymTab.Name; .)
  450. = "(" (. ok := FALSE;
  451. IF hasDead THEN MGen.Drop END;
  452. MGen.ActBegin(pn); .)
  453. [ Expr<t, lx, v, vn> (. IF MGen.ActValue(t, v, vn) # 0 THEN
  454. SemError(233)
  455. END; .)
  456. { "," Expr<t, lx, v, vn> (. IF MGen.ActValue(t, v, vn) # 0 THEN
  457. SemError(233)
  458. END; .) } ]
  459. ")" (. IF MGen.ActEnd(pn, sfx, inExpr) # 0
  460. THEN SemError(233)
  461. ELSE ok := TRUE
  462. END; .) .
  463. IfStat (. VAR t: SymTab.TypeIndex;
  464. lxC: MGen.LitStr;
  465. vC: BOOLEAN;
  466. vnC: SymTab.Name;
  467. elseL, endL: INTEGER;
  468. hasElse: BOOLEAN; .)
  469. = "IF"
  470. Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
  471. SemError(214) END;
  472. elseL := MGen.NewLabel();
  473. endL := MGen.NewLabel();
  474. MGen.Jz(elseL);
  475. hasElse := FALSE; .)
  476. "THEN"
  477. StatSeq
  478. { "ELSIF" (. MGen.Jmp(endL);
  479. MGen.DefLabel(elseL); .)
  480. Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
  481. SemError(214) END;
  482. elseL := MGen.NewLabel();
  483. MGen.Jz(elseL); .)
  484. "THEN"
  485. StatSeq }
  486. [ "ELSE" (. MGen.Jmp(endL);
  487. MGen.DefLabel(elseL);
  488. hasElse := TRUE; .)
  489. StatSeq ]
  490. "END" (. IF ~hasElse THEN
  491. MGen.DefLabel(elseL)
  492. END;
  493. MGen.DefLabel(endL); .) .
  494. CaseStat (. VAR st: SymTab.TypeIndex;
  495. lxS: MGen.LitStr;
  496. vS: BOOLEAN;
  497. vnS: SymTab.Name;
  498. tmp, endL: INTEGER; .)
  499. = "CASE"
  500. Expr<st, lxS, vS, vnS> (. tmp := MGen.TempGlobal();
  501. MGen.StoreTemp(tmp);
  502. endL := MGen.NewLabel(); .)
  503. "OF"
  504. Case<st, tmp, endL> { "|"
  505. Case<st, tmp, endL> }
  506. [ "ELSE"
  507. StatSeq ]
  508. "END" (. MGen.DefLabel(endL); .) .
  509. Case <sel: SymTab.TypeIndex; tmp: INTEGER; endL: INTEGER>
  510. (. VAR lB, lN: INTEGER; .)
  511. = [ LabelList<sel, tmp, lB, lN> ":" (. MGen.DefLabel(lB); .)
  512. StatSeq (. MGen.Jmp(endL);
  513. MGen.DefLabel(lN); .) ] .
  514. LabelList <sel: SymTab.TypeIndex; tmp: INTEGER;
  515. VAR lB: INTEGER; VAR lN: INTEGER>
  516. = (. lB := MGen.NewLabel();
  517. lN := MGen.NewLabel(); .)
  518. Labels<sel, tmp, lB> { ","
  519. Labels<sel, tmp, lB> }
  520. (. MGen.Jmp(lN); .) .
  521. Labels <sel: SymTab.TypeIndex; tmp: INTEGER; bodyL: INTEGER>
  522. (. VAR t, t2: SymTab.TypeIndex;
  523. lx1, lx2: MGen.LitStr;
  524. v1, v2: BOOLEAN;
  525. vn1, vn2: SymTab.Name;
  526. ta, tb, chunk: INTEGER;
  527. r, hasRange: BOOLEAN; .)
  528. = ConstExpr<t, lx1> (. IF ~SymTab.EqCheck(t, sel) THEN
  529. SemError(213) END;
  530. r := (SymTab.ClassOf(sel)
  531. = SymTab.ClReal)
  532. & (SymTab.ClassOf(t)
  533. = SymTab.ClReal);
  534. ta := MGen.TempGlobal();
  535. MGen.StoreTemp(ta);
  536. hasRange := FALSE; .)
  537. [ ".."
  538. ConstExpr<t2, lx2> (. IF ~SymTab.EqCheck(t2, sel) THEN
  539. SemError(213) END;
  540. tb := MGen.TempGlobal();
  541. MGen.StoreTemp(tb);
  542. hasRange := TRUE; .) ]
  543. (. IF hasRange THEN
  544. MGen.LoadTemp(tmp);
  545. MGen.LoadTemp(ta);
  546. IF r THEN MGen.RealGe
  547. ELSE MGen.IGe END;
  548. MGen.LoadTemp(tmp);
  549. MGen.LoadTemp(tb);
  550. IF r THEN MGen.RealLe
  551. ELSE MGen.ILe END;
  552. MGen.And
  553. ELSE
  554. MGen.LoadTemp(tmp);
  555. MGen.LoadTemp(ta);
  556. IF r THEN MGen.RealEq
  557. ELSE MGen.Eq END
  558. END;
  559. chunk := MGen.NewLabel();
  560. MGen.Jz(chunk);
  561. MGen.Jmp(bodyL);
  562. MGen.DefLabel(chunk); .) .
  563. WhileStat (. VAR t: SymTab.TypeIndex;
  564. lxC: MGen.LitStr;
  565. vC: BOOLEAN;
  566. vnC: SymTab.Name;
  567. topL, endL: INTEGER; .)
  568. = "WHILE" (. topL := MGen.NewLabel();
  569. endL := MGen.NewLabel();
  570. MGen.DefLabel(topL); .)
  571. Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
  572. SemError(214) END;
  573. MGen.Jz(endL); .)
  574. "DO"
  575. StatSeq
  576. "END" (. MGen.Jmp(topL);
  577. MGen.DefLabel(endL); .) .
  578. RepeatStat (. VAR t: SymTab.TypeIndex;
  579. lxC: MGen.LitStr;
  580. vC: BOOLEAN;
  581. vnC: SymTab.Name;
  582. topL: INTEGER; .)
  583. = "REPEAT" (. topL := MGen.NewLabel();
  584. MGen.DefLabel(topL); .)
  585. StatSeq
  586. "UNTIL"
  587. Expr<t, lxC, vC, vnC> (. IF ~SymTab.BoolCheck(t) THEN
  588. SemError(214) END;
  589. MGen.Jz(topL); .) .
  590. LoopStat (. VAR topL, exitL: INTEGER; .)
  591. = "LOOP" (. topL := MGen.NewLabel();
  592. exitL := MGen.NewLabel();
  593. MGen.DefLabel(topL);
  594. MGen.PushLoop(exitL); .)
  595. StatSeq
  596. "END" (. MGen.Jmp(topL);
  597. MGen.DefLabel(exitL);
  598. MGen.PopLoop; .) .
  599. ForStat (. VAR n, lv: SymTab.Name;
  600. fk: INTEGER;
  601. lo, hi: SymTab.TypeIndex;
  602. lxLo, lxHi: MGen.LitStr;
  603. vLo, vHi: BOOLEAN;
  604. vnLo, vnHi: SymTab.Name;
  605. byV, ht: INTEGER;
  606. lTop, lChk, lEnd: INTEGER;
  607. neg, storable: BOOLEAN; .)
  608. = "FOR"
  609. GetIdent<n> (. IF ~SymTab.Lookup(n) THEN
  610. SemError(201);
  611. fk := -1
  612. ELSIF (SymTab.SymKind(n) #
  613. SymTab.KindVar)
  614. & (SymTab.SymKind(n) #
  615. SymTab.KindParam)
  616. & (SymTab.SymKind(n) #
  617. SymTab.KindVarPar)
  618. & (SymTab.SymKind(n) #
  619. SymTab.KindField) THEN
  620. SemError(220);
  621. fk := -1
  622. ELSIF (SymTab.SymType(n) #
  623. SymTab.InvalidType)
  624. & ~SymTab.IsIntFamily(
  625. SymTab.SymType(n)) THEN
  626. SemError(220);
  627. fk := -1
  628. ELSE
  629. fk := SymTab.SymKind(n)
  630. END;
  631. MGen.CopyName(n, lv);
  632. storable := (fk = SymTab.KindVar)
  633. OR (fk = SymTab.KindParam)
  634. OR (fk = SymTab.KindVarPar);
  635. IF storable THEN
  636. MGen.StoreSetup(lv)
  637. END; .)
  638. ":="
  639. Expr<lo, lxLo, vLo, vnLo> (. IF (lo # SymTab.InvalidType)
  640. & ~SymTab.IsIntFamily(lo) THEN
  641. SemError(220) END;
  642. IF storable THEN
  643. MGen.StoreFinish(lv)
  644. ELSE MGen.Drop
  645. END; .)
  646. "TO"
  647. Expr<hi, lxHi, vHi, vnHi> (. IF (hi # SymTab.InvalidType)
  648. & ~SymTab.IsIntFamily(hi) THEN
  649. SemError(220) END;
  650. ht := MGen.TempGlobal();
  651. MGen.StoreTemp(ht);
  652. byV := 1; neg := FALSE; .)
  653. [ "BY"
  654. ByLit<byV> (. neg := byV < 0; .) ]
  655. "DO" (. lTop := MGen.NewLabel();
  656. lChk := MGen.NewLabel();
  657. lEnd := MGen.NewLabel();
  658. MGen.Jmp(lChk);
  659. MGen.DefLabel(lTop); .)
  660. StatSeq
  661. "END" (. MGen.PushVar(lv);
  662. MGen.PushInt(byV);
  663. MGen.Add;
  664. IF storable THEN
  665. MGen.StoreFinish(lv)
  666. ELSE MGen.Drop
  667. END;
  668. MGen.DefLabel(lChk);
  669. MGen.PushVar(lv);
  670. MGen.LoadTemp(ht);
  671. IF neg THEN MGen.IGe
  672. ELSE MGen.ILe END;
  673. MGen.Jz(lEnd);
  674. MGen.Jmp(lTop);
  675. MGen.DefLabel(lEnd); .) .
  676. ByLit <VAR v: INTEGER> (. VAR s: ARRAY [0 .. 255] OF CHAR; .)
  677. = integer (. LexString(s);
  678. IF ~MGen.ParseInt(s, v) THEN
  679. v := 1
  680. END; .)
  681. | "-" integer (. LexString(s);
  682. IF MGen.ParseInt(s, v) THEN
  683. v := -v
  684. ELSE v := -1
  685. END; .) .
  686. WithStat (. VAR dt: SymTab.TypeIndex;
  687. dk: INTEGER;
  688. bnW: SymTab.Name;
  689. lxW: MGen.LitStr;
  690. pushed: BOOLEAN; .)
  691. = "WITH"
  692. Design<dt, dk, bnW, FALSE, lxW> (. pushed := FALSE;
  693. IF dt # SymTab.InvalidType THEN
  694. pushed :=
  695. SymTab.PushRecord(dt);
  696. IF ~pushed THEN
  697. SemError(215)
  698. END
  699. END;
  700. IF pushed THEN
  701. MGen.NoSupEnter;
  702. SemError(230)
  703. END; .)
  704. "DO"
  705. StatSeq
  706. "END" (. IF pushed THEN
  707. SymTab.PopScope;
  708. MGen.NoSupExit
  709. END; .) .
  710. ReturnStat (. VAR t: SymTab.TypeIndex;
  711. lx: MGen.LitStr;
  712. v: BOOLEAN;
  713. vn: SymTab.Name;
  714. hasE, doRet, conv: BOOLEAN; .)
  715. = "RETURN" (. hasE := FALSE; .)
  716. [ Expr<t, lx, v, vn> (. hasE := TRUE;
  717. doRet := FALSE;
  718. IF ~SymTab.InProc() THEN
  719. SemError(232)
  720. ELSIF ~SymTab.InFunction() THEN
  721. SemError(232)
  722. ELSIF ~SymTab.Assignable(
  723. t, SymTab.CurRet()) THEN
  724. SemError(232)
  725. ELSE doRet := TRUE
  726. END;
  727. conv := doRet
  728. & SymTab.IsIntFamily(t)
  729. & (SymTab.ClassOf(
  730. SymTab.CurRet())
  731. = SymTab.ClReal);
  732. IF doRet THEN
  733. IF conv THEN
  734. MGen.IntToReal
  735. END;
  736. MGen.Leave(
  737. SymTab.CurNPar(), TRUE)
  738. ELSE MGen.Drop
  739. END; .) ]
  740. (. IF ~hasE THEN
  741. IF ~SymTab.InProc() THEN
  742. SemError(232)
  743. ELSIF SymTab.InFunction() THEN
  744. SemError(232)
  745. ELSE MGen.Leave(
  746. SymTab.CurNPar(), FALSE)
  747. END
  748. END; .) .
  749. (* Expressions: Designator without ActualParameters (calls use
  750. CallTail). Each expression synthesizes its SymTab type in t,
  751. the source text in lx for single literals ("" otherwise), and
  752. whether it is a plain variable (v/vn) for VAR actuals.
  753. Values travel on the MC64 stack. *)
  754. DesignHead <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  755. VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
  756. (. VAR n: SymTab.Name;
  757. cls: INTEGER; .)
  758. = GetIdent<n> (. MGen.CopyName(n, bn);
  759. lx[0] := 0C;
  760. IF ~SymTab.Lookup(n) THEN
  761. SemError(201);
  762. t := SymTab.InvalidType; k := -1;
  763. IF doLoad THEN
  764. MGen.PushInt(0)
  765. END
  766. ELSE
  767. t := SymTab.SymType(n);
  768. k := SymTab.SymKind(n);
  769. IF k = SymTab.KindConst THEN
  770. IF SymTab.Equal(n, "TRUE") THEN
  771. t := SymTab.BoolType();
  772. MGen.CopyName("TRUE", lx);
  773. IF doLoad THEN
  774. MGen.PushInt(1)
  775. END
  776. ELSIF SymTab.Equal(n,
  777. "FALSE") THEN
  778. t := SymTab.BoolType();
  779. MGen.CopyName("FALSE", lx);
  780. IF doLoad THEN
  781. MGen.PushInt(0)
  782. END
  783. ELSE
  784. cls :=
  785. SymTab.ClassOf(t);
  786. IF (t #
  787. SymTab.InvalidType)
  788. & (cls # SymTab.ClStr)
  789. & ((cls = SymTab.ClInt)
  790. OR (cls = SymTab.ClReal)
  791. OR (cls = SymTab.ClBool)
  792. OR (cls = SymTab.ClChar)
  793. OR (cls
  794. = SymTab.ClEnum)) THEN
  795. IF doLoad THEN
  796. MGen.LoadVar(n)
  797. END
  798. ELSIF doLoad THEN
  799. MGen.PushInt(0)
  800. END
  801. END
  802. ELSIF (k = SymTab.KindVar)
  803. OR (k = SymTab.KindParam)
  804. OR (k
  805. = SymTab.KindVarPar) THEN
  806. cls := SymTab.ClassOf(t);
  807. IF (cls = SymTab.ClInt)
  808. OR (cls = SymTab.ClReal)
  809. OR (cls = SymTab.ClBool)
  810. OR (cls = SymTab.ClChar)
  811. OR (cls
  812. = SymTab.ClEnum)
  813. OR (cls
  814. = SymTab.ClSet) THEN
  815. IF doLoad THEN
  816. MGen.PushVar(n)
  817. END
  818. ELSE SemError(230);
  819. IF doLoad THEN
  820. MGen.PushInt(0)
  821. END
  822. END
  823. ELSE
  824. IF doLoad THEN
  825. MGen.PushInt(0)
  826. END;
  827. IF k = SymTab.KindField THEN
  828. IF ~MGen.NoSup() THEN
  829. SemError(230)
  830. END
  831. ELSIF k
  832. = SymTab.KindImport THEN
  833. SemError(230)
  834. END
  835. END
  836. END; .) .
  837. DesignTail <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  838. VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr;
  839. VAR sfx: BOOLEAN>
  840. (. VAR m: SymTab.Name;
  841. it: SymTab.TypeIndex;
  842. lxI: MGen.LitStr;
  843. vI: BOOLEAN;
  844. vnI: SymTab.Name; .)
  845. = (. sfx := FALSE; .)
  846. { "." (. sfx := TRUE; lx[0] := 0C; .)
  847. GetIdent<m> (. IF t = SymTab.InvalidType THEN
  848. ELSIF SymTab.ClassOf(t) #
  849. SymTab.ClRecord THEN
  850. SemError(215);
  851. t := SymTab.InvalidType
  852. ELSIF ~SymTab.FieldExists(t, m) THEN
  853. SemError(216);
  854. t := SymTab.InvalidType
  855. ELSE t := SymTab.FieldType(t, m);
  856. SemError(230)
  857. END;
  858. IF doLoad THEN
  859. MGen.Drop; MGen.PushInt(0)
  860. END; .)
  861. | "[" (. sfx := TRUE; lx[0] := 0C; .)
  862. Expr<it, lxI, vI, vnI> (. MGen.Drop;
  863. IF t = SymTab.InvalidType THEN
  864. ELSIF SymTab.ClassOf(t) #
  865. SymTab.ClArray THEN
  866. SemError(217);
  867. t := SymTab.InvalidType
  868. ELSIF (it #
  869. SymTab.InvalidType)
  870. & ~SymTab.IsIntFamily(it) THEN
  871. SemError(218);
  872. t := SymTab.InvalidType
  873. ELSE t :=
  874. SymTab.ArrayElem(t);
  875. SemError(230)
  876. END;
  877. IF doLoad THEN
  878. MGen.Drop; MGen.PushInt(0)
  879. END; .)
  880. { ","
  881. Expr<it, lxI, vI, vnI> (. MGen.Drop;
  882. IF (it # SymTab.InvalidType)
  883. & ~SymTab.IsIntFamily(it) THEN
  884. SemError(218) END; .) }
  885. "]"
  886. | "^" (. sfx := TRUE; lx[0] := 0C; .)
  887. (. IF t = SymTab.InvalidType THEN
  888. ELSIF SymTab.ClassOf(t) #
  889. SymTab.ClPtr THEN
  890. SemError(219);
  891. t := SymTab.InvalidType
  892. ELSE t := SymTab.PtrBase(t);
  893. SemError(230)
  894. END;
  895. IF doLoad THEN
  896. MGen.Drop; MGen.PushInt(0)
  897. END; .) } .
  898. Design <VAR t: SymTab.TypeIndex; VAR k: INTEGER;
  899. VAR bn: SymTab.Name; doLoad: BOOLEAN; VAR lx: MGen.LitStr>
  900. (. VAR sfxD: BOOLEAN; .)
  901. = DesignHead<t, k, bn, doLoad, lx>
  902. DesignTail<t, k, bn, doLoad, lx, sfxD> .
  903. Expr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
  904. VAR v: BOOLEAN; VAR vn: SymTab.Name>
  905. (. VAR t2: SymTab.TypeIndex;
  906. tc, op: INTEGER;
  907. lx2: MGen.LitStr;
  908. v2: BOOLEAN;
  909. vn2: SymTab.Name;
  910. r: BOOLEAN; .)
  911. = SimExpr<t, lx, v, vn> [ Rel<op> SimExpr<t2, lx2, v2, vn2>
  912. (. lx[0] := 0C; v := FALSE;
  913. IF op = SymTab.OpIn THEN
  914. IF SymTab.InCheck(t, t2) THEN
  915. t := SymTab.BoolType();
  916. MGen.BitIn
  917. ELSE SemError(222);
  918. t := SymTab.InvalidType;
  919. MGen.Drop; MGen.Drop; MGen.PushInt(0)
  920. END
  921. ELSE
  922. tc := SymTab.ClassOf(t);
  923. IF SymTab.RelCheck(t, t2, op) THEN
  924. t := SymTab.BoolType()
  925. ELSE SemError(213); t := SymTab.InvalidType END;
  926. IF t # SymTab.InvalidType THEN
  927. r := tc = SymTab.ClReal;
  928. IF r THEN
  929. IF op = SymTab.OpEq THEN MGen.RealEq
  930. ELSIF (op = SymTab.OpNeq1)
  931. OR (op = SymTab.OpNeq2) THEN MGen.RealNe
  932. ELSIF op = SymTab.OpLt THEN MGen.RealLt
  933. ELSIF op = SymTab.OpLe THEN MGen.RealLe
  934. ELSIF op = SymTab.OpGt THEN MGen.RealGt
  935. ELSE MGen.RealGe END
  936. ELSE
  937. IF op = SymTab.OpEq THEN MGen.Eq
  938. ELSIF (op = SymTab.OpNeq1)
  939. OR (op = SymTab.OpNeq2) THEN MGen.Neq
  940. ELSIF op = SymTab.OpLt THEN MGen.ILt
  941. ELSIF op = SymTab.OpLe THEN MGen.ILe
  942. ELSIF op = SymTab.OpGt THEN MGen.IGt
  943. ELSE MGen.IGe END
  944. END
  945. ELSE MGen.Drop; MGen.Drop; MGen.PushInt(0)
  946. END
  947. END; .) ] .
  948. Rel <VAR op: INTEGER>
  949. = "=" (. op := SymTab.OpEq; .)
  950. | "#" (. op := SymTab.OpNeq1; .)
  951. | "<>" (. op := SymTab.OpNeq2; .)
  952. | "<" (. op := SymTab.OpLt; .)
  953. | "<=" (. op := SymTab.OpLe; .)
  954. | ">" (. op := SymTab.OpGt; .)
  955. | ">=" (. op := SymTab.OpGe; .)
  956. | "IN" (. op := SymTab.OpIn; .) .
  957. SimExpr <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
  958. VAR v: BOOLEAN; VAR vn: SymTab.Name>
  959. (. VAR t2, res2: SymTab.TypeIndex;
  960. op: INTEGER;
  961. lx2: MGen.LitStr;
  962. v2: BOOLEAN;
  963. vn2: SymTab.Name;
  964. neg, isR: BOOLEAN; .)
  965. = (. neg := FALSE; .)
  966. [ "+" | "-" (. neg := TRUE; .) ]
  967. Term<t, lx, v, vn> (. IF neg THEN
  968. v := FALSE;
  969. IF MGen.IsLit(lx) THEN
  970. MGen.NegFold(lx, lx)
  971. ELSE lx[0] := 0C
  972. END;
  973. IF SymTab.ClassOf(t)
  974. = SymTab.ClReal THEN
  975. MGen.NegReal
  976. ELSE MGen.NegInt
  977. END
  978. END; .)
  979. { AddOp<op> Term<t2, lx2, v2, vn2>
  980. (. lx[0] := 0C; v := FALSE;
  981. IF op = SymTab.OpOr THEN
  982. IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
  983. t := SymTab.BoolType()
  984. ELSE SemError(212); t := SymTab.InvalidType END;
  985. MGen.Or
  986. ELSE
  987. IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN t := res2
  988. ELSE SemError(211); t := SymTab.InvalidType END;
  989. isR := (t # SymTab.InvalidType)
  990. & (SymTab.ClassOf(t) = SymTab.ClReal);
  991. IF op = SymTab.OpAdd THEN
  992. IF isR THEN MGen.RealAdd ELSE MGen.Add END
  993. ELSE
  994. IF isR THEN MGen.RealSub ELSE MGen.Sub END
  995. END
  996. END; .) } .
  997. AddOp <VAR op: INTEGER>
  998. = "+" (. op := SymTab.OpAdd; .)
  999. | "-" (. op := SymTab.OpSub; .)
  1000. | "OR" (. op := SymTab.OpOr; .) .
  1001. Term <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
  1002. VAR v: BOOLEAN; VAR vn: SymTab.Name>
  1003. (. VAR t2, res2: SymTab.TypeIndex;
  1004. op: INTEGER;
  1005. lx2: MGen.LitStr;
  1006. v2: BOOLEAN;
  1007. vn2: SymTab.Name;
  1008. isR: BOOLEAN;
  1009. mt: INTEGER; .)
  1010. = Fact<t, lx, v, vn> { MulOp<op> Fact<t2, lx2, v2, vn2>
  1011. (. lx[0] := 0C; v := FALSE;
  1012. IF op = SymTab.OpAnd THEN
  1013. IF SymTab.BoolCheck(t) & SymTab.BoolCheck(t2) THEN
  1014. t := SymTab.BoolType()
  1015. ELSE SemError(212); t := SymTab.InvalidType END;
  1016. MGen.And
  1017. ELSE
  1018. IF SymTab.ArithCheck(t, t2,
  1019. (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
  1020. res2) THEN t := res2
  1021. ELSE SemError(211); t := SymTab.InvalidType END;
  1022. isR := (t # SymTab.InvalidType)
  1023. & (SymTab.ClassOf(t) = SymTab.ClReal);
  1024. IF op = SymTab.OpTimes THEN
  1025. IF isR THEN MGen.RealMul ELSE MGen.MulU END
  1026. ELSIF op = SymTab.OpSlash THEN
  1027. IF isR THEN MGen.RealDiv ELSE MGen.DivI END
  1028. ELSIF op = SymTab.OpDiv THEN
  1029. MGen.DivI
  1030. ELSE
  1031. mt := MGen.TempGlobal();
  1032. MGen.ModI(mt)
  1033. END
  1034. END; .) } .
  1035. MulOp <VAR op: INTEGER>
  1036. = "*" (. op := SymTab.OpTimes; .)
  1037. | "/" (. op := SymTab.OpSlash; .)
  1038. | "DIV" (. op := SymTab.OpDiv; .)
  1039. | "MOD" (. op := SymTab.OpMod; .)
  1040. | "AND" (. op := SymTab.OpAnd; .)
  1041. | "&" (. op := SymTab.OpAnd; .) .
  1042. Fact <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
  1043. VAR v: BOOLEAN; VAR vn: SymTab.Name>
  1044. (. VAR s: ARRAY [0 .. 255] OF CHAR;
  1045. t2, et, dt, st: SymTab.TypeIndex;
  1046. dk: INTEGER;
  1047. bnF: SymTab.Name;
  1048. lxD, lx2: MGen.LitStr;
  1049. v2: BOOLEAN;
  1050. vn2: SymTab.Name;
  1051. vi: INTEGER;
  1052. c: CARDINAL;
  1053. b: LONGCARD;
  1054. sfxF: BOOLEAN;
  1055. okF: BOOLEAN; .)
  1056. = integer (. LexString(s);
  1057. MGen.CopyName(s, lx);
  1058. v := FALSE;
  1059. IF MGen.ParseInt(s, vi) THEN
  1060. MGen.PushInt(vi)
  1061. ELSIF MGen.ParseCard(s, c) THEN
  1062. MGen.PushBits(
  1063. VAL(LONGCARD, c))
  1064. ELSE MGen.PushInt(0)
  1065. END;
  1066. t := SymTab.IntType(); .)
  1067. | real (. LexString(s);
  1068. MGen.CopyName(s, lx);
  1069. v := FALSE;
  1070. IF MGen.ParseReal(s, b) THEN
  1071. MGen.PushBits(b)
  1072. ELSE MGen.PushBits(0H)
  1073. END;
  1074. t := SymTab.RealType(); .)
  1075. | string (. LexString(s);
  1076. v := FALSE;
  1077. IF SymTab.StrLen(s) <= 3 THEN
  1078. t := SymTab.CharType();
  1079. MGen.CopyName(s, lx);
  1080. MGen.PushInt(
  1081. MGen.CharOrd(s))
  1082. ELSE t := SymTab.NewStr();
  1083. SemError(230);
  1084. lx[0] := 0C;
  1085. MGen.PushInt(0)
  1086. END; .)
  1087. | DesignHead<dt, dk, bnF, TRUE, lxD>
  1088. DesignTail<dt, dk, bnF, TRUE, lxD, sfxF>
  1089. (. t := dt;
  1090. MGen.CopyName(lxD, lx);
  1091. v := ~sfxF
  1092. & ((dk = SymTab.KindVar)
  1093. OR (dk = SymTab.KindParam)
  1094. OR (dk
  1095. = SymTab.KindVarPar));
  1096. MGen.CopyName(bnF, vn); .)
  1097. [ CallTail<bnF, sfxF, TRUE, okF, TRUE>
  1098. (. IF okF THEN
  1099. IF SymTab.SymKind(bnF)
  1100. = SymTab.KindProc THEN
  1101. t := SymTab.ProcRet(bnF)
  1102. ELSE
  1103. t := SymTab.InvalidType
  1104. END
  1105. ELSE t := SymTab.InvalidType
  1106. END;
  1107. lx[0] := 0C; v := FALSE; .) ]
  1108. | "("
  1109. Expr<et, lx, v, vn> ")" (. t := et; .)
  1110. | ( "NOT" | "~" )
  1111. Fact<t2, lx2, v2, vn2> (. lx[0] := 0C; v := FALSE;
  1112. IF SymTab.BoolCheck(t2) THEN
  1113. t := SymTab.BoolType()
  1114. ELSE SemError(212);
  1115. t := SymTab.InvalidType END;
  1116. MGen.Not; .)
  1117. | SetLit<st> (. lx[0] := 0C; v := FALSE;
  1118. t := st; .) .
  1119. SetLit <VAR t: SymTab.TypeIndex>
  1120. (. VAR first, et: SymTab.TypeIndex;
  1121. lxE, lxE2: MGen.LitStr;
  1122. vE, vE2: BOOLEAN;
  1123. vnE, vnE2: SymTab.Name;
  1124. hasR: BOOLEAN; .)
  1125. = "{"
  1126. (. MGen.PushInt(0);
  1127. t := SymTab.SetFor(SymTab.IntType()); .)
  1128. [ Elem<et, lxE, lxE2, hasR> (. first := et;
  1129. t := SymTab.SetFor(et);
  1130. IF hasR THEN MGen.FieldMask
  1131. ELSE MGen.Power2 END;
  1132. MGen.Or; .)
  1133. { ","
  1134. Elem<et, lxE, lxE2, hasR> (. IF ~SymTab.SetElemCheck(first, et) THEN
  1135. SemError(222) END;
  1136. IF hasR THEN MGen.FieldMask
  1137. ELSE MGen.Power2 END;
  1138. MGen.Or; .) } ]
  1139. "}" .
  1140. Elem <VAR t: SymTab.TypeIndex; VAR lx: MGen.LitStr;
  1141. VAR lx2: MGen.LitStr; VAR hasR: BOOLEAN>
  1142. (. VAR t2: SymTab.TypeIndex;
  1143. vD, vD2: BOOLEAN;
  1144. vnD, vnD2: SymTab.Name; .)
  1145. = Expr<t, lx, vD, vnD> (. hasR := FALSE;
  1146. lx2[0] := 0C; .)
  1147. [ ".."
  1148. Expr<t2, lx2, vD2, vnD2> (. IF ~SymTab.SetElemCheck(t, t2) THEN
  1149. SemError(222) END;
  1150. hasR := TRUE; .) ] .
  1151. GetIdent <VAR n: SymTab.Name>
  1152. = ident (. LexName(n); .) .
  1153. END M2c.