home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d3xx
/
d339
/
pcq.lha
/
PCQ
/
Source.lzh
/
Source
/
Expression.p
< prev
next >
Wrap
Text File
|
1990-02-06
|
23KB
|
873 lines
External;
{
Expression.p (of PCQ Pascal)
Copyright (c) 1989 Patrick Quaid
This module only has two parts. The first is expression(),
which handles all run-time expressions. The other one is
conexpr(), which handles all constant expressions.
}
{$O-}
{$I "Pascal.i"}
Function TypeCheck(l, r : TypePtr) : Boolean;
external;
procedure NextSymbol;
external;
procedure Error(s : string);
external;
Procedure Abort;
external;
Procedure ReadChar;
external;
Function EndOfFile() : Boolean;
external;
Procedure CallFunc(f : IDPtr);
external;
Procedure StdFunc(f : IDPtr);
external;
Function Match(s : Symbols): Boolean;
external;
Function FindID(s : string) : IDPtr;
external;
Function FindWithField(s : String) : IDPtr;
External;
Procedure PrintLabel(l : Integer);
external;
Function GetLabel() : Integer;
external;
Function Selector(f : IDPtr) : TypePtr;
external;
Function GetFramePointer(Ref : Integer) : Short;
External;
Procedure Mismatch;
external;
Procedure NoLeftParent;
external;
Procedure NoRightParent;
external;
Procedure NeedNumber;
external;
Procedure NeedRightParent;
external;
Procedure NeedLeftParent;
external;
Function Suffix(s : Integer) : Char;
external;
Function NumberType(l : TypePtr) : Boolean;
external;
Function BaseType(b : TypePtr): TypePtr;
external;
Function SimpleType(t : TypePtr) : Boolean;
external;
Procedure WriteHex(h : Integer);
external;
Procedure PromoteType(var f : TypePtr; o : TypePtr; r : Short);
external;
Procedure PushLongD0;
external;
Procedure PushLongD1;
External;
Procedure PopLongD1;
external;
Procedure PopLongA1;
External;
Procedure PopStackSpace(amount : Integer);
External;
Function EnterStandard( st_Name : String;
st_Object : IDObject;
st_Type : TypePtr;
st_Storage : IDStorage;
st_Offset : Integer) : IDPtr;
external;
Function Expression() : TypePtr;
forward;
Procedure IncLitPtr;
begin
if LitPtr >= LiteralSize then begin
Writeln('Too much literal data');
Abort;
end else
LitPtr := Succ(LitPtr);
end;
Function ReadLit(Quote : Char) : TypePtr;
{
This routine reads a literal array of char into the literal
array.
}
var
Length : Short;
begin
Length := 1;
while (currentchar <> Quote) and (currentchar <> chr(10)) do begin
if CurrentChar = '\\' then begin
ReadChar;
if CurrentChar = Chr(10) then
Error("Missing closing quote");
case CurrentChar of
'n' : Litq[LitPtr] := Chr(10);
't' : Litq[LitPtr] := Chr(9);
'0' : Litq[LitPtr] := Chr(0);
'b' : Litq[LitPtr] := Chr(8);
'e' : Litq[LitPtr] := Chr(27);
'c' : Litq[LitPtr] := Chr($9B);
'a' : Litq[LitPtr] := Chr(7);
'f' : Litq[LitPtr] := Chr(12);
'r' : Litq[LitPtr] := Chr(13);
'v' : Litq[LitPtr] := Chr(11);
else
Litq[LitPtr] := CurrentChar;
end;
end else
Litq[LitPtr] := CurrentChar;
if CurrentChar <> Chr(10) then begin
ReadChar;
if currentchar = chr(10) then
error("Missing closing quote");
end;
Length := Succ(Length);
IncLitPtr;
end;
ReadChar;
NextSymbol;
if Quote = '"' then begin
LitQ[LitPtr] := Chr(0);
IncLitPtr;
ReadLit := StringType;
end else begin
LiteralType^.Upper := Length - 1;
ReadLit := LiteralType;
end;
end;
Function LoadValue(ID : IDPtr) : TypePtr;
var
TP : TypePtr;
Reg : Short;
begin
TP := ID^.VType;
case ID^.Object of
typed_const,
global : if ID^.Level <= 1 then begin
if SimpleType(TP) then
writeln(OutFile,"\tmove.", Suffix(TP^.Size),
"\t_", ID^.Name, ',d0')
else
Writeln(OutFile, "\tmove.l\t#_", ID^.Name, ',d0');
end else begin
if SimpleType(TP) then
writeln(OutFile, '\tmove.', Suffix(TP^.Size), '\t_',
ID^.Name, '%', ID^.Unique, ',d0')
else
writeln(OutFile, '\tmove.l\t#_', ID^.Name, '%',
ID^.Unique, ',d0');
end;
local,
valarg : begin
Reg := GetFramePointer(ID^.Level);
if SimpleType(TP) then
Writeln(OutFile, "\tmove.", Suffix(TP^.Size),
Chr(9), ID^.Offset, '(a', Reg, '),d0')
else begin
Writeln(OutFile, "\tlea\t", ID^.Offset, '(a', Reg, '),a0');
Writeln(OutFile, "\tmove.l\ta0,d0");
end;
end;
refarg : begin
Reg := GetFramePointer(ID^.Level);
if SimpleType(TP) then begin
Writeln(OutFile, "\tmove.l\t", ID^.Offset, '(a', Reg, '),a0');
Writeln(OutFile, "\tmove.", Suffix(TP^.Size), "\t(a0),d0");
end else
writeln(OutFile, "\tmove.l\t", ID^.Offset, '(a', Reg, '),d0')
end;
else begin
Error("expecting a variable or function");
TP := BadType;
end;
end;
LoadValue := TP;
end;
Procedure ReadBadArgs;
var
TP : TypePtr;
begin
if Match(LeftParent1) then begin
While (CurrSym <> RightParent1) and (CurrSym <> SemiColon1) and
(Not EndOfFile()) do begin
TP := Expression();
if CurrSym <> RightParent1 then
if not Match(Comma1) then
Error("Expecting a comma");
end;
NeedRightParent;
end;
end;
Function IDFactor(ID : IDPtr) : TypePtr;
{
idfactor() is another nightmare function. It does whatever
is necessary when the compiler runs across an identifer in an
expression, which almost always means loading a value into d0.
}
var
TP : TypePtr;
begin
if ID = nil then begin
Error("Unknown ID");
ID := EnterStandard(SymText, global, BadType, st_none, 1);
NextSymbol;
ReadBadArgs;
IDFactor := BadType;
end else begin
case ID^.Object of
func : begin
CallFunc(ID);
IDFactor := ID^.VType;
end;
stanfunc : begin
StdFunc(ID);
IDFactor := ID^.VType;
end;
obtype : begin
NeedLeftParent;
TP := Expression();
NeedRightParent;
IDFactor := ID^.VType;
end;
constant : begin
TP := ID^.VType;
if TP^.Object = ob_ordinal then { Integer, Short, etc. }
writeln(OutFile, "\tmove.l\t#",
ID^.Offset, ',d0')
else if TP^.Object = ob_pointer then begin
{ String or Nil }
if TP = StringType then begin
write(OutFile, "\tmove.l\t#");
PrintLabel(litlab);
writeln(OutFile, '+', ID^.Offset, ',d0');
end else
writeln(OutFile, "\tmove.l\t#", ID^.Offset, ',d0');
end else if TP^.Object = ob_array then begin
{ Must be charray }
write(OutFile, "\tmove.l\t#");
PrintLabel(litlab);
writeln(OutFile, '+', ID^.Offset, ',d0');
end else if TP^.Object = ob_real then begin
Write(Outfile, "\tmove.l\t#");
writehex(ID^.Offset);
writeln(OutFile, ',d0');
end;
IDFactor := TP;
end;
else begin { Else clause of CASE, remember }
TP := Selector(ID);
if TP <> Nil then begin
if SimpleType(TP) then
writeln(OutFile, "\tmove.",
Suffix(TP^.Size), "\t(a0),d0")
else
writeln(OutFile, "\tmove.l\ta0,d0");
end else
TP := LoadValue(ID);
IDFactor := TP;
end;
end;
end;
end;
Function Factor() : TypePtr;
{
This is the lowest level of the expression parsing
business. It's pretty standard stuff. All these expression
routines return a pointer to the type they're working on.
}
var
ID : IDPtr;
TP, TP2 : TypePtr;
LitSpot : Integer;
begin
if CurrSym = Ident1 then begin
ID := FindWithField(SymText);
if ID = Nil then
ID := FindID(SymText);
nextsymbol;
Factor := IDFactor(ID);
end else if CurrSym = Numeral1 then begin
Write(OutFile, "\tmove.l\t#");
if abs(symloc) > 1000000 then begin
writehex(symloc);
writeln(OutFile, ',d0');
end else
writeln(OutFile, symloc, ',d0');
nextsymbol;
Factor := IntType;
end else if CurrSym = RealNumeral1 then begin
write(OutFile, "\tmove.l\t#");
writehex(integer(RealValue));
writeln(OutFile, ',d0');
nextsymbol;
Factor := RealType;
end else if Currsym = Apostrophe1 then begin
LitSpot := LitPtr;
TP := ReadLit(Chr(39));
if TP^.Upper = 1 then begin
LitPtr := Pred(LitPtr);
Writeln(OutFile, "\tmove.b\t#", Ord(LitQ[LitPtr]), ',d0');
Factor := CharType;
end else begin
New(TP2);
TP2^ := TP^;
TP2^.Next := CurrentBlock^.FirstType;
CurrentBlock^.FirstType := TP2;
Write(OutFile, "\tmove.l\t#");
PrintLabel(LitLab);
Writeln(OutFile, '+', LitSpot, ',d0');
Factor := TP2;
end;
end else if CurrSym = Quote1 then begin
Write(OutFile, "\tmove.l\t#");
PrintLabel(LitLab);
Writeln(OutFile, '+', LitPtr, ',d0');
Factor := ReadLit('"');
end else if match(not1) then begin
TP := Factor();
if TP^.Object <> ob_ordinal then begin
error("NOT applies only to ordinal values");
Factor := BadType;
end else
writeln(OutFile, "\tnot.", Suffix(TP^.Size), "\td0");
Factor := TP;
end else if Match(LeftParent1) then begin
TP := Expression();
NeedRightParent;
Factor := TP;
end else begin
error("Unrecognizable expression");
NextSymbol;
Factor := BadType;
end;
end;
Function Operate(LeftType, RightType : TypePtr; Operator : Symbols) : TypePtr;
{
This routine handles the actual code generation for the
various operations. This handles all the math stuff, even though
it's called by different routines.
}
var
Suffer : Char;
begin
if not TypeCheck(LeftType, RightType) then begin
Mismatch;
Operate := BadType;
end else begin
PopLongD1;
if (Operator = And1) or (Operator = Or1) or (Operator = Xor1) or
(Operator = Shl1) or (Operator = Shr1) then begin
if LeftType^.Object <> ob_ordinal then
Error("Need ordinal expression")
else if LeftType^.size <> RightType^.Size then begin
PromoteType(lefttype, RightType, 1);
PromoteType(RightType, lefttype, 0);
end;
end else begin
if NumberType(LeftType) or (LeftType = RealType) then begin
PromoteType(LeftType, RightType, 1);
PromoteType(RightType, LeftType, 0);
end else
NeedNumber;
end;
Suffer := Suffix(LeftType^.Size);
if Operator = Asterisk1 then begin
if LeftType = ByteType then begin
PromoteType(LeftType, ShortType, 1);
PromoteType(RightType, ShortType, 0);
end;
if LeftType = ShortType then begin
writeln(OutFile, "\tmuls\td1,d0");
Operate := IntType;
end else if LeftType = IntType then begin
PushLongD0;
PushLongD1;
writeln(OutFile, "\tjsr\t_p%lmul");
PopStackSpace(8);
Operate := Inttype;
end else begin
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-78(a6)");
Operate := RealType;
end;
end else if Operator = Div1 then begin
if LeftType <> IntType then
PromoteType(LeftType, IntType, 1);
if RightType = ByteType then
PromoteType(RightType, ShortType, 0);
if RightType = ShortType then begin
writeln(OutFile, "\tdivs\td0,d1");
writeln(OutFile, "\tmove.l\td1,d0");
Operate := ShortType;
end else if RightType = IntType then begin
PushLongD0;
PushLongD1;
writeln(OutFile, "\tjsr\t_p%ldiv");
PopStackSpace(8);
Operate := IntType;
end else begin
Error("No reals allowed for DIV");
Operate := BadType;
end;
end else if Operator = Mod1 then begin
if LeftType <> IntType then
PromoteType(LeftType, IntType, 1);
if RightType = ByteType then
PromoteType(RightType, ShortType, 0);
if RightType = ShortType then begin
writeln(OutFile, "\tdivs\td0,d1");
writeln(OutFile, "\tmove.l\td1,d0");
writeln(OutFile, "\tswap\td0");
Operate := ShortType;
end else if RightType = IntType then begin
PushLongD0;
PushLongD1;
writeln(OutFile, "\tjsr\t_p%lrem");
PopStackSpace(8);
Operate := IntType;
end else begin
Error("No reals allowed for MOD");
Operate := BadType;
end;
end else if Operator = And1 then begin
writeln(OutFile, "\tand.", suffer, "\td1,d0");
Operate := LeftType;
end else if Operator = Shl1 then begin
writeln(OutFile, "\tand.w\t#31,d0");
if LeftType^.Size = 1 then
Writeln(OutFile, '\tand.l\t#$FF,d1')
else if LeftType^.Size = 2 then
Writeln(OutFile, '\tand.l\t#$FFFF,d1');
writeln(OutFile, "\tasl.", Suffer, "\td0,d1");
writeln(OutFile, "\tmove.", Suffer, "\td1,d0");
Operate := LeftType;
end else if Operator = Shr1 then begin
writeln(OutFile, "\tand.w\t#31,d0");
if LeftType^.Size = 1 then
Writeln(OutFile, '\tand.l\t#$FF,d1')
else if LeftType^.Size = 2 then
Writeln(OutFile, '\tand.l\t#$FFFF,d1');
writeln(OutFile, "\tlsr.", Suffer, "\td0,d1");
writeln(OutFile, "\tmove.", Suffer, "\td1,d0");
Operate := LeftType;
end else if Operator = Plus1 then begin
if LeftType = RealType then begin
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-66(a6)");
end else
writeln(OutFile, "\tadd.", Suffer, "\td1,d0");
Operate := LeftType;
end else if Operator = Minus1 then begin
writeln(OutFile, "\texg\td0,d1");
if LeftType = RealType then begin
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-72(a6)");
end else
writeln(OutFile, "\tsub.", Suffer, "\td1,d0");
Operate := LeftType;
end else if Operator = RealDiv1 then begin
PromoteType(LeftType, RealType, 1);
PromoteType(RightType, RealType, 0);
writeln(OutFile, "\texg\td0,d1");
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-84(a6)");
Operate := RealType;
end else if Operator = Or1 then begin
writeln(OutFile, "\tor.", suffer, "\td1,d0");
Operate := LeftType;
end else if Operator = Xor1 then begin
writeln(OutFile, "\teor.", Suffer, "\td1,d0");
Operate := LeftType;
end;
end;
end;
Function Term() : TypePtr;
{
Again, pretty standard stuff. This handles the level of
precedence that includes *, div, mod, /, and, and unary minus.
}
var
LeftType : TypePtr;
stay : Boolean;
begin
if Match(Minus1) then begin
LeftType := Factor();
if LeftType = RealType then begin
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-60(a6)");
end else if TypeCheck(LeftType, IntType) then
writeln(OutFile, "\tneg.", suffix(LeftType^.Size),"\td0")
else begin
Error("Need numeric type for unary minus");
LeftType := BadType;
end;
end else
LeftType := Factor();
stay := true;
while stay do begin
if Match(Asterisk1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), asterisk1);
end else if Match(Div1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), div1);
end else if match(realdiv1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), realdiv1);
end else if match(mod1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), mod1);
end else if match(and1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), and1);
end else if Match(Shl1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), Shl1);
end else if Match(Shr1) then begin
PushLongD0;
LeftType := Operate(LeftType, Factor(), Shr1);
end else
stay := false;
end;
Term := LeftType;
end;
Function Simple() : TypePtr;
{
This is similar to term(), except it handles plus, minus,
and or.
}
var
LeftType : TypePtr;
Stay : Boolean;
begin
LeftType := Term();
Stay := True;
while Stay do begin
if Match(Plus1) then begin
PushLongD0;
LeftType := Operate(LeftType, Term(), plus1);
end else if match(minus1) then begin
PushLongD0;
LeftType := Operate(LeftType, Term(), minus1);
end else if match(or1) then begin
PushLongD0;
LeftType := Operate(LeftType, Term(), or1);
end else if Match(Xor1) then begin
PushLongD0;
LeftType := Operate(LeftType, Term(), Xor1);
end else
Stay := false;
end;
Simple := LeftType;
end;
Function ExprRelOp(LeftType : TypePtr; Operation : Symbols) : TypePtr;
{
This handles the code for the various relative comparisons
(like <, >, <=, etc.)
}
var
RightType : TypePtr;
begin
NextSymbol;
PushLongD0;
RightType := Simple();
if not TypeCheck(LeftType, RightType) then begin
Mismatch;
ExprRelOp := BadType;
end else if not SimpleType(LeftType) then begin
error("only simple types allowed in inequalities");
ExprRelOp := BadType;
end else begin
PopLongD1;
if NumberType(LeftType) or (LeftType = RealType) then begin
PromoteType(LeftType, RightType, 1);
PromoteType(RightType, LeftType, 0);
end;
if LeftType = RealType then begin
writeln(OutFile, "\texg\td0,d1");
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-42(a6)");
end else
writeln(OutFile, "\tcmp.", Suffix(LeftType^.Size), "\td0,d1");
if Operation = Less1 then
writeln(OutFile, "\tslt\td0")
else if Operation = greater1 then
writeln(OutFile, "\tsgt\td0")
else if Operation = notless1 then
writeln(OutFile, "\tsge\td0")
else if Operation = notgreater1 then
writeln(OutFile, "\tsle\td0");
ExprRelOp := BoolType;
end;
end;
Function ExprEqOp(LeftType : TypePtr; Operation : Symbols) : TypePtr;
{
This generates code for comparisons of equality. The main
difference between this and the previous routine is that Pascal
allows the comparison of complex types, so this routine has to
handle that.
}
var
RightType : TypePtr;
lab : Integer;
TotalSize : Integer;
begin
NextSymbol;
PushLongD0;
RightType := Simple();
if not TypeCheck(LeftType, RightType) then begin
Mismatch;
ExprEqOp := BadType;
end else begin
TotalSize := LeftType^.Size;
if not SimpleType(LeftType) then begin
writeln(OutFile, "\tmove.l\td0,a0");
PopLongA1;
writeln(OutFile, "\tmove.b\t#-1,d0");
writeln(OutFile, "\tmove.l\t#", totalsize - 1, ",d1");
lab := GetLabel();
PrintLabel(lab);
writeln(OutFile, "\tmove.b\t(a0)+,d2");
writeln(OutFile, "\tcmp.b\t(a1)+,d2");
writeln(OutFile, "\tseq\td2");
writeln(OutFile, "\tand.b\td2,d0");
write(OutFile, "\tdbra\td1,");
PrintLabel(lab);
writeln(OutFile);
writeln(OutFile, "\ttst.b\td0");
if Operation = notequal1 then
writeln(OutFile, "\tseq\td0");
end else begin
PopLongD1;
if NumberType(LeftType) or (LeftType = RealType) then begin
promotetype(LeftType, RightType, 1);
promotetype(RightType, LeftType, 0);
end;
if LeftType = RealType then begin
writeln(OutFile, "\tmove.l\t_p%MathBase,a6");
writeln(OutFile, "\tjsr\t-42(a6)");
end else
writeln(OutFile, "\tcmp.", Suffix(LeftType^.Size), "\td0,d1");
if Operation = equal1 then
writeln(OutFile, "\tseq\td0")
else
writeln(OutFile, "\tsne\td0");
end;
ExprEqOp := BoolType;
end;
end;
Function Expression() : TypePtr;
{
This is the main part of expression(). If there weren't
any errors, the result of the expression will be in d0.
}
var
LeftType : TypePtr;
stay : Boolean;
begin
LeftType := Simple();
stay := True;
while stay do begin
case CurrSym of
equal1,
notequal1 : LeftType := ExprEqOp(LeftType, CurrSym);
less1,
greater1,
notless1,
notgreater1 : LeftType := ExprRelOp(LeftType, CurrSym);
else
stay := False;
end;
end;
Expression := LeftType;
end;
Function ConExpr(VAR ConType : TypePtr) : Integer;
forward;
Function ConPrimary(VAR ConType : TypePtr) : Integer;
{
These routines are very similar to the other expression
routines, but are much simpler. They return the running value of
the expression. The type is returned in the reference parameter.
This routine should handle type conversions and standard functions.
}
var
Result : Integer;
ID : IDPtr;
TP : TypePtr;
begin
if Match(LeftParent1) then begin
Result := ConExpr(contype);
NeedRightParent;
ConPrimary := Result;
end else if CurrSym = Numeral1 then begin
Result := Symloc;
NextSymbol;
ConType := IntType;
ConPrimary := Result;
end else if CurrSym = RealNumeral1 then begin
Result := Integer(RealValue);
NextSymbol;
ConType := RealType;
ConPrimary := Result;
end else if Match(Minus1) then begin
ConPrimary := -ConPrimary(ConType);
end else if Currsym = Apostrophe1 then begin
Result := LitPtr;
ConType := ReadLit(Chr(39));
if ConType^.Upper = 1 then begin
LitPtr := Pred(LitPtr);
Result := Ord(LitQ[LitPtr]);
ConType := CharType;
end else begin
New(TP);
TP^ := ConType^;
TP^.Next := CurrentBlock^.FirstType;
CurrentBlock^.FirstType := TP;
ConType := TP;
end;
ConPrimary := Result;
end else if CurrSym = Quote1 then begin
Result := LitPtr;
ConType := ReadLit('"');
ConPrimary := Result;
end else if CurrSym = Ident1 then begin
ID := FindID(symtext);
if ID <> Nil then begin
if (ID^.Object = constant) or (ID^.Object = typed_const) then begin
NextSymbol;
ConType := ID^.VType;
ConPrimary := ID^.Offset;
end;
end;
error("Expecting a constant");
ConType := IntType;
ConPrimary := 1;
end else begin
error("Unknown Constant");
ConType := IntType;
ConPrimary := 1;
end;
end;
Function ConFactor(VAR ConType : TypePtr) : Integer;
{
This handles the second level of precedence for constant
expressions.
}
var
Result, Rightresult : integer;
RightType : TypePtr;
begin
Result := ConPrimary(ConType);
While (CurrSym = Asterisk1) or (CurrSym = Div1) or
(CurrSym = RealDiv1) do begin
if (not NumberType(ConType)) and (ConType <> RealType) then
NeedNumber;
if Match(Asterisk1) then begin
RightResult := ConPrimary(RightType);
if TypeCheck(ConType, RightType) then begin
if ConType = Realtype then
Result := Integer(Real(result) * Real(RightResult))
else
Result := Result * RightResult
end else
Mismatch;
end else if (CurrSym = Div1) or (CurrSym = RealDiv1) then begin
NextSymbol;
Rightresult := ConPrimary(RightType);
if TypeCheck(ConType, RightType) then begin
if RightResult = 0 then begin
error("Division by zero");
RightResult := 1;
end;
if ConType = Realtype then
Result := Integer(real(Result) / Real(RightResult))
else
Result := Result div RightResult;
end else
Mismatch;
end;
end;
ConFactor := Result;
end;
Function ConExpr(VAR ConType : TypePtr) : Integer;
{
This handles the other level of constant expressions, and
is also the outermost level.
}
var
Result,
RightResult : Integer;
Righttype : TypePtr;
begin
Result := ConFactor(ConType);
while (CurrSym = Minus1) or (CurrSym = Plus1) do begin
if (not NumberType(ConType)) and (ConType <> RealType) then
NeedNumber;
if Match(Minus1) then begin
RightResult := ConFactor(RightType);
if TypeCheck(ConType, RightType) then begin
if ConType = RealType then
Result := Integer(Real(Result) - Real(RightResult))
else
Result := Result - Rightresult;
end else
Mismatch;
end else if Match(Plus1) then begin
RightResult := ConFactor(RightType);
if TypeCheck(ConType, RightType) then begin
if ConType = RealType then
Result := Integer(Real(Result) + Real(RightResult))
else
Result := Result + Rightresult;
end else
Mismatch;
end;
end;
ConExpr := Result;
end;