GOTO Statement
This procedure processes GoTo
statement. It expects already declared numeric label that should be in the in the current block and adds GoTo
record to a linked list.
Procedure TStatement.Process_GOTO_Statement;
Var JumpCodeRecord: PIntermediateCodeRecord;
begin
GetNextToken;
CheckForNumericLabel;
CheckForDeclaredIdentifier;
ExpectTokenAndGetNext (Token_LabelIdentifier);
If CurrentIdentifierOffset < Ofs (CurrentScopeIdentifierTableAddress^) then Error (LabelNotWithinCurrentBlock);
JumpCodeRecord := IncreaseSymbolTable (stIntermediateCode, 8);
With JumpCodeRecord^ do
begin
RecordType := icJumpNear;
JumpOpCode := JMP_ShortDirect;
LabelIdentifierOffset := CurrentIdentifierOffset;
Next_GOTO_Record := Last_GOTO_Record;
end;
Last_GOTO_Record := Ofs (JumpCodeRecord^);
StatementCode := EndSubroutine;
end;
After the program block is processed, labels are added to the GoTo
records.
Procedure PlaceLabelRecordsTo_GOTO_Records;
Var GOTO_Record: PIntermediateCodeRecord;
GOTO_RecordOfs: Word absolute GOTO_Record;
LabelIdentifier: PIdentifier;
LabelIdentifierOfs: Word absolute LabelIdentifier;
LabelIdentifierData: PLabelIdentifierData;
LabelIdentifierDataOfs: Word absolute LabelIdentifierData;
begin
GOTO_Record := Ptr (SymbolTable [stIntermediateCode].Segment, Last_GOTO_Record);
LabelIdentifier := Ptr (SymbolTable [stMain].Segment, 0);
LabelIdentifierData := Ptr (SymbolTable [stMain].Segment, 0);
While GOTO_RecordOfs <> 0 do
begin
LabelIdentifierOfs := GOTO_Record^.LabelIdentifierOffset;
LabelIdentifierDataOfs := LabelIdentifierOfs + LabelIdentifier^.Name.Len + 4;
If LabelIdentifierData^.LabelRecordOffset = 0 then
IdentifierError (LabelIdentifier^.Name.Str, UndefinedLabelInPrecedingStatementPart);
GOTO_Record^.LabelRecordOffset := LabelIdentifierData^.LabelRecordOffset;
GOTO_RecordOfs := GOTO_Record^.Next_GOTO_Record;
end;
end;
This procedure processes labels in program block. It expects already declared label, reports error if the label was already placed somewhere and generates intermediate code for the label. Finally, it processes the next statement.
Procedure TStatement.ProcessLabelIdentifierStatement;
Var TempLabelIdentifierData: PLabelIdentifierData;
LabelRecord: PIntermediateCodeRecord;
Statement: TStatement;
begin
TempLabelIdentifierData := CurrentLabelIdentifierData;
If Ofs (CurrentIdentifierDataPtr^) < Ofs (CurrentScopeIdentifierTableAddress^) then Error (LabelNotWithinCurrentBlock);
If TempLabelIdentifierData^.LabelRecordOffset <> 0 then Error (LabelAlreadyDefined);
Dec (TempLabelIdentifierData^.LabelRecordOffset);
GetNextToken;
ExpectTokenAndGetNext (Token_Colon);
Statement.ProcessStatement;
LabelRecord := IncreaseSymbolTable (stIntermediateCode, 3);
LabelRecord^.RecordType := icLabel;
TempLabelIdentifierData^.LabelRecordOffset := Ofs (LabelRecord^) + 1;
StoreCode_icGoSub (Statement.StatementCode);
StatementCode := EndSubroutine
end;