PL/0语言编译程序整理实现:(7)、目标代码

来源:互联网 发布:网络机顶盒怎么刷机 编辑:程序博客网 时间:2024/05/16 03:52

unit uCode;

 

interface

 

uses

    SysUtils,Classes,uSymbolType,uCodeType,uError;

 

type

    TCodes = class

    private

        FError: TError;

        FCode: PInstructions; //--代码表

        FCodeAddress: integer;

        procedure GenerateCode(AType: TInstructionType; ALevel,AAddress: integer);

    public

        constructor Create(pCode: PInstructions; const AError: TError = nil);

        //---

        procedure ListCode(AList: TStrings);

        //---

        procedure GenerateCode_Factor(ASign: TSymbolType);

        procedure GenerateCode_Term(ASign: TSymbolType; const AIsFirst: boolean = false);

        procedure GenerateCode_Condition(ASign: TSymbolType);

        procedure GenerateCode_Return;

        procedure GenerateCode_Odd;

        procedure GenerateCode_AllocMem(ASize: integer);

        procedure GenerateCode_Write;

        procedure GenerateCode_WriteLn;

        procedure GenerateCode_Read(ALevel,AAddress: integer);

        procedure GenerateCode_Call(ALevel,AAddress: integer);

        procedure GenerateCode_SetVar(ALevel,AAddress: integer);

        procedure GenerateCode_GetVar(ALevel,AAddress: integer);

        procedure GenerateCode_SetNum(AValue: integer);

        function GenerateCode_JMP(ADestAddress: integer): integer;

        procedure UpdateAddress_JMP(ASourceAddress,ADestAddress: integer);

        function GenerateCode_JPC(ADestAddress: integer): integer;

        procedure UpdateAddress_JPC(ASourceAddress,ADestAddress: integer);

        //---

        property CodeAddress: integer read FCodeAddress;

    end;

 

implementation

 

uses uErrorInfo;

 

constructor TCodes.Create(pCode: PInstructions; const AError: TError);

begin

    FCode := pCode;

    FError := AError;

end;

 

procedure TCodes.GenerateCode(AType: TInstructionType; ALevel,AAddress:

    integer);

(*

名称:目标代码生成

功能:用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行

参数:

    AType:代码类型

    ALevel, AAddress:代码的两个操作数

*)

    //---

    procedure _ReportError(const AMsg: string);

    begin

        if Assigned(FError) then

            FError.ReportError(AMsg);

    end;

begin

    if FCodeAddress > high(FCode^) then

        _ReportError(CNT_Error4);

    //---写入目标代码

    with FCode[FCodeAddress] do

    begin

        IType := AType;

        Level := ALevel;

        Address := AAddress;

    end;

    //---指向下一个空位

    FCodeAddress := FCodeAddress + 1;

end;

 

procedure TCodes.ListCode(AList: TStrings);

var

    i: integer;

begin

    AList.Clear;

    for i := 0 to FCodeAddress - 1 do

        with FCode[i] do

            AList.Add(format('%.3d : %s  %d , %d', [i,CNT_CodeNames[IType],Level,Address]));

end;

 

procedure TCodes.GenerateCode_Factor(ASign: TSymbolType);

begin

    if ASign = symTimes then

        self.GenerateCode(opr,0,4) //--生成"乘法运算指令"

    else

        self.GenerateCode(opr,0,5); //--生成"除法运算指令"

end;

 

procedure TCodes.GenerateCode_Term(ASign: TSymbolType; const AIsFirst: boolean =

    false);

begin

    if AIsFirst then

    begin

        if ASign = symMinus then

            self.GenerateCode(opr,0,1) //--如果是负号,生成"取反运算指令"; 如果是正号,不需生成指令

    end

    else

    begin

        if ASign = symPlus then

            self.GenerateCode(opr,0,2) //--生成"加法运算指令"

        else

            self.GenerateCode(opr,0,3); //--生成"减法运算指令"

    end;

end;

 

procedure TCodes.GenerateCode_Condition(ASign: TSymbolType);

begin

    case ASign of

        symEql: self.GenerateCode(opr,0,8); //--等号:生成"判等运算指令"

        symNeq: self.GenerateCode(opr,0,9); //--不等号:生成"判不等运算指令"

        symLss: self.GenerateCode(opr,0,10); //--小于号:生成"判小运算指令"

        symGeq: self.GenerateCode(opr,0,11); //--大于等号号:生成"判不小于运算指令"

        symGtr: self.GenerateCode(opr,0,12); //--大于号:生成"判大于运算指令"

        symLeq: self.GenerateCode(opr,0,13); //--小于等于号:生成"判不大于运算指令"

    end;

end;

 

procedure TCodes.GenerateCode_Return;

begin

    self.GenerateCode(opr,0,0); //---生成"从子程序返回操作指令"

end;

 

procedure TCodes.GenerateCode_AllocMem(ASize: integer);

begin

    self.GenerateCode(int,0,ASize); //---生成"分配空间指令",分配ASize个空间

end;

 

procedure TCodes.GenerateCode_WriteLn;

begin

    self.GenerateCode(opr,0,15); //--生成"输出一个换行指令"

end;

 

procedure TCodes.GenerateCode_Write;

begin

    self.GenerateCode(opr,0,14); //--生成"向屏幕输出指令"

end;

 

procedure TCodes.GenerateCode_Read(ALevel,AAddress: integer);

begin

    self.GenerateCode(opr,0,16); //--生成"从键盘读入数字指令"

    self.GenerateCode(sto,ALevel,AAddress); //--生成"sto指令",把读入的值存入指定变量所在的空间

end;

 

procedure TCodes.GenerateCode_Call(ALevel,AAddress: integer);

begin

    self.GenerateCode(cal,ALevel,AAddress); //--生成"调用子过程指令"

end;

 

procedure TCodes.GenerateCode_Odd;

begin

    self.GenerateCode(opr,0,6); //--生成"奇偶判断运算指令"

end;

 

procedure TCodes.GenerateCode_SetVar(ALevel,AAddress: integer);

begin

    self.GenerateCode(sto,ALevel,AAddress); //--生成"更新变量内容指令"

end;

 

procedure TCodes.GenerateCode_SetNum(AValue: integer);

begin

    self.GenerateCode(lit,0,AValue); //--生成"数值放到栈顶指令"

end;

 

procedure TCodes.GenerateCode_GetVar(ALevel,AAddress: integer);

begin

    self.GenerateCode(lod,ALevel,AAddress); //--生成指令,把位于距离当前层level层、偏移地址为Address的变量的值放到栈顶

end;

 

function TCodes.GenerateCode_JMP(ADestAddress: integer): integer;

begin

    Result := FCodeAddress;

    self.GenerateCode(jmp,0,ADestAddress); //---生成"条件跳转指令",跳转位置为ADestAddress

end;

 

procedure TCodes.UpdateAddress_JMP(ASourceAddress,ADestAddress: integer);

begin

    FCode[ASourceAddress].Address := ADestAddress; //---ASourceAddress位置的跳转语句的跳转位置改成ADestAddress位置

end;

 

function TCodes.GenerateCode_JPC(ADestAddress: integer): integer;

begin

    Result := FCodeAddress;

    self.GenerateCode(jpc,0,ADestAddress); //---生成"条件跳转指令",跳转位置为ADestAddress

end;

 

procedure TCodes.UpdateAddress_JPC(ASourceAddress,ADestAddress: integer);

begin

    UpdateAddress_JMP(ASourceAddress,ADestAddress);

end;

 

end.

 

原创粉丝点击