-- BasicParser.mesa
-- edited by Brotz and Hilton, September 23, 1982 5:13 PM

DIRECTORY
BasicDefs,
BasicImpDefs,
BasicOps,
Inline,
Storage,
String;

BasicParser: PROGRAM

IMPORTS BasicImpDefs, Inline, Storage, String
EXPORTS BasicImpDefs =

BEGIN
OPEN BasicDefs, BasicImpDefs;


ArithmeticExpression: PROCEDURE =
BEGIN
op: CHARACTER;
Term[];
IF haveToken THEN
WHILE token[0] = ’+ OR token[0] = ’- DO
op ← token[0];
IF GetToken[] THEN
BEGIN
Term[];
SELECT op FROM
’+ => AppendByte[lineCodeCm, BasicOps.Add];
’- => AppendByte[lineCodeCm, BasicOps.Sub];
ENDCASE;
END
ELSE ParseError["Missing term in arithmetic expression."L];
ENDLOOP;
END; -- of ArithmeticExpression --


Expression: PUBLIC PROCEDURE =
-- Expression is the first procedure of a recursive descent expression
-- parser. It in turn calls procedures which parse the expression into
-- ’Relation’, ’ArithmeticExpression’, ’Term’, ’Factor’ and ’Primary’.
BEGIN
op: CHARACTER;
Relation[];
IF haveToken THEN
WHILE token[0] = ’& OR token[0] = ’| DO
op ← token[0];
IF GetToken[] THEN
BEGIN
Relation[];
SELECT op FROM
’& => AppendByte[lineCodeCm, BasicOps.And];
’| => AppendByte[lineCodeCm, BasicOps.Or];
ENDCASE;
END
ELSE ParseError["Missing relation in logical expression."L];
ENDLOOP;
END; -- of Expression --


Factor: PROCEDURE =
BEGIN
Primary[];
IF haveToken THEN
WHILE token[0] = ’↑ DO
IF GetToken[] THEN
BEGIN
Primary[];
AppendByte[lineCodeCm, BasicOps.Exp];
END
ELSE ParseError["Missing exponent."L];
ENDLOOP;
END; -- of Factor --


ParseConstant: PUBLIC PROCEDURE RETURNS [value: BasicValue] =
BEGIN
SELECT token[0] FROM
IN [’0 .. ’9] =>
BEGIN
integerPart: STRING ← [40];
String.AppendString[integerPart, token];
IF GetToken[] AND token[0] = ’. THEN
value ← BasicValue[real, real[realValue: GetRealNumber[integerPart]]]
ELSE value ← BasicValue
[integer, integer[integerValue: String.StringToLongNumber[integerPart, 10]]];
END;
’. => value ← BasicValue[real, real[realValue: GetRealNumber["0"L]]];
’" =>
BEGIN
string: STRING ← ScanQuotedString[];
value ← BasicValue[string, string[stringValue: string]];
[] ← GetToken[];
END;
’+ =>
IF GetToken[] THEN value ← ParseConstant[] ELSE ParseError["Missing constant!"L];
’- =>
IF GetToken[] THEN
BEGIN
value ← ParseConstant[];
SELECT value.type FROM
integer => value.integerValue ← -value.integerValue;
real => value.realValue ← -value.realValue;
ENDCASE => ParseError["Unary minus of non-numeric value!"L];
END
ELSE ParseError["Missing constant!"L];
ENDCASE => ParseError["Illegal constant!"L];
END; -- of ParseConstant --


Primary: PROCEDURE =
BEGIN
varPtr: VariablePtr;
value: BasicValue;
nIndices: CARDINAL ← 0;
SELECT TRUE FROM
charTablePtr[token[0]] = letter =>
BEGIN
IF IsReservedWord[token] THEN ParseError["Missing Primary"L];
varPtr ← LookUpVariable[token];
[] ← GetToken[];
WITH var: varPtr SELECT FROM
numeric =>
BEGIN
IF haveToken AND token[0] = ’( THEN
{nIndices ← ParseSubscripts[]; [] ← GetToken[]};
SELECT nIndices FROM
0 => AppendByte[lineCodeCm, BasicOps.PushVal];
1 => AppendByte[lineCodeCm, BasicOps.Arr1Push];
2 => AppendByte[lineCodeCm, BasicOps.Arr2Push];
ENDCASE;
AppendPointer[lineCodeCm, varPtr];
END;
string =>
BEGIN
IF haveToken AND token[0] = ’[ THEN
{nIndices ← ParseSubscripts[]; [] ← GetToken[]};
SELECT nIndices FROM
0 => AppendByte[lineCodeCm, BasicOps.PushVal];
1 => AppendByte[lineCodeCm, BasicOps.Str1Push];
2 => AppendByte[lineCodeCm, BasicOps.Str2Push];
ENDCASE;
AppendPointer[lineCodeCm, varPtr];
END;
builtInFunction =>
BEGIN
IF haveToken AND token[0] = ’( THEN
BEGIN
IF GetToken[] THEN Expression[] ELSE ParseError["Missing parameter!"L];
IF haveToken THEN
SELECT token[0] FROM
’, =>
BEGIN
IF GetToken[] THEN Expression[] ELSE ParseError["Missing parameter!"L];
IF ~haveToken OR token[0] # ’) THEN ParseError["Missing )!"L];
[] ← GetToken[];
END;
’) =>
BEGIN
AppendByte[lineCodeCm, BasicOps.PushI];
AppendByte[lineCodeCm, 0];
[] ← GetToken[];
END;
ENDCASE => ParseError["Illegal parameter terminator!"L]
ELSE ParseError["Missing )!"L];
END
ELSE BEGIN
AppendByte[lineCodeCm, BasicOps.PushI];
AppendByte[lineCodeCm, 0];
AppendByte[lineCodeCm, BasicOps.PushI];
AppendByte[lineCodeCm, 0];
END;
AppendByte[lineCodeCm, BasicOps.CallBuiltInFn];
AppendPointer[lineCodeCm, varPtr];
END;
userFunction =>
BEGIN
IF haveToken AND token[0] = ’( THEN
BEGIN
IF GetToken[] THEN Expression[] ELSE ParseError["Missing parameter!"L];
IF ~haveToken OR token[0] # ’) THEN ParseError["Missing )!"L];
[] ← GetToken[];
END
ELSE BEGIN
AppendByte[lineCodeCm, BasicOps.PushI];
AppendByte[lineCodeCm, 0];
END;
AppendByte[lineCodeCm, BasicOps.CallUserFn];
AppendPointer[lineCodeCm, varPtr];
END;
ENDCASE => ParseError["Complex primary not implemented"L];
END;
token[0] IN [’0 .. ’9] =>
BEGIN
value ← ParseConstant[];
IF value.type = integer AND value.integerValue IN [0 .. 255] THEN
BEGIN
AppendByte[lineCodeCm, BasicOps.PushI];
AppendByte[lineCodeCm, Inline.LowHalf[value.integerValue]];
END
ELSE BEGIN
AppendByte[lineCodeCm, BasicOps.PushVal];
AppendPointer[lineCodeCm, AllocateConstant[value]];
END;
END;
token[0] = ’. =>
BEGIN
value ← ParseConstant[];
AppendByte[lineCodeCm, BasicOps.PushVal];
AppendPointer[lineCodeCm, AllocateConstant[value]];
END;
token[0] = ’" =>
BEGIN
value ← ParseConstant[];
AppendByte[lineCodeCm, BasicOps.PushVal];
AppendPointer[lineCodeCm, AllocateConstant[value]];
Storage.FreeString[value.stringValue];
END;
token[0] = ’+ =>
IF GetToken[] THEN Primary[] ELSE ParseError["Missing Primary"L];
token[0] = ’- =>
IF GetToken[] THEN {Primary[]; AppendByte[lineCodeCm, BasicOps.UnaryMinus]}
ELSE ParseError["Missing Primary"L];
token[0] = ’~ =>
IF GetToken[] THEN {Primary[]; AppendByte[lineCodeCm, BasicOps.Not]}
ELSE ParseError["Missing Primary"L];
token[0] = ’( =>
BEGIN
IF GetToken[] AND token[0] ~= ’) THEN Expression[]
ELSE IF token[0] = ’) THEN
ParseError["Missing argument in parenthesis."];
IF ~haveToken OR token[0] ~= ’) THEN ParseError["Missing matching )."L];
[] ← GetToken[];
END;
ENDCASE => ParseError["Illegal primary."L];
END; -- of Primary --


Relation: PROCEDURE =
BEGIN
op: {lt, le, eq, ne, ge, gt};
ArithmeticExpression[];
IF haveToken THEN
BEGIN
SELECT token[0] FROM
’< =>
BEGIN
IF GetToken[] THEN
SELECT token[0] FROM
’= => {op ← le; [] ← GetToken[];};
’> => {op ← ne; [] ← GetToken[];};
ENDCASE => op ← lt
ELSE ParseError["Missing relation term."L];
END;
’= => {op ← eq; [] ← GetToken[]};
’> =>
BEGIN
IF GetToken[] THEN
SELECT token[0] FROM
’= => {op ← ge; [] ← GetToken[];};
ENDCASE => op ← gt
ELSE ParseError["Missing relation term."L];
END;
ENDCASE => RETURN;
IF haveToken THEN
BEGIN
ArithmeticExpression[];
AppendByte[lineCodeCm, SELECT op FROM
lt => BasicOps.Lesser,
le => BasicOps.LE,
eq => BasicOps.Equal,
ne => BasicOps.NE,
ge => BasicOps.GE,
gt => BasicOps.Greater,
ENDCASE => ERROR];
END
ELSE ParseError["Missing relation term."L];
END;
END; -- of Relation --


Term: PROCEDURE =
BEGIN
op: CHARACTER;
Factor[];
IF haveToken THEN
WHILE token[0] = ’* OR token[0] = ’/ DO
op ← token[0];
IF GetToken[] THEN
BEGIN
Factor[];
SELECT op FROM
’* => AppendByte[lineCodeCm, BasicOps.Mul];
’/ => AppendByte[lineCodeCm, BasicOps.Div];
ENDCASE;
END
ELSE ParseError["Missing a factor or divisor."L];
ENDLOOP;
END; -- of Term --


END. -- of BasicParser --