RobotTParserImpl.mesa
Created Saturday, June 2, 1984 1:26 pm PDT
Lasted edited by Eric Nickell, November 4, 1984 5:26:23 pm PST
Temporary Parser until we can hook into the PGS system
DIRECTORY
BasicTime USING [GMT],
IO USING [int, Put, rope, STREAM],
RobotDefs USING [Robot, RobotRec],
RobotEvaluator,
RobotHardware USING [InstallStandardSymbols],
RobotInstruction USING [EncodeStatement],
RobotScanner,
RobotTParser,
Rope USING [Cat, Concat, Equal, ROPE];
RobotTParserImpl: CEDAR PROGRAM
IMPORTS IO, RobotEvaluator, RobotHardware, RobotInstruction, RobotScanner, Rope
EXPORTS RobotTParser ~ {
Value: TYPE ~ RobotEvaluator.Value;
Index: TYPE ~ RobotEvaluator.Index;
AssembleRobot: PUBLIC PROC [file: Rope.ROPE, err: IO.STREAMNIL] RETURNS [r: RobotDefs.Robot ← NEW[RobotDefs.RobotRec], valid: BOOLFALSE, s: RobotEvaluator.SymbolTable ← RobotEvaluator.NewSymbolTable[]] ~ {
Process is as follows:
1. Tokenize the given file
2. Parse the tokens in Pass 1 to define all the symbols
3. Resolve the value of all the symbols
4. Parse the tokens in Pass 2 to generate the code.
See Robot.grammar (generated by PGS) for the grammar in use.
OPEN RobotEvaluator;
tokens: RobotScanner.ScannedProgram;
rVal: REF ARRAY [0..256) OF Value ← NEW[ARRAY [0..256) OF Value ← ALL[NIL]];--The pass1 values
i: INTEGER ← 0;      --The next token
lastLoc, curLoc: INTEGER ← 16; --The current memory location
pass: [1..2] ← 1;      --We'll make 2 passes at the tokens
parseError: BOOLEANFALSE; --Detect any error throughout the parse
Type: PROC [index: INTEGER] RETURNS [RobotScanner.RTknClass] ~ INLINE {RETURN[tokens.token[index].class]};
Error: PROC [error: Rope.ROPE, pos: INTEGER ← tokens.token[i-1].pc] ~ {
OPEN IO;
msg: Rope.ROPE ← Rope.Cat[error, " at Error["];
parseError ← TRUE;
Put[err, rope[msg], int[pos], rope["]\n"]];
};
Complain: PROC [error: Rope.ROPE] ~ {
OPEN IO;
Put[err, rope[error], rope["\n"]];
};
StartsExp: PROC [i: Index] RETURNS [result: BOOLEAN] ~ {
result ← SELECT Type[i] FROM
tknID => TRUE,
tknNum => TRUE,
tknIF => TRUE,
tknLParen => TRUE,
tknAddop => TRUE,
tknLBracket => TRUE,
ENDCASE => FALSE;
};
AssembleModule: PROC RETURNS [error: BOOLEAN] ~ {
AssembleCreateTime[];
AssemblePicdescript[];
AssembleBody[];
error ← parseError;
};
AssembleCreateTime: PROC ~ {
t: REF BasicTime.GMT;
IF Type[i]#time THEN Error["Expected create time"];
TRUSTED {t ← LOOPHOLE[tokens.token[i].data]}; --WON'T LET ME DO NARROW!!!
r.timeOfSource ← t^;
i ← i+1;
};
AssemblePicdescript: PROC ~ {
};
AssembleBody: PROC ~ {
WHILE StartsExp[i] OR Type[i]=tknInstruction DO
AssembleLine[];
ENDLOOP;
};
AssembleLine: PROC ~ {
SELECT TRUE FROM
Type[i]=tknID AND Type[i+1]=tknColon => {AssembleLabel[]; RETURN};
Type[i]=tknID AND Type[i+1]=tknAssign => {
AssembleAssignment[];
IF Type[i]=tknSemiColon THEN i←i+1 ELSE Error["Expected ;"];
RETURN;
};
Type[i]=tknInstruction => {
rVal[curLoc] ← AssembleStatement[];
curLoc ← curLoc+1;
IF Type[i]=tknSemiColon THEN i←i+1 ELSE Error["Expected ;"];
RETURN;
};
StartsExp[i] => {
rVal[curLoc] ← AssembleExp[];
curLoc ← curLoc+1;
IF Type[i]=tknSemiColon THEN i←i+1 ELSE Error["Expected ;"];
};
ENDCASE => Error["Expect start of line"];
};
AssembleAssignment: PROC ~ {
index: Index;      --Index into symbol table
IF Type[i]#tknID OR Type[i+1]#tknAssign THEN {Error["Assignment expected"];RETURN};
index ← RobotEvaluator.RopeToSymbolIndex[r: NARROW[tokens.token[i].data], s: s];  --Get the index to this symbol
i ← i+2;             --Skip the id and ←
RobotEvaluator.AssignValueToSymbol[v: AssembleExp[], index: index, s: s];
};
AssembleLabel: PROC ~ {
index: Index;      --Index into symbol table
IF Type[i]#tknID OR Type[i+1]#tknColon THEN {Error["Label expected"]; RETURN};
index ← RobotEvaluator.RopeToSymbolIndex[r: NARROW[tokens.token[i].data], s: s];
i ← i+2;             --Skip the id and ←
RobotEvaluator.AssignValueToSymbol[v: RobotEvaluator.NewValueFromInteger[curLoc], index: index, s:s];
};
AssembleStatement: PROC RETURNS [v: Value] ~ {
tag: Value;
immediate, indirect, indexed: BOOLFALSE;
opCodeNum: INTEGER;
IF Type[i]#tknInstruction THEN {Error["OpCode expected"]; RETURN};
opCodeNum ← NARROW[tokens.token[i].data, REF INTEGER]^; i←i+1;
IF Type[i]=tknImmediate THEN {immediate←TRUE; i←i+1};
tag ← AssembleExp[];
IF Type[i]=tknIndirect THEN {indirect←TRUE; i←i+1};
IF Type[i]=tknComma THEN {
i←i+1;  --Gobble comma
IF Type[i]#tknID THEN Error["Expected I"] ELSE {
IF ~Rope.Equal[NARROW[tokens.token[i].data],"I"] THEN Error["Expected I"];
i←i+1;  --Gobble it whether it was right or not...
};
indexed←TRUE;
};
v ← RobotInstruction.EncodeStatement[opCodeNum, tag, immediate, indirect, indexed];
};
AssembleExp: PROC RETURNS [v: Value] ~ {
WHILE ~StartsExp[i] AND Type[i]~=tknEOF DO i←i+1 ENDLOOP;
IF Type[i]=tknIF THEN {
cond, exp1, exp2: Value;
i←i+1;
cond ← AssembleDisjunct[];
IF Type[i]=tknTHEN THEN i←i+1 ELSE Error["Expected THEN"];
exp1 ← AssembleExp[];
IF Type[i]=tknELSE THEN i←i+1 ELSE Error["Expected ELSE"];
exp2 ← AssembleExp[];
v ← ApplyTrinaryFcn[opIfThenElse, cond, exp1, exp2];
}
ELSE {
v ← AssembleSum[];
};
};
AssembleSum: PROC RETURNS [v: Value] ~ {
sum: Value ← AssembleProduct[];
addop: RobotEvaluator.BinOp;
WHILE Type[i]=tknAddop DO
addop ← NARROW[tokens.token[i].data, RobotEvaluator.BinOp]; i←i+1;
sum ← RobotEvaluator.ApplyBinaryFcn[addop, sum, AssembleProduct[]];
ENDLOOP;
v ← sum;
};
AssembleProduct: PROC RETURNS [v: Value] ~ {
product: Value ← AssembleFactor[];
multop: RobotEvaluator.BinOp;
WHILE Type[i]=tknMulop DO
multop ← NARROW[tokens.token[i].data]; i←i+1;
product ← RobotEvaluator.ApplyBinaryFcn[multop, product, AssembleFactor[]];
ENDLOOP;
v ← product;
};
AssembleDisjunct: PROC RETURNS [v: Value] ~ {
disjunct: Value ← AssembleConjunct[];
or: RobotEvaluator.BinOp;
WHILE Type[i]=tknOR DO
or ← NARROW[tokens.token[i].data]; i←i+1;
disjunct ← RobotEvaluator.ApplyBinaryFcn[or, disjunct, AssembleConjunct[]];
ENDLOOP;
v ← disjunct;
};
AssembleConjunct: PROC RETURNS [v: Value] ~ {
conjunct: Value ← AssembleNegation[];
and: RobotEvaluator.BinOp;
WHILE Type[i]=tknAND DO
and ← NARROW[tokens.token[i].data]; i←i+1;
conjunct ← RobotEvaluator.ApplyBinaryFcn[and, conjunct, AssembleNegation[]];
ENDLOOP;
v ← conjunct;
};
AssembleNegation: PROC RETURNS [v: Value] ~ {
IF Type[i]=tknNOT THEN {
i←i+1;
RETURN[RobotEvaluator.ApplyUnaryFcn[NARROW[tokens.token[i].data], AssembleRelation[]]];
};
v ← AssemblePrimary[];
};
AssembleRelation: PROC RETURNS [v: Value] ~ {
relation: Value ← AssembleExp[];
relop: RobotEvaluator.BinOp;
IF Type[i]#tknRelop THEN {
Error["Expected Relational Operator"];
RETURN[NewUnassignedValue[]];
};
relop ← NARROW[tokens.token[i].data]; i←i+1;
relation ← RobotEvaluator.ApplyBinaryFcn[relop, relation, AssembleExp[]];
v ← relation;
};
AssembleFactor: PROC RETURNS [v: Value] ~ {
IF Type[i]=tknAddop AND RobotEvaluator.opMinus=NARROW[tokens.token[i].data, RobotEvaluator.BinOp] THEN {
i←i+1;
RETURN[RobotEvaluator.ApplyUnaryFcn[RobotEvaluator.opUMinus, AssembleFactor[]]];
};
IF Type[i]=tknAddop THEN i←i+1;
v ← AssemblePrimary[];
};
AssemblePrimary: PROC RETURNS [v: Value] ~ {
OPEN RobotEvaluator;
SELECT Type[i] FROM
tknID => {
v ← ValueOfSymbol[RopeToSymbolIndex[NARROW[tokens.token[i].data], s], s];
i ← i+1;
};
tknNum => {
vval: INTEGERNARROW[tokens.token[i].data, REF INT]^;
v ← NewValueFromInteger[vval];
i ← i+1;
};
tknLParen => {
i ← i+1;  --Skip the paren
v ← AssembleExp[];
IF Type[i]=tknRParen THEN i←i+1 ELSE Error["Expected Right Parenthesis"];
};
tknLBracket => {
i ← i+1;
v ← AssembleStatement[];
IF Type[i]=tknRBracket THEN i←i+1 ELSE Error["Expected Right Bracket"];
};
ENDCASE => {
Error["Expected id"];
v ← NewUnassignedValue[];
};
};
ResolveSymbols: PROC RETURNS [error: BOOLEAN] ~ {
error ← RobotEvaluator.ResolveSymbolTable[s];
IF error THEN {
FOR i: RobotEvaluator.Index IN Index DO
IF s[i]#NIL AND s[i].value.type#integer THEN
Complain[Rope.Concat[s[i].name, " undefined."]];
ENDLOOP;
};
};
ResolveCode: PROC RETURNS [error: BOOLEANFALSE] ~ {
lastLoc ← curLoc-1;
FOR i: INTEGER IN [0..256) DO
r.code[i] ← 0;
ENDLOOP;
FOR i: INTEGER IN [16..lastLoc] DO
rVal[i] ← Eval[rVal[i], s];
IF rVal[i].type=integer THEN r.code[i]←rVal[i].value ELSE {
error←TRUE;
Error["instruction SYSERR",i];
};
ENDLOOP;
};
Main routine for AssembleRobot starts here!!!
Note that in the binding, we have already gotten a list of tokens.
RobotHardware.InstallStandardSymbols[s];  --Define AC, I, etc...
tokens ← RobotScanner.GetTokensFromFile[file];
r.pic[0][0]←TRUE; r.pic[0][15]←TRUE; r.pic[15][0]←TRUE; r.pic[15][15]←TRUE;
SELECT TRUE FROM
AssembleModule[] => Complain["Parsing Errors"];
ResolveSymbols[] => Complain["Undefined or circularly defined symbols"];
ResolveCode[] => Complain["SYSTEM ERROR while resolving code"];
ENDCASE => valid ← TRUE;  --Nothing went wrong
};
}.