FILE: M2QImpl.mesa
Modula-2 Parser, Part 2
Last Edited by: Gutknecht, September 19, 1985 3:21:10 am PDT
DIRECTORY
M2D USING [StrForm, ObjPtr, ConstPtr, VarPtr, ProcPtr, CodePtr, FieldPtr, StrPtr, EnumPtr, RangePtr, SetPtr, PointerPtr, ProcTypPtr, ArrayPtr, RecordPtr, ParPtr, WordSize, Proc, undftyp, notyp, inttyp, cardtyp, dbltyp, realtyp, bitstyp, chartyp, stringtyp, UNION],
M2F USING [GenStParam, GenStFct],
M2G USING [LabelTabPtr, LabelTable, NofCases, GenItem, GenSingSet, GenSet, GenTrap, GenIndex, GenField, GenDeRef, PrepCall, GenCall, GenParam],
M2H USING [ItemPtr, Item, LoadAdr, Load, LoadStk, GenIn, GenOp, GenNeg, GenNot, GenAnd, GenOr],
M2I USING [pc, AllocString],
M2S USING [Symbol, sym, numtyp, intval, dblval, realval, id, GetSym, KeepId, Mark],
M2T USING [Scope, LastObj, NewScope, NewObj, NewStr, NewPar, CloseScope, ParamLink, Find, FindExport, FindField],
M2Q;
M2QImpl: CEDAR PROGRAM
IMPORTS M2D, M2F, M2G, M2H, M2I, M2S, M2T
EXPORTS M2Q =
BEGIN OPEN M2Q;
MaxInt: CARDINAL = 77777B;
EnumTypSize : CARDINAL = 1;
SetTypSize: CARDINAL = 1;
PointerTypSize: CARDINAL = 1;
ProcTypSize: CARDINAL = 1;
DynArrDesSize: CARDINAL = 2;
dummyContxt: M2D.ProcPtr ← NEW [M2D.Proc ← [cell: 2]];
InitQ: PUBLIC PROC = {};
err: PROC [n: CARDINAL] = { M2S.Mark [n] };
CheckSym: PROC [s: M2S.Symbol, n: CARDINAL] =
{ IF M2S.sym = s THEN M2S.GetSym ELSE M2S.Mark [n] };
qualident: PROC RETURNS [obj: M2D.ObjPtr] =
{ -- sym = ident --
obj ← M2T.Find [M2S.id];
M2S.GetSym;
WHILE (M2S.sym = period) AND (obj # NIL) AND (obj^.class = Module) DO
M2S.GetSym;
IF M2S.sym = ident THEN
{ obj ← M2T.FindExport [M2S.id, NARROW [obj^.ext]]; M2S.GetSym }
ELSE err [10]
ENDLOOP };
CheckComp: PROC [t0, t1: M2D.StrPtr] =
{ IF (t0 # t1) AND ((t0 # M2D.inttyp) OR (t1 # M2D.cardtyp)) THEN err [61] };
CaseLabelList: PUBLIC PROC [Ltyp: M2D.StrPtr, n: CARDINAL, tab: M2G.LabelTabPtr] RETURNS [N: CARDINAL] =
{ x: M2H.ItemPtr ← NEW [M2H.Item];
y: M2H.ItemPtr ← NEW [M2H.Item];
f: M2D.StrForm ← Ltyp^.form;
IF f = Range THEN
{ range: M2D.RangePtr ← NARROW [Ltyp^.ext]; Ltyp ← range^.BaseTyp }
ELSE
IF (f > Int) AND (f # Enum) THEN err [38];
DO ConstExpression [x]; CheckComp [Ltyp, x.typ];
IF M2S.sym = ellipsis THEN
{ M2S.GetSym; ConstExpression [y]; CheckComp [Ltyp, y.typ] }
ELSE y^ ← x^;
enter label range into ordered table --
IF n < M2G.NofCases THEN { i: CARDINAL ← n;
DO
IF i = 0 THEN EXIT;
IF tab[i-1].low <= y.val.I THEN
{ IF tab[i-1].high >= x.val.I THEN err [62];
EXIT };
tab[i] ← tab[i-1]; i ← i-1
ENDLOOP;
tab[i].low ← x.val.I; tab[i].high ← y.val.I; tab[i].label ← M2I.pc;
n ← n + 1 }
ELSE err [92];
IF M2S.sym = comma THEN M2S.GetSym
ELSE
IF (M2S.sym >= lparen) AND (M2S.sym <= ident) THEN err [11]
ELSE EXIT
ENDLOOP;
N ← n };
FieldListSequence: PROC [adr: CARDINAL] RETURNS [maxAdr: CARDINAL] =
{fld0, fld1, tagfldtyp: M2D.ObjPtr; typ: M2D.StrPtr;
VariantPart: PROC =
{ tabPtr: M2G.LabelTabPtr ← NEW [M2G.LabelTable];
lastadr: CARDINAL; N: CARDINAL;
maxAdr ← adr; N ← 0;
DO
IF M2S.sym < bar THEN
{ N ← CaseLabelList [typ, N, tabPtr]; CheckSym [colon, 13];
lastadr ← FieldListSequence [adr];
IF lastadr > maxAdr THEN maxAdr ← lastadr };
IF M2S.sym = bar THEN M2S.GetSym ELSE EXIT
ENDLOOP;
IF M2S.sym = else THEN
{ M2S.GetSym; lastadr ← FieldListSequence [adr];
IF lastadr > maxAdr THEN maxAdr ← lastadr }};
typ ← M2D.undftyp;
IF (M2S.sym = ident) OR (M2S.sym = case) THEN
DO
IF M2S.sym = ident THEN
{ fld0 ← M2T.LastObj []; fld1 ← fld0;
DO
IF M2S.sym = ident THEN
{ fld1 ← M2T.NewObj [M2S.id, Field]; M2S.KeepId; M2S.GetSym }
ELSE err [10];
IF M2S.sym = comma THEN M2S.GetSym
ELSE IF M2S.sym = ident THEN err [11]
ELSE EXIT
ENDLOOP;
CheckSym [colon, 13]; typ ← Type [];
WHILE fld0 # fld1 DO fld0 ← fld0^.next;
{ field: M2D.FieldPtr ← NARROW [fld0^.ext];
fld0^.typ ← typ; field^.offset ← adr };
adr ← adr + typ^.size
ENDLOOP }
ELSE IF M2S.sym = case THEN
{ M2S.GetSym; fld1 ← NIL; tagfldtyp ← NIL;
IF M2S.sym = ident THEN
{ fld1 ← M2T.NewObj [M2S.id, Field]; M2S.KeepId; M2S.GetSym };
CheckSym [colon, 13];
IF M2S.sym = ident THEN tagfldtyp ← qualident [] ELSE err [10];
IF (tagfldtyp # NIL) AND (tagfldtyp^.class = Typ) THEN typ ← tagfldtyp^.typ
ELSE err [52];
IF fld1 # NIL THEN
{ field: M2D.FieldPtr ← NARROW [fld1^.ext];
field^.offset ← adr; fld1^.typ ← typ; adr ← adr + typ^.size };
CheckSym [of, 23]; VariantPart; adr ← maxAdr;
CheckSym [end, 20] };
IF M2S.sym = semicolon THEN M2S.GetSym
ELSE IF M2S.sym = ident THEN err [12]
ELSE EXIT
ENDLOOP;
maxAdr ← adr };
SubRange: PROC RETURNS [typ: M2D.StrPtr] =
{ x: M2H.ItemPtr ← NEW [M2H.Item];
y: M2H.ItemPtr ← NEW [M2H.Item];
f: M2D.StrForm; range: M2D.RangePtr ← NIL;
typ ← M2T.NewStr [Range]; range ← NARROW [typ^.ext];
ConstExpression [x]; f ← x^.typ^.form;
IF (f <= Int) OR (f = Enum) THEN range^.min ← x^.val.I ELSE err [82];
CheckSym [ellipsis, 21]; ConstExpression [y]; CheckComp [x^.typ, y^.typ];
IF (y^.typ = M2D.cardtyp) AND (y^.val.C > MaxInt) THEN err [95];
range^.max ← y^.val.I;
IF range^.min > range^.max THEN err [63];
range^.BaseTyp ← x^.typ; typ^.size ← x^.typ^.size };
SimpleType: PROC RETURNS [typ: M2D.StrPtr] =
{ obj: M2D.ObjPtr; typ0: M2D.StrPtr; n: CARDINAL;
range: M2D.RangePtr ← NIL; enum: M2D.EnumPtr ← NIL;
typ ← M2D.undftyp;
IF M2S.sym = ident THEN { obj ← qualident [];
IF (obj # NIL) AND (obj^.class = Typ) THEN typ ← obj^.typ ELSE err [52];
IF M2S.sym = lbrak THEN { M2S.GetSym;
typ0 ← typ; typ ← SubRange []; range ← NARROW [typ^.ext];
IF range^.BaseTyp # typ0 THEN
IF (typ0 = M2D.inttyp) AND(range^.BaseTyp = M2D.cardtyp) THEN
range^.BaseTyp ← M2D.inttyp
ELSE err [61];
IF M2S.sym = rbrak THEN M2S.GetSym
ELSE
{ err [16]; IF M2S.sym = rparen THEN M2S.GetSym }}}
ELSE IF M2S.sym = lparen THEN { M2S.GetSym;
typ ← M2T.NewStr [Enum]; enum ← NARROW [typ^.ext];
obj ← NIL; n ← 0;
DO const: M2D.ConstPtr ← NIL;
IF M2S.sym = ident THEN
{ obj ← M2T.NewObj [M2S.id, Const]; M2S.KeepId;
const ← NARROW [obj^.ext]; const^.conval.C ← n;
n ← n + 1; obj^.typ ← typ;
M2S.GetSym }
ELSE err [10];
IF M2S.sym = comma THEN M2S.GetSym
ELSE IF M2S.sym = ident THEN err [11]
ELSE EXIT
ENDLOOP;
enum^.NofConst ← n; typ^.size ← EnumTypSize;
CheckSym [rparen, 15] }
ELSE IF M2S.sym = lbrak THEN
{ M2S.GetSym; typ ← SubRange [];
IF M2S.sym = rbrak THEN M2S.GetSym
ELSE { err [16];
IF M2S.sym = rparen THEN M2S.GetSym }}
ELSE err [32] };
FormalType: PUBLIC PROC RETURNS [typ: M2D.StrPtr] =
{ objtyp: M2D.ObjPtr; array: M2D.ArrayPtr ← NIL;
typ ← M2D.undftyp;
IF M2S.sym = array THEN { M2S.GetSym;
typ ← M2T.NewStr [Array]; array ← NARROW [typ^.ext];
typ^.strobj ← NIL; typ^.size ← DynArrDesSize; array^.dyn ← TRUE;
CheckSym [of, 23];
IF M2S.sym = ident THEN { objtyp ← qualident [];
IF (objtyp # NIL) AND (objtyp^.class = Typ) THEN
array^.ElemTyp ← objtyp^.typ
ELSE err [52] }
ELSE err [10] }
ELSE
IF M2S.sym = ident THEN
{ objtyp ← qualident [];
IF (objtyp # NIL) AND (objtyp^.class = Typ) THEN
typ ← objtyp^.typ
ELSE err [52] }
ELSE err [10] };
FormalTypeList: PROC [proctyp: M2D.ProcTypPtr] =
{ obj: M2D.ObjPtr; partyp: M2D.StrPtr; isvar: BOOLEAN;
IF (M2S.sym = ident) OR (M2S.sym = var) OR (M2S.sym = array) THEN
DO
IF M2S.sym = var THEN { M2S.GetSym; isvar ← TRUE }
ELSE isvar ← FALSE;
partyp ← FormalType []; M2T.NewPar [partyp, isvar];
IF M2S.sym = comma THEN M2S.GetSym
ELSE IF M2S.sym = ident THEN err [11]
ELSE EXIT
ENDLOOP;
CheckSym [rparen, 15]; proctyp^.firstPar ← M2T.ParamLink [];
IF M2S.sym = colon THEN
{ M2S.GetSym; proctyp^.resTyp ← M2D.undftyp;
IF M2S.sym = ident THEN { obj ← qualident [];
IF (obj # NIL) AND (obj^.class = Typ) THEN proctyp^.resTyp ← obj^.typ
ELSE err [52] }
ELSE err [10] }
ELSE proctyp^.resTyp ← M2D.notyp };
ArrayType: PROC RETURNS [typ: M2D.StrPtr] =
{ a, b: INTEGER; array: M2D.ArrayPtr ← NIL;
typ ← M2T.NewStr [Array]; array ← NARROW [typ^.ext];
array^.dyn ← FALSE; a ← 0;
array^.IndexTyp ← SimpleType [];
IF array^.IndexTyp^.form = Range THEN
{ range: M2D.RangePtr ← NARROW [array^.IndexTyp^.ext];
a ← range^.min; b ← range^.max }
ELSE { err [94]; b ← 0 };
IF M2S.sym = of THEN { M2S.GetSym; array^.ElemTyp ← Type [] }
ELSE
IF M2S.sym = comma THEN { M2S.GetSym; array^.ElemTyp ← ArrayType [] }
ELSE { err [23]; array^.ElemTyp ← M2D.undftyp };
a ← b-a+1; b ← array^.ElemTyp^.size;
IF array^.ElemTyp^.form = Char THEN {}
ELSE
IF MaxInt / b >= a THEN a ← a*b
ELSE { err [210]; a ← 1 };
typ^.size ← a };
OpaqueType: PUBLIC PROC RETURNS [typ: M2D.StrPtr] =
{ typ ← M2T.NewStr [Opaque]; typ^.size ← PointerTypSize };
Type: PUBLIC PROC RETURNS [typ: M2D.StrPtr] =
{ obj: M2D.ObjPtr; btyp: M2D.StrPtr;
IF M2S.sym < lparen THEN { err [33];
DO M2S.GetSym;
IF M2S.sym >= lparen THEN EXIT
ENDLOOP };
IF M2S.sym = array THEN { M2S.GetSym; typ ← ArrayType [] }
ELSE IF M2S.sym = record THEN
{ record: M2D.RecordPtr ← NIL; M2S.GetSym;
typ ← M2T.NewStr [Record]; record ← NARROW [typ^.ext];
obj ← M2T.NewScope [Typ]; -- header --
typ^.size ← FieldListSequence [0];
record^.firstFld ← obj^.next;
CheckSym [end, 20];
M2T.CloseScope }
ELSE IF M2S.sym = set THEN
{ set: M2D.SetPtr ← NIL; M2S.GetSym; CheckSym [of, 23];
typ ← M2T.NewStr [Set]; set ← NARROW [typ^.ext];
set^.BaseTyp ← SimpleType []; btyp ← set^.BaseTyp;
IF btyp^.form = Enum THEN
{ enum: M2D.EnumPtr ← NARROW [btyp^.ext];
IF enum^.NofConst > M2D.WordSize THEN err [209] }
ELSE IF btyp^.form = Range THEN
{ range: M2D.RangePtr ← NARROW [btyp^.ext];
IF (range^.min < 0) OR (range^.max >= M2D.WordSize) THEN err [209] }
ELSE err [60];
typ^.size ← SetTypSize }
ELSE IF M2S.sym = pointer THEN
{ pointer: M2D.PointerPtr ← NIL; M2S.GetSym;
typ ← M2T.NewStr [Pointer]; pointer ← NARROW [typ^.ext];
pointer^.BaseId ← 0; typ^.size ← PointerTypSize;
CheckSym [to, 24];
IF M2S.sym = ident THEN { obj ← qualident [];
IF obj = NIL THEN
{ pointer^.BaseTyp ← M2D.undftyp; pointer^.BaseId ← M2S.id;
M2S.KeepId-- forward ref --}
ELSE
IF obj^.class = Typ THEN pointer^.BaseTyp ← obj^.typ ELSE err [52] }
ELSE pointer^.BaseTyp ← Type [] }
ELSE IF M2S.sym = procedure THEN
{ proctyp: M2D.ProcTypPtr; M2S.GetSym;
typ ← M2T.NewStr [ProcTyp]; proctyp ← NARROW[typ^.ext];
typ^.size ← ProcTypSize;
IF M2S.sym = lparen THEN { M2S.GetSym; FormalTypeList [proctyp] }
ELSE proctyp^.resTyp ← NIL }
ELSE typ ← SimpleType [];
IF (M2S.sym < semicolon) OR (M2S.sym > else) THEN { err [34];
WHILE (M2S.sym < ident) OR (M2S.sym > else) AND (M2S.sym < begin) DO
M2S.GetSym
ENDLOOP }};
Selector: PUBLIC PROC [x: M2H.ItemPtr, obj: M2D.ObjPtr] =
{ y: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
M2G.GenItem [x, obj, M2T.Scope];
DO
IF M2S.sym = lbrak THEN { M2S.GetSym;
DO
M2H.LoadAdr [x]; Expression [y]; M2G.GenIndex [x, y];
IF M2S.sym = comma THEN M2S.GetSym ELSE EXIT
ENDLOOP;
CheckSym [rbrak, 16] }
ELSE IF M2S.sym = period THEN { M2S.GetSym;
IF M2S.sym = ident THEN
{ IF (x^.typ # NIL) AND (x^.typ^.form = Record) THEN
{ obj ← M2T.FindField [M2S.id, NARROW[x^.typ^.ext]];
M2G.GenField [x, obj] }
ELSE err [57];
M2S.GetSym }
ELSE err [10] }
ELSE IF M2S.sym = arrow THEN { M2S.GetSym; M2G.GenDeRef [x] }
ELSE EXIT
ENDLOOP };
FormalParameters: PUBLIC PROC [proc: M2D.ProcPtr] =
{ isvar: BOOLEAN; par, par0: M2D.ObjPtr; typ0: M2D.StrPtr;
proc^.cell ← 0; proc^.adr ← 0;
IF (M2S.sym = ident) OR (M2S.sym = var) THEN
DO par0 ← M2T.LastObj []; isvar ← FALSE;
IF M2S.sym = var THEN { M2S.GetSym; isvar ← TRUE };
DO
IF M2S.sym = ident THEN
{ par ← M2T.NewObj [M2S.id, Var]; M2S.KeepId; M2S.GetSym }
ELSE err [10];
IF M2S.sym = comma THEN M2S.GetSym
ELSE IF M2S.sym = ident THEN err [11]
ELSE IF M2S.sym = var THEN { err [11]; M2S.GetSym }
ELSE EXIT
ENDLOOP;
CheckSym [colon, 13];
typ0 ← FormalType []; par0 ← par0^.next;
WHILE par0 # NIL DO
var0: M2D.VarPtr ← NARROW [par0^.ext];
par0^.typ ← typ0; var0^.mod ← 0;
var0^.lev ← proc^.lev; var0^.varpar ← isvar;
IF proc^.cell >= 14 THEN { err [99]; proc^.cell ← 0 };
var0^.cell ← proc^.cell; proc^.cell ← proc^.cell + 1;
IF typ0^.form = Array THEN
{ array: M2D.ArrayPtr ← NARROW [typ0^.ext];
IF array^.dyn THEN
{ IF proc^.cell >= 14 THEN { err [99]; proc^.cell ← 0 };
proc^.cell ← proc^.cell + 1 } -- size
ELSE IF NOT isvar THEN proc^.adr ← proc^.adr + typ0^.size }
ELSE IF (typ0^.form = Record) AND NOT isvar THEN
proc^.adr ← proc^.adr + typ0^.size;
par0 ← par0^.next
ENDLOOP;
IF M2S.sym = semicolon THEN M2S.GetSym
ELSE IF M2S.sym = ident THEN err [12]
ELSE EXIT
ENDLOOP;
CheckSym [rparen, 15] };
ActualParameters: PUBLIC PROC [x: M2H.ItemPtr] =
{ apar: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
fpar: M2D.ParPtr ← M2G.PrepCall [x];
IF M2S.sym # rparen THEN
DO Expression [apar];
IF fpar # NIL THEN { M2G.GenParam [apar, fpar];
x^.expRegs ← M2D.UNION [x^.expRegs, apar^.expRegs]; fpar ← fpar^.next }
ELSE err [64];
IF M2S.sym = comma THEN M2S.GetSym
ELSE IF (M2S.sym >= lparen) AND (M2S.sym <= ident) THEN err [11]
ELSE EXIT
ENDLOOP;
IF fpar = NIL THEN M2G.GenCall [x] ELSE err [65] };
StandProcCall: PUBLIC PROC [p: M2H.ItemPtr] =
{ code: M2D.CodePtr ← NARROW [p^.obj^.ext];
m: CARDINAL ← code^.num; n: CARDINAL;
x: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: p^.contxt]];
IF m = 1 THEN
{ M2G.GenTrap [10]; p^.typ ← M2D.notyp }
ELSE { CheckSym [lparen, 22]; n ← 0;
DO Expression [x]; M2F.GenStParam [p, x, m, n]; n ← n + 1;
IF M2S.sym = comma THEN M2S.GetSym
ELSE IF M2S.sym # ident THEN EXIT
ENDLOOP;
CheckSym [rparen, 15];
M2F.GenStFct [p, m, n] }};
Element: PROC [x: M2H.ItemPtr] =
{ e1: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
e2: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
Expression [e1];
IF M2S.sym = ellipsis THEN { M2S.GetSym;
IF e1^.mode = conMd THEN { Expression [e2];
IF e2^.mode # conMd THEN err [90] }
ELSE { M2H.Load [e1]; Expression [e2] };
M2G.GenSet [x, e1, e2] }
ELSE M2G.GenSingSet [x, e1] };
Sets: PROC [x: M2H.ItemPtr, styp: M2D.StrPtr] =
{ y: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
x^.typ ← styp; y^.typ ← styp;
IF M2S.sym # rbrace THEN { Element [x];
DO
IF M2S.sym = comma THEN M2S.GetSym
ELSE
IF (M2S.sym >= lparen) AND (M2S.sym <= ident) THEN err [11]
ELSE EXIT;
M2H.Load [x];
Element [y]; M2H.Load [y];
M2H.GenOp [plus, x, y]
ENDLOOP }
ELSE { x^.mode ← conMd; x^.val.S ← ALL [FALSE] };
CheckSym [rbrace, 17] };
Factor: PROC [x: M2H.ItemPtr] =
{ obj: M2D.ObjPtr; xt: M2D.StrPtr;
IF M2S.sym < lparen THEN { err [31];
DO M2S.GetSym;
IF M2S.sym >= lparen THEN EXIT
ENDLOOP };
IF M2S.sym = ident THEN { obj ← qualident [];
IF M2S.sym = lbrace THEN { M2S.GetSym;
IF (obj # NIL) AND (obj^.class = Typ) AND (obj^.typ^.form = Set) THEN
Sets [x, obj^.typ]
ELSE { err [52]; Sets [x, M2D.bitstyp] }}
ELSE { Selector [x, obj];
IF x^.mode = codMd THEN
{ code: M2D.CodePtr ← NARROW [x^.obj^.ext];
IF code^.num > 0 THEN StandProcCall [x] }
ELSE IF M2S.sym = lparen THEN { M2S.GetSym;
IF x^.mode = typMd THEN -- type transfer function --
{ xt ← x^.typ; Expression [x]; M2H.Load [x];
IF xt^.size # x.typ^.size THEN err [81];
x^.typ ← xt }
ELSE ActualParameters [x];
CheckSym [rparen, 15] }}}
ELSE IF M2S.sym = number THEN
{ M2S.GetSym; x^.mode ← conMd;
SELECT M2S.numtyp FROM
cardint => { x^.typ ← M2D.cardtyp; x^.val.C ← M2S.intval };
longint => { x^.typ ← M2D.dbltyp; x^.val.D ← M2S.dblval };
char => { x^.typ ← M2D.chartyp; x^.val.C ← M2S.intval };
real => { x^.typ ← M2D.realtyp; x^.val.R ← M2S.realval };
longreal => { x^.typ ← M2D.realtyp; x^.val.R ← M2S.realval }
ENDCASE }
ELSE IF M2S.sym = string THEN
{ x^.typ ← M2D.stringtyp; x^.mode ← conMd;
[ x^.val.D0, x^.val.D1 ] ← M2I.AllocString [M2S.id];
M2S.GetSym }
ELSE IF M2S.sym = lparen THEN
{ M2S.GetSym; Expression [x]; CheckSym [rparen, 15] }
ELSE IF M2S.sym = lbrace THEN
{ M2S.GetSym; Sets [x, M2D.bitstyp] }
ELSE IF M2S.sym = not THEN
{ M2S.GetSym; Factor [x]; M2H.GenNot [x] }
ELSE { err [31]; x^.typ ← M2D.undftyp; x^.mode ← stkMd }};
Term: PROC [x: M2H.ItemPtr] =
{ y: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
mulop: M2S.Symbol;
Factor [x];
WHILE (M2S.sym >= times) AND (M2S.sym <= and) DO
mulop ← M2S.sym; M2S.GetSym;
IF x^.mode # conMd THEN
IF x^.typ^.form = Set THEN M2H.Load [x] ELSE M2H.LoadStk [x];
IF mulop = and THEN M2H.GenAnd [x];
Factor [y];
IF y^.mode # conMd THEN
IF y^.typ^.form = Set THEN M2H.Load [y] ELSE M2H.LoadStk [y];
M2H.GenOp [mulop, x, y]
ENDLOOP };
SimpleExpression: PROC [x: M2H.ItemPtr] =
{ y: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
addop: M2S.Symbol;
IF M2S.sym = minus THEN { M2S.GetSym; Term [x]; M2H.GenNeg [x] }
ELSE
{ IF M2S.sym = plus THEN M2S.GetSym;
Term [x] };
WHILE (M2S.sym >= plus) AND (M2S.sym <= or) DO
addop ← M2S.sym; M2S.GetSym;
IF addop = or THEN
{ IF x^.mode # conMd THEN M2H.LoadStk [x];
M2H.GenOr [x]; Term [y];
IF y^.mode # conMd THEN M2H.LoadStk [y] }
ELSE { M2H.Load [x]; Term [y]; M2H.Load [y] };
M2H.GenOp [addop, x, y]
ENDLOOP };
Expression: PUBLIC PROC [x: M2H.ItemPtr] =
{ y: M2H.ItemPtr ← NEW [M2H.Item ← [contxt: x^.contxt]];
relation: M2S.Symbol;
SimpleExpression [x];
IF (M2S.sym >= eql) AND (M2S.sym <= geq) THEN
{ relation ← M2S.sym; M2S.GetSym;
IF x^.mode # conMd THEN
IF x^.typ^.form = Set THEN M2H.Load [x] ELSE M2H.LoadStk [x];
SimpleExpression [y];
IF y^.mode # conMd THEN M2H.Load [y];
M2H.GenOp [relation, x, y] }
ELSE IF M2S.sym = in THEN { M2S.GetSym;
IF x^.mode # conMd THEN M2H.LoadStk [x];
SimpleExpression [y]; M2H.Load [y];
M2H.GenIn [x, y] }};
ConstExpression: PUBLIC PROC [x: M2H.ItemPtr] =
{ x^.contxt ← dummyContxt;
Expression [x];
IF x^.mode # conMd THEN
{ err [44]; x^.mode ← conMd; x^.val.C ← 1 }};
END.