Press enter to see results or esc to cancel.

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;