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.STREAM _ NIL] RETURNS [r: RobotDefs.Robot _ NEW[RobotDefs.RobotRec], valid: BOOL _ FALSE, s: RobotEvaluator.SymbolTable _ RobotEvaluator.NewSymbolTable[]] ~ { 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: BOOLEAN _ FALSE; --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: BOOL _ FALSE; 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: INTEGER _ NARROW[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: BOOLEAN _ FALSE] ~ { 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; }; 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 }; }. 4RobotTParserImpl.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 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. Main routine for AssembleRobot starts here!!! Note that in the binding, we have already gotten a list of tokens. Ê õ˜šœ™Jšœ*™*J™>J™6J™—šÏk ˜ Jšœ œœ˜Jšœœœ˜"Jšœ œ˜"J˜Jšœœ˜-Jšœœ˜)J˜ J˜ Jšœœœ˜&J˜—šœœ˜JšœœE˜OJšœ˜J˜—Jšœœ˜#šœœ˜#J˜—J˜šÏn œœœ œœœœœœœœD˜Ó™J™J™7J™'J™3—J™Jšœœ œ ˜5J˜Jšœœ œ ˜3šœœ˜JšœŸ˜šœœœ˜0Jšœ œœ˜JJšœŸ*˜2J˜—Jšœœ˜ Jšœ˜—JšœS˜SJšœ˜—šž œœœ˜(Jšœœœœ˜9šœœ˜J˜Jšœ˜J˜Jšœœœ˜:J˜Jšœœœ˜:J˜J˜4J˜—šœ˜J˜J˜—Jšœ˜—šž œœœ˜(J˜J˜šœ˜Jšœœ4˜BJ˜CJšœ˜—J˜J˜—šžœœœ˜,J˜"J˜šœ˜Jšœ œ˜-JšœK˜KJšœ˜—Jšœ ˜ J˜—šžœœœ˜-Jšœ%˜%J˜šœ˜Jšœœ˜)JšœK˜KJšœ˜—Jšœ ˜ J˜—šžœœœ˜-J˜%J˜šœ˜Jšœœ˜*JšœL˜LJšœ˜—Jšœ ˜ J˜—šžœœœ˜-šœœ˜J˜Jšœœ-˜WJ˜—J˜J˜—šžœœœ˜-J˜ J˜šœœ˜Jšœ&˜&Jšœ˜J˜—Jšœœ˜,JšœI˜IJšœ ˜ J˜—šžœœœ˜+šœœœ-œ˜hJ˜JšœJ˜PJ˜—Jšœœ˜J˜J˜—šžœœœ˜,Jšœ˜šœ ˜˜ Jšœ$œ˜IJ˜J˜—˜ Jš œœœœœ˜7Jšœ˜J˜J˜—˜Jšœ Ÿ˜J˜Jšœœœ%˜IJ˜—˜J˜J˜Jšœœœ!˜GJ˜—šœ˜ J˜J˜J˜——J˜J˜—šžœœœ œ˜1J˜-šœœ˜šœœ˜'šœœœ˜,J˜0—Jšœ˜—J˜—J˜J˜—š ž œœœ œœ˜6J˜šœœœ ˜J˜Jšœ˜—šœœœ˜"J˜šœœœ˜;Jšœœ˜ J˜J˜—Jšœ˜—J˜—J˜™-J™BJ˜—J˜@J˜.Jš œ œœœœ˜Lšœœ˜J˜/J˜HJ˜?Jšœ œŸ˜.—J˜—J˜—…— 4,]