Разработка компилятора подмножества языка Паскаль на язык Ассемблера

Изучение составных частей, основных принципов построения и функционирования компиляторов. Создание компилятора с заданного подмножества языка Паскаль с незначительными модификациями и упрощениями. Грамматика входного языка в форме Бэкуса-Наура.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 20.01.2013
Размер файла 735,6 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Result := MakeSymbolStr(iRuleNum)

else Result := Lexem.LexInfoStr;

end;

destructor TSymbol.Destroy;

var i: integer;

begin

if SymbInfo.SymbType = SYMB_SYNT then

with SymbInfo.LexList do

begin

for i:=Count-1 downto 0 do TSymbol(Items[i]).Free;

Free;

end;

inherited Destroy;

end;

destructor TSymbStack.Destroy;

begin

Clear;

inherited Destroy;

end;

procedure TSymbStack.Clear;

var i: integer;

begin

for i:=Count-1 downto 0 do TSymbol(Items[i]).Free;

inherited Clear;

end;

function TSymbStack.GetSymbol(iIdx: integer): TSymbol;

begin

Result := TSymbol(Items[iIdx]);

end;

function TSymbStack.TopLexem: TLexem;

var i: integer;

begin

Result := nil;

for i:=Count-1 downto 0 do

if Symbols[i].SymbType = SYMB_LEX then

begin

Result := Symbols[i].Lexem;

Break;

end;

end;

function TSymbStack.Push(lex: TLexem): TSymbol;

begin

Result := TSymbol.CreateLex(lex);

Add(Result);

end;

function TSymbStack.MakeTopSymb: TSymbol;

var

symCur: TSymbol;

SymbArr: TSymbArray;

i,iSymbN: integer;

sRuleStr: string;

procedure AddToRule(const sStr: string;

sym: TSymbol);

begin

symCur := sym;

SymbArr[iSymbN] := Symbols[i];

sRuleStr := sStr + sRuleStr;

Delete(i);

Inc(iSymbN);

end;

begin

Result := nil;

iSymbN := 0;

symCur := nil;

sRuleStr := '';

for i:=Count-1 downto 0 do

begin

if Symbols[i].SymbType = SYMB_SYNT then

AddToRule(Symbols[i].SymbolStr,symCur)

else

if symCur = nil then

AddToRule(LexTypeInfo(Symbols[i].Lexem.LexType),

Symbols[i])

else

if GramMatrix[Symbols[i].Lexem.LexType,

symCur.Lexem.LexType] = '=' then

AddToRule(LexTypeInfo(Symbols[i].Lexem.LexType),

Symbols[i])

else

Break;

if iSymbN > RULE_LENGTH then Break;

end;

if iSymbN <> 0 then

begin

for i:=1 to RULE_NUM do

if GramRules[i] = sRuleStr then

begin

Result := TSymbol.CreateSymb(i,iSymbN,SymbArr);

Add(Result);

Break;

end;

if Result = nil then

for i:=0 to iSymbN-1 do SymbArr[i].Free;

end;

end;

function BuildSyntList(

const listLex: TLexList{входная таблица лексем};

symbStack: TSymbStack{стек для работы алгоритма}

): TSymbol;

var

i,iCnt: integer;

lexStop: TLexem;

lexTCur: TLexType;{тип текущей лексемы}

cRule: char;{текущее отношение предшествования}

begin

Result := nil;

iCnt := listLex.Count-1;

lexStop := TLexem.CreateInfo('Начало файла',0,0,0);

try

symbStack.Push(lexStop);

i := 0;

while i<=iCnt do

begin

lexTCur := symbStack.TopLexem.LexType;

if (lexTCur = LEX_START)

and (listLex[i].LexType = LEX_START) then Break;

cRule := GramMatrix[lexTCur,listLex[i].LexType];

cRule := CorrectRule(cRule,lexTCur,

listLex[i].LexType,symbStack);

case cRule of

'<','=':

begin

symbStack.Push(listLex[i]);

Inc(i);

end;

'>':

if symbStack.MakeTopSymb = nil then

begin

Result := TSymbol.CreateLex(listLex[i]);

Break;

end;

else

begin

Result := TSymbol.CreateLex(listLex[i]);

Break;

end;

end{case};

end{while};

if Result = nil then

begin

if symbStack.Count = 2 then

Result := symbStack[1]

else Result := TSymbol.CreateLex(listLex[iCnt]);

end;

finally

lexStop.Free;

end;

end;

end.

unit TblElem;

interface

type

TAddVarInfo = class(TObject)

public

procedure SetInfo(iIdx: integer; iInfo: longint);

virtual; abstract;

function GetInfo(iIdx: integer): longint;

virtual; abstract;

property Info[iIdx: integer]: longint

read GetInfo write SetInfo; default;

end;

TVarInfo = class(TObject)

protected

sName: string;

pInfo: TAddVarInfo;

minEl,maxEl: TVarInfo;

public

constructor Create(const sN: string);

destructor Destroy; override;

procedure SetInfo(pI: TAddVarInfo);

procedure ClearInfo;

procedure ClearAllInfo;

property VarName: string read sName;

property Info: TAddVarInfo read pInfo write SetInfo;

function AddElCnt(const sAdd: string;

var iCnt: integer): TVarInfo;

function AddElem(const sAdd: string): TVarInfo;

function FindElCnt(const sN: string;

var iCnt: integer): TVarInfo;

function FindElem(const sN: string): TVarInfo;

function GetElList(const sLim,sInp,sOut: string): string;

end;

function Upper(const x:string): string;

implementation

uses SysUtils;

{$IFDEF REGNAME}

function Upper(const x:string): string;

begin Result := UpperCase(x); end;

{$ELSE}

function Upper(const x:string): string;

begin Result := x; end;

{$ENDIF}

constructor TVarInfo.Create(const sN: string);

begin

inherited Create;

sName := sN;

pInfo := nil;

minEl := nil;

maxEl := nil;

end;

destructor TVarInfo.Destroy;

begin

ClearAllInfo;

minEl.Free;

maxEl.Free;

inherited Destroy;

end;

function TVarInfo.GetElList(const sLim{разделитель списка},

sInp,sOut{имена, не включаемые в строку}: string): string;

var sAdd: string;

begin

Result := '';

if (Upper(sName) <> Upper(sInp))

and (Upper(sName) <> Upper(sOut)) then Result := sName;

if minEl <> nil then

begin

sAdd := minEl.GetElList(sLim,sInp,sOut);

if sAdd <> '' then

begin

if Result <> '' then Result := Result + sLim + sAdd

else Result := sAdd;

end;

end;

if maxEl <> nil then

begin

sAdd := maxEl.GetElList(sLim,sInp,sOut);

if sAdd <> '' then

begin

if Result <> '' then Result := Result + sLim + sAdd

else Result := sAdd;

end;

end;

end;

procedure TVarInfo.SetInfo(pI: TAddVarInfo);

begin

pInfo := pI;

end;

procedure TVarInfo.ClearInfo;

begin

pInfo.Free;

pInfo := nil;

end;

procedure TVarInfo.ClearAllInfo;

begin

if minEl <> nil then minEl.ClearAllInfo;

if maxEl <> nil then maxEl.ClearAllInfo;

pInfo.Free;

pInfo := nil;

end;

function TVarInfo.AddElCnt(const sAdd: string;

var iCnt: integer): TVarInfo;

var i: integer;

begin

Inc(iCnt);

i := StrComp(PChar(Upper(sAdd)),PChar(Upper(sName)));

if i < 0 then

begin

if minEl <> nil then

Result := minEl.AddElCnt(sAdd,iCnt)

else

begin

Result := TVarInfo.Create(sAdd);

minEl := Result;

end;

end

else

if i > 0 then

begin

if maxEl <> nil then

Result := maxEl.AddElCnt(sAdd,iCnt)

else

begin

Result := TVarInfo.Create(sAdd);

maxEl := Result;

end;

end

else Result := Self;

end;

function TVarInfo.AddElem(const sAdd: string): TVarInfo;

var iCnt: integer;

begin

Result := AddElCnt(sAdd,iCnt);

end;

function TVarInfo.FindElCnt(const sN: string;

var iCnt: integer): TVarInfo;

var i: integer;

begin

Inc(iCnt);

i := StrComp(PChar(Upper(sN)),PChar(Upper(sName)));

if i < 0 then

begin

if minEl <> nil then Result := minEl.FindElCnt(sN,iCnt)

else Result := nil;

end

else

if i > 0 then

begin

if maxEl <> nil then Result := maxEl.FindElCnt(sN,iCnt)

else Result := nil;

end

else Result := Self;

end;

function TVarInfo.FindElem(const sN: string): TVarInfo;

var iCnt: integer;

begin

Result := FindElCnt(sN,iCnt);

end;

end.

unit Triads;

interface

uses Classes, TblElem, LexElem, TrdType;

type

TTriad = class;

TOpType = (OP_CONST, OP_VAR, OP_LINK);

TOperand = record

case OpType: TOpType of

OP_CONST: (ConstVal: integer);

OP_VAR: (VarLink: TVarInfo);

OP_LINK: (TriadNum: integer);

end;

TOpArray = array[1..2] of TOperand;

TTriad = class(TObject)

private

TriadType: TTriadType;

Operands: TOpArray;

public

Info: longint;

IsLinked: Boolean;

constructor Create(Typ: TTriadType; const Ops: TOpArray);

function GetOperand(iIdx: integer): TOperand;

procedure SetOperand(iIdx: integer; Op: TOperand);

function GetLink(iIdx: integer): integer;

procedure SetLink(iIdx: integer; TrdN: integer);

function GetOpType(iIdx: integer): TOpType;

procedure SetOpType(iIdx: integer; OpT: TOpType);

function GetConstVal(iIdx: integer): integer;

procedure SetConstVal(iIdx: integer; iVal: integer);

property TrdType: TTriadType read TriadType;

property Opers[iIdx: integer]: TOperand read GetOperand

write SetOperand; default;

property Links[iIdx: integer]: integer read GetLink

write SetLink;

property OpTypes[iIdx: integer]: TOpType read GetOpType

write SetOpType;

property Values[iIdx: integer]: integer read GetConstVal

write SetConstVal;

function IsEqual(Trd1: TTriad): Boolean;

function MakeString(i: integer): string;

end;

TTriadList = class(TList)

public

procedure Clear; override;

destructor Destroy; override;

procedure WriteToList(list: TStrings);

procedure DelTriad(iIdx: integer);

function GetTriad(iIdx: integer): TTriad;

property Triads[iIdx: integer]: TTriad read GetTriad;

default;

end;

procedure DelTriadTypes(listTriad: TTriadList;

TrdType: TTriadType);

implementation

uses SysUtils, FncTree, LexType;

constructor TTriad.Create(Typ: TTriadType;

const Ops: TOpArray);

var i: integer;

begin

inherited Create;

TriadType := Typ;

for i:=1 to 2 do Operands[i] := Ops[i];

Info := 0;

IsLinked := False;

end;

function TTriad.GetOperand(iIdx: integer): TOperand;

begin

Result := Operands[iIdx];

end;

procedure TTriad.SetOperand(iIdx: integer; Op: TOperand);

begin

Operands[iIdx] := Op;

end;

function TTriad.GetLink(iIdx: integer): integer;

begin

Result := Operands[iIdx].TriadNum;

end;

procedure TTriad.SetLink(iIdx: integer; TrdN: integer);

begin

Operands[iIdx].TriadNum := TrdN;

end;

function TTriad.GetOpType(iIdx: integer): TOpType;

begin

Result := Operands[iIdx].OpType;

end;

function TTriad.GetConstVal(iIdx: integer): integer;

begin

Result := Operands[iIdx].ConstVal;

end;

procedure TTriad.SetConstVal(iIdx: integer; iVal: integer);

begin

Operands[iIdx].ConstVal := iVal;

end;

procedure TTriad.SetOpType(iIdx: integer; OpT: TOpType);

begin

Operands[iIdx].OpType := OpT;

end;

function IsEqualOp(const Op1,Op2: TOperand): Boolean;

begin

Result := (Op1.OpType = Op2.OpType);

if Result then

case Op1.OpType of

OP_CONST: Result := (Op1.ConstVal = Op2.ConstVal);

OP_VAR: Result := (Op1.VarLink = Op2.VarLink);

OP_LINK: Result := (Op1.TriadNum = Op2.TriadNum);

end;

end;

function TTriad.IsEqual(Trd1: TTriad): Boolean;

begin

Result := (TriadType = Trd1.TriadType)

and IsEqualOp(Operands[1],Trd1[1])

and IsEqualOp(Operands[2],Trd1[2]);

end;

function GetOperStr(Op: TOperand): string;

begin

case Op.OpType of

OP_CONST: Result := IntToStr(Op.ConstVal);

OP_VAR: Result := Op.VarLink.VarName;

OP_LINK: Result := '^'+ IntToStr(Op.TriadNum+1);

end{case};

end;

function TTriad.MakeString(i: integer): string;

begin

Result := Format('%d:'#9'%s (%s, %s)',

[i+1,TriadStr[TriadType],

GetOperStr(Opers[1]),GetOperStr(Opers[2])]);

end;

destructor TTriadList.Destroy;

begin

Clear;

inherited Destroy;

end;

procedure TTriadList.Clear;

var i: integer;

begin

for i:=Count-1 downto 0 do TTriad(Items[i]).Free;

inherited Clear;

end;

procedure TTriadList.DelTriad(iIdx: integer);

begin

if iIdx < Count-1 then

TTriad(Items[iIdx+1]).IsLinked :=

TTriad(Items[iIdx+1]).IsLinked

or TTriad(Items[iIdx]).IsLinked;

TTriad(Items[iIdx]).Free;

Delete(iIdx);

end;

function TTriadList.GetTriad(iIdx: integer): TTriad;

begin

Result := TTriad(Items[iIdx]);

end;

procedure TTriadList.WriteToList(list: TStrings);

var

i,iCnt: integer;

begin

list.Clear;

iCnt := Count-1;

for i:=0 to iCnt do

list.Add(TTriad(Items[i]).MakeString(i));

end;

procedure DelTriadTypes(listTriad: TTriadList;

TrdType: TTriadType);

var

i,j,iCnt,iDel: integer;

listNum: TList;

Trd: TTriad;

begin

iDel := 0;

iCnt := listTriad.Count-1;

listNum := TList.Create;

try

for i:=0 to iCnt do

begin

listNum.Add(TObject(iDel));

if listTriad[i].TriadType = TrdType then Inc(iDel);

end;

for i:=iCnt downto 0 do

begin

Trd := listTriad[i];

if Trd.TriadType = TrdType then listTriad.DelTriad(i)

else

for j:=1 to 2 do

if Trd[j].OpType = OP_LINK then

Trd.Links[j] :=

Trd.Links[j] - integer(listNum[Trd.Links[j]]);

end;

finally listNum.Free;

end;

end;

end.

unit TrdType;

interface

const

NAME_PROG = 'MyCurs';

NAME_INPVAR = 'InpVar';

NAME_RESULT = 'Result';

NAME_FUNCT = 'CompileTest';

NAME_TYPE = 'integer';

type

TTriadType = (TRD_IF, TRD_OR, TRD_XOR, TRD_AND, TRD_NOT,

TRD_LT, TRD_GT, TRD_EQ, TRD_NEQ,

TRD_ADD, TRD_SUB, TRD_UMIN, TRD_ASSIGN,

TRD_JMP, TRD_CONST, TRD_SAME, TRD_NOP);

TTriadStr = array[TTriadType] of string;

const

TriadStr: TTriadStr =

('if','or','xor','and','not',

'<','>','=','<>','+','-','-',':=',

'jmp','C','same','nop');

TriadLineSet : set of TTriadType =

[TRD_OR, TRD_XOR, TRD_AND, TRD_NOT, TRD_ADD, TRD_SUB,

TRD_LT, TRD_GT, TRD_EQ, TRD_NEQ, TRD_UMIN];

implementation

end.

unit TrdOpt;

interface

uses Classes, TblElem, LexElem, TrdType, Triads;

type

TConstInfo = class(TAddVarInfo)

protected

iConst: longint;

constructor Create(iInfo: longint);

public

function GetInfo(iIdx: integer): longint; override;

procedure SetInfo(iIdx: integer; iInfo: longint);

override;

end;

TDepInfo = class(TAddVarInfo)

protected

iDep: longint;

constructor Create(iInfo: longint);

public

function GetInfo(iIdx: integer): longint; override;

procedure SetInfo(iIdx: integer; iInfo: longint);

override;

end;

procedure OptimizeConst(listTriad: TTriadList);

procedure OptimizeSame(listTriad: TTriadList);

implementation

uses SysUtils, FncTree, LexType, TrdCalc;

constructor TConstInfo.Create(iInfo: longint);

begin

inherited Create;

iConst := iInfo;

end;

procedure TConstInfo.SetInfo(iIdx: integer;

iInfo: longint);

begin

iConst := iInfo;

end;

function TConstInfo.GetInfo(iIdx: integer): longint;

begin

Result := iConst;

end;

function TestOperConst(Op: TOperand; listTriad: TTriadList;

var iConst: integer): Boolean;

var pInfo: TConstInfo;

begin

Result := False;

case Op.OpType of

OP_CONST:

begin

iConst := Op.ConstVal;

Result := True;

end;

OP_VAR:

begin

pInfo := TConstInfo(Op.VarLink.Info);

if pInfo <> nil then

begin

iConst := pInfo[0];

Result := True;

end;

end;

OP_LINK:

begin

if listTriad[Op.TriadNum].TrdType = TRD_CONST

then

begin

iConst := listTriad[Op.TriadNum][1].ConstVal;

Result := True;

end;

end;

end{case};

end;

procedure OptimizeConst(listTriad: TTriadList);

var

i,j,iCnt,iOp1,iOp2: integer;

Ops: TOpArray;

Trd: TTriad;

begin

ClearTreeInfo;

Ops[1].OpType := OP_CONST;

Ops[2].OpType := OP_CONST;

Ops[2].ConstVal := 0;

iCnt := listTriad.Count-1;

for i:=0 to iCnt do

begin

Trd := listTriad[i];

if Trd.TrdType in TriadLineSet then

begin

for j:=1 to 2 do

if (Trd[j].OpType = OP_LINK)

and (listTriad[Trd.Links[j]].TrdType = TRD_CONST)

then

begin

Trd.OpTypes[j] := OP_CONST;

Trd.Values[j] :=

listTriad[Trd.Links[j]][1].ConstVal;

end;

end

else

if Trd.TrdType = TRD_IF then

begin

if (Trd[1].OpType = OP_LINK)

and (listTriad[Trd.Links[1]].TrdType = TRD_CONST)

then

begin

Trd.OpTypes[1] := OP_CONST;

Trd.Values[1] :=

listTriad[Trd.Links[1]][1].ConstVal;

end;

end

else

if Trd.TrdType = TRD_ASSIGN then

begin

if (Trd[2].OpType = OP_LINK)

and (listTriad[Trd.Links[2]].TrdType = TRD_CONST)

then

begin

Trd.OpTypes[2] := OP_CONST;

Trd.Values[2] :=

listTriad[Trd.Links[2]][1].ConstVal;

end;

end;

if Trd.IsLinked then ClearTreeInfo;

if Trd.TrdType = TRD_ASSIGN then

begin

if TestOperConst(Trd[2],listTriad,iOp2) then

Trd[1].VarLink.Info := TConstInfo.Create(iOp2);

end

else

if Trd.TrdType in TriadLineSet then

begin

if TestOperConst(Trd[1],listTriad,iOp1)

and TestOperConst(Trd[2],listTriad,iOp2) then

begin

Ops[1].ConstVal :=

CalcTriad(Trd.TrdType,iOp1,iOp2);

listTriad.Items[i] := TTriad.Create(TRD_CONST,Ops);

listTriad[i].IsLinked := Trd.IsLinked;

Trd.Free;

end;

end;

end;

end;

constructor TDepInfo.Create(iInfo: longint);

begin

inherited Create;

iDep := iInfo;

end;

procedure TDepInfo.SetInfo(iIdx: integer; iInfo: longint);

begin

iDep := iInfo;

end;

function TDepInfo.GetInfo(iIdx: integer): longint;

begin

Result := iDep;

end;

function CalcDepOp(listTriad: TTriadList;

Op: TOperand): longint;

begin

Result := 0;

case Op.OpType of

OP_VAR:

if Op.VarLink.Info <> nil then Result :=

Op.VarLink.Info.Info[0];

OP_LINK:

Result := listTriad[Op.TriadNum].Info;

end{case};

end;

function CalcDep(listTriad: TTriadList;

Trd: TTriad): longint;

var iDepTmp: longint;

begin

Result := CalcDepOp(listTriad,Trd[1]);

iDepTmp := CalcDepOp(listTriad,Trd[2]);

if iDepTmp > Result then Result := iDepTmp+1

else Inc(Result);

Trd.Info := Result;

end;

procedure OptimizeSame(listTriad: TTriadList);

var

i,j,iStart,iCnt,iNum: integer;

Ops: TOpArray;

Trd: TTriad;

begin

iStart := 0;

ClearTreeInfo;

iCnt := listTriad.Count-1;

Ops[1].OpType := OP_LINK;

Ops[2].OpType := OP_CONST;

Ops[2].ConstVal := 0;

for i:=0 to iCnt do

begin

Trd := listTriad[i];

if Trd.IsLinked then

begin

ClearTreeInfo;

iStart := i;

end;

for j:=1 to 2 do

if Trd[j].OpType = OP_LINK then

begin

iNum := Trd[j].TriadNum;

if listTriad[iNum].TrdType = TRD_SAME then

Trd.Links[j] := listTriad[iNum].Links[1];

end;

if Trd.TrdType = TRD_ASSIGN then

begin

Trd[1].VarLink.Info := TDepInfo.Create(i+1);

end

else

if Trd.TrdType in TriadLineSet then

begin

CalcDep(listTriad,Trd);

for j:=iStart to i-1 do

begin

if Trd.IsEqual(listTriad[j])

and (Trd.Info = listTriad[j].Info) then

begin

Ops[1].TriadNum := j;

listTriad.Items[i] :=

TTriad.Create(TRD_SAME,Ops);

listTriad[i].IsLinked := Trd.IsLinked;

Trd.Free;

Break;

end;

end;

end{if};

end{for};

end;

end.

unit TrdCalc;

interface

uses TrdType;

function CalcTriad(Triad: TTriadType;

iOp1,iOp2: integer): integer;

implementation

function CalcTriad(Triad: TTriadType;

iOp1,iOp2: integer): integer;

begin

Result := 0;

case Triad of

TRD_OR: Result := (iOp1 or iOp2) and 1;

TRD_XOR: Result := (iOp1 xor iOp2) and 1;

TRD_AND: Result := (iOp1 and iOp2) and 1;

TRD_NOT: Result := (not iOp1) and 1;

TRD_LT: if iOp1<iOp2 then Result := 1

else Result := 0;

TRD_GT: if iOp1>iOp2 then Result := 1

else Result := 0;

TRD_EQ: if iOp1=iOp2 then Result := 1

else Result := 0;

TRD_NEQ: if iOp1<>iOp2 then Result := 1

else Result := 0;

TRD_ADD: Result := iOp1 + iOp2;

TRD_SUB: Result := iOp1 - iOp2;

TRD_UMIN: Result := -iOp2;

end;

end;

end.

unit TrdMake;

interface

uses LexElem, Triads, SyntSymb;

function MakeTriadList(symbTop: TSymbol;

listTriad: TTriadList): TLexem;

implementation

uses LexType, TrdType;

function GetLexem(symbOp: TSymbol): TLexem;

begin

case symbOp.Rule of

0: Result := symbOp.Lexem;

27,28: Result := symbOp[0].Lexem;

19,26: Result := GetLexem(symbOp[1])

else Result := nil;

end;

end;

function MakeTriadListNOP(symbTop: TSymbol;

listTriad: TTriadList): TLexem;

var

Opers: TOpArray;

iIns1,iIns2,iIns3: integer;

function MakeOperand(

iOp{номер операнда},

iSymOp{порядковый номер символа в синт. конструкции},

iMin{минимальная позиция триады в списке},

iSymErr{номер лексемы, на которой

позиционировать ошибку}: integer;

var iIns: integer{индекс триады в списке}): TLexem;

var lexTmp: TLexem;

begin

lexTmp := GetLexem(symbTop[iSymOp]);

if lexTmp <> nil then

with lexTmp do

begin

if LexType = LEX_VAR then

begin

if VarInfo.VarName = NAME_RESULT then

begin

Result := lexTmp;

Exit;

end;

Opers[iOp].OpType := OP_VAR;

Opers[iOp].VarLink := VarInfo;

end

else

if LexType = LEX_CONST then

begin

Opers[iOp].OpType := OP_CONST;

Opers[iOp].ConstVal := ConstVal;

end

else

begin

Result := lexTmp;

Exit;

end;

iIns := iMin;

Result := nil;

end

else

begin

Result := MakeTriadListNOP(symbTop[iSymOp],listTriad);

if Result <> nil then Exit;

iIns := listTriad.Count;

if iIns <= iMin then

begin

Result := symbTop[iSymErr].Lexem;

Exit;

end;

Opers[iOp].OpType := OP_LINK;

Opers[iOp].TriadNum := iIns-1;

end;

end;

function MakeOperation(

Trd: TTriadType{тип создаваемой триады}): TLexem;

begin

Result := MakeOperand(1{op},0{sym},listTriad.Count,

1{sym err},iIns1);

if Result <> nil then Exit;

Result := MakeOperand(2{op},2{sym},iIns1,

1{sym err},iIns2);

if Result <> nil then Exit;

listTriad.Add(TTriad.Create(Trd,Opers));

end;

begin

case symbTop.Rule of

5:{'if(B)EelseE'}

begin

Result := MakeOperand(1{op},2{sym},listTriad.Count,

1{sym err},iIns1);

if Result <> nil then Exit;

Opers[2].OpType := OP_LINK;

Opers[2].TriadNum := 0;

listTriad.Add(TTriad.Create(TRD_IF,Opers));

Result := MakeOperand(2{op},4{sym},iIns1,

3{sym err},iIns2);

if Result <> nil then Exit;

Opers[1].OpType := OP_CONST;

Opers[1].ConstVal := 1;

Opers[2].OpType := OP_LINK;

Opers[2].TriadNum := 0;

listTriad.Add(TTriad.Create(TRD_JMP,Opers));

listTriad[iIns1].Links[2] := iIns2+1;

Result := MakeOperand(2{op},6{sym},iIns2,

5{sym err},iIns3);

if Result <> nil then Exit;

listTriad[iIns2].Links[2] := iIns3;

end;

6:{'if(B)E'}

begin

Result := MakeOperand(1{op},2{sym},listTriad.Count,

1{sym err},iIns1);

if Result <> nil then Exit;

Opers[2].OpType := OP_LINK;

Opers[2].TriadNum := 0;

listTriad.Add(TTriad.Create(TRD_IF,Opers));

Result := MakeOperand(2{op},4{sym},iIns1,

3{sym err},iIns2);

if Result <> nil then Exit;

listTriad[iIns1].Links[2] := iIns2;

end;

8:{'while(B)doE'}

begin

iIns3 := listTriad.Count;

Result := MakeOperand(1{op},2{sym},iIns3,

1{sym err},iIns1);

if Result <> nil then Exit;

Opers[2].OpType := OP_LINK;

Opers[2].TriadNum := 0;

listTriad.Add(TTriad.Create(TRD_IF,Opers));

Result := MakeOperand(2{op},5{sym},iIns1,

4{sym err},iIns2);

if Result <> nil then Exit;

Opers[1].OpType := OP_CONST;

Opers[1].ConstVal := 1;

Opers[2].OpType := OP_LINK;

Opers[2].TriadNum := iIns3;

{ Создаем триаду типа "JMP" }

listTriad.Add(TTriad.Create(TRD_JMP,Opers));

listTriad[iIns1].Links[2] := iIns2+1;

end;

9:{'a:=E'}

begin

if symbTop[0].Lexem.LexType <> LEX_VAR then

begin

Result := symbTop[0].Lexem;

Exit;

end;

if (symbTop[0].Lexem.VarName = NAME_INPVAR)

or (symbTop[0].Lexem.VarName = NAME_RESULT) then

begin

Result := symbTop[0].Lexem;

Exit;

end;

Opers[1].OpType := OP_VAR;

Opers[1].VarLink := symbTop[0].Lexem.VarInfo;

Result := MakeOperand(2{op},2{sym},listTriad.Count,

1{sym err},iIns1);

if Result <> nil then Exit;

listTriad.Add(TTriad.Create(TRD_ASSIGN,Opers));

end;

10:{'BorB'} Result := MakeOperation(TRD_OR);

11:{'BxorB'} Result := MakeOperation(TRD_XOR);

13:{'BandB'} Result := MakeOperation(TRD_AND);

15:{'E<E'} Result := MakeOperation(TRD_LT);

16:{'E>E'} Result := MakeOperation(TRD_GT);

17:{'E=E'} Result := MakeOperation(TRD_EQ);

18:{'E<>E'} Result := MakeOperation(TRD_NEQ);

21:{'E-E'} Result := MakeOperation(TRD_SUB);

22:{'E+E'} Result := MakeOperation(TRD_ADD);

20:{not(B)}

begin

Result := MakeOperand(1{op},2{sym},listTriad.Count,

1{sym err},iIns1);

if Result <> nil then Exit;

Opers[2].OpType := OP_CONST;

Opers[2].ConstVal := 0;

listTriad.Add(TTriad.Create(TRD_NOT,Opers));

end;

24:{uminE}

begin

Result := MakeOperand(2{op},1{sym},listTriad.Count,

0{sym err},iIns1);

if Result <> nil then Exit;

Opers[1].OpType := OP_CONST;

Opers[1].ConstVal := 0;

listTriad.Add(TTriad.Create(TRD_UMIN,Opers));

end;

1,7,19,26:{'progEend.','beginEend','(E)','(B)'}

Result := MakeTriadListNOP(symbTop[1],listTriad);

3:{E;E}

begin

Result := MakeTriadListNOP(symbTop[0],listTriad);

if Result <> nil then Exit;

Result := MakeTriadListNOP(symbTop[2],listTriad);

end;

27,28: Result := nil;

else Result := MakeTriadListNOP(symbTop[0],listTriad);

end{case Rule};

end;

function MakeTriadList(symbTop: TSymbol;

listTriad: TTriadList): TLexem;

var

i: integer;

Opers: TOpArray;

Trd: TTriad;

begin

Result := MakeTriadListNOP(symbTop,listTriad);

if Result = nil then

with listTriad do

begin

Opers[1].OpType := OP_CONST;

Opers[1].ConstVal := 0;

Opers[2].OpType := OP_CONST;

Opers[2].ConstVal := 0;

Add(TTriad.Create(TRD_NOP,Opers));

for i:=Count-1 downto 0 do

begin

Trd := Triads[i];

if Trd.TrdType in [TRD_IF,TRD_JMP] then

begin

if Trd.OpTypes[2] = OP_LINK then

listTriad[Trd.Links[2]].IsLinked := True;

end;

end;

end;

end;

end.

unit TrdAsm;

interface

uses Classes, TrdType, Triads;

const

TEMP_VARNAME = '_Tmp';

NUM_PROCREG = 6;

function MakeRegisters(listTriad: TTriadList): integer;

function MakeAsmCode(listTriad: TTriadList;

listCode: TStrings;

flagOpt: Boolean): integer;

implementation

uses SysUtils;

function MakeRegisters(listTriad: TTriadList): integer;

var

i,j,iR,iCnt,iNum : integer;

listReg: TList;

begin

Result := 0;

listReg := TList.Create;

if listReg <> nil then

try

for i:=listTriad.Count-1 downto 0 do

listTriad[i].Info := 0;

for i:=listTriad.Count-1 downto 0 do

for j:=1 to 2 do

if ((listTriad[i].TrdType in TriadLineSet)

or (listTriad[i].TrdType = TRD_IF) and (j = 1)

or (listTriad[i].TrdType = TRD_ASSIGN) and (j = 2))

and (listTriad[i][j].OpType = OP_LINK) then

begin

iNum := listTriad[i][j].TriadNum;

if (listTriad[iNum].Info = 0) and (iNum <> i-1) then

begin

iCnt := listReg.Count-1;

for iR:=0 to iCnt do

begin

if longint(listReg[iR]) >= i then

begin

listReg[iR] := TObject(iNum);

listTriad[iNum].Info := iR+1;

Break;

end;

end;

if listTriad[iNum].Info = 0 then

begin

listReg.Add(TObject(iNum));

listTriad[iNum].Info := listReg.Count;

end;

end;

end;

Result := listReg.Count - (NUM_PROCREG-1);

finally listReg.Free;

end;

end;

function GetRegName(iInfo: integer): string;

begin

case iInfo of

0: Result := 'eax';

1: Result := 'ebx';

2: Result := 'ecx';

3: Result := 'edx';

4: Result := 'esi';

5: Result := 'edi';

else Result :=

Format('%s%d',[TEMP_VARNAME,iInfo-NUM_PROCREG]);

end{case};

end;

function GetOpName(i: integer; listTriad: TTriadList;

iOp: integer): string;

var

iNum: integer;

Triad: TTriad;

begin

Triad := listTriad[i];

case Triad[iOp].OpType of

OP_CONST: Result := IntToStr(Triad[iOp].ConstVal);

OP_VAR:

begin

Result := Triad[iOp].VarLink.VarName;

if Result = NAME_FUNCT then Result := NAME_RESULT;

end;

else

begin

iNum := Triad[iOp].TriadNum;

if iNum = i-1 then Result := ''

else

begin

iNum := listTriad[iNum].Info;

if iNum = 0 then Result := ''

else Result := GetRegName(iNum);

end;

end;

end{case};

end;

function MakeMove(const sReg,{имя регистра}

sPrev,{предыдущая команда}

sVal{предыдущая величина в eax}: string;

flagOpt: Boolean{флаг оптимизации}): string;

begin

if (Pos(Format(#9'mov'#9'%s,eax',[sReg]),sPrev) = 1)

or (sVal = sReg) then

begin

Result := '';

Exit;

end;

if flagOpt then

begin

if sReg = '0' then

begin

if sVal = '-1' then

Result := #9'inc'#9'eax'

else

if sVal = '1' then

Result := #9'dec'#9'eax'

else

Result := #9'xor'#9'eax,eax'

end

else

if sReg = '1' then

begin

if sVal = '-1' then

Result := #9'neg'#9'eax'

else

if sVal = '0' then

Result := #9'inc'#9'eax'

else

Result := #9'xor'#9'eax,eax'#13#10#9'inc'#9'eax';

end

else

if sReg = '-1' then

begin

if sVal = '1' then

Result := #9'neg'#9'eax'

else

if sVal = '0' then

Result := #9'dec'#9'eax'

else

Result := #9'xor'#9'eax,eax'#13#10#9'dec'#9'eax';

end

else Result := Format(#9'mov'#9'eax,%s',[sReg]);

end

else Result := Format(#9'mov'#9'eax,%s',[sReg]);

end;

function MakeOpcode(i: integer;{номер текущей триады}

listTriad: TTriadList;{список триад}

const sOp,sReg,{код операции и операнд}

sPrev,{предыдущая команда}

sVal{предыдущая величина в eax}: string;

flagOpt: Boolean{флаг оптимизации}): string;

var Triad: TTriad;{текущая триада}

begin

Triad := listTriad[i];

if flagOpt then

begin

if sReg = '0' then

begin

case Triad.TrdType of

TRD_AND:

Result := MakeMove('0',sPrev,sVal,flagOpt);

TRD_OR,TRD_ADD,TRD_SUB: Result := #9#9;

else Result := Format(#9'%s'#9'eax,%s',[sOp,sReg]);

end{case};

end

else

if sReg = '1' then

begin

case Triad.TrdType of

TRD_OR:

Result := MakeMove('1',sPrev,sVal,flagOpt);

TRD_AND: Result := #9#9;

TRD_ADD: Result := #9'inc'#9'eax';

TRD_SUB: Result := #9'dec'#9'eax';

else Result := Format(#9'%s'#9'eax,%s',[sOp,sReg]);

end{case};

end

else

if sReg = '-1' then

begin

case Triad.TrdType of

TRD_ADD: Result := #9'dec'#9'eax';

TRD_SUB: Result := #9'inc'#9'eax';

else Result := Format(#9'%s'#9'eax,%s',[sOp,sReg]);

end{case};

end

else Result := Format(#9'%s'#9'eax,%s',[sOp,sReg]);

end

else Result := Format(#9'%s'#9'eax,%s',[sOp,sReg]);

Result := Result + Format(#9'{ %s }',

[Triad.MakeString(i)]);

end;

function MakeAsmCode(

listTriad: TTriadList;{входной список триад}

listCode: TStrings;{список строк рез. кода}

flagOpt: Boolean{флаг оптимизации}): integer;

var

i,iCnt: integer;{счетчик и переменная цикла}

sR: string;{строка для имени регистра}

sPrev,sVal: string;

procedure TakePrevAsm;

var j: integer;

begin

j := listCode.Count;

if j > 0 then

begin

sPrev := listCode[j-1];

sVal := StrPas(PChar(listCode.Objects[j-1]));

end

else

begin

sPrev := '';

sVal := '';

end;

end;

procedure MakeOper1(const sOp,{код операции}

sAddOp: string;{код доп. операции}

iOp: integer{номер операнда в триаде});

var sReg{строка для имени регистра}: string;

begin

TakePrevAsm;

sReg := GetOpName(i,listTriad,iOp);

if sReg <> '' then

begin

sReg := MakeMove(sReg,sPrev,sVal,flagOpt);

if sReg <> '' then listCode.Add(sReg);

end;

listCode.Add(Format(#9'%s'#9'eax'#9'{ %s }',

[sOp,listTriad[i].MakeString(i)]));

if sAddOp <> '' then

listCode.Add(Format(#9'%s'#9'eax,1',[sAddOp]));

if listTriad[i].Info <> 0 then

begin

sReg := GetRegName(listTriad[i].Info);

listCode.AddObject(Format(#9'mov'#9'%s,eax',[sReg]),

TObject(PChar(sReg)));

end;

end;

procedure MakeOper2(const sOp,

sAddOp: string{код доп. операции});

var sReg1,sReg2{строки для имен регистров}: string;

begin

TakePrevAsm;

sReg1 := GetOpName(i,listTriad,1);

sReg2 := GetOpName(i,listTriad,2);

if (sReg1 = '') or (sReg1 = sVal) then

listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,

sPrev,sVal,flagOpt))

else

if (sReg2 = '') or (sReg2 = sVal) then

begin

listCode.Add(MakeOpCode(i,listTriad,sOp,sReg1,

sPrev,sVal,flagOpt));

if sAddOp <> '' then

listCode.Add(Format(#9'%s'#9'eax',[sAddOp]));

end

else

begin

sReg1 := MakeMove(sReg1,sPrev,sVal,flagOpt);

if sReg1 <> '' then listCode.Add(sReg1);

listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,

sPrev,sVal,flagOpt));

end;

if listTriad[i].Info <> 0 then

begin

sReg1 := GetRegName(listTriad[i].Info);

listCode.AddObject(Format(#9'mov'#9'%s,eax',[sReg1]),

TObject(PChar(sReg1)));

end;

end;

procedure MakeCompare(const sOp: string

var sReg1,sReg2{строки для имен регистров}: string;

begin

TakePrevAsm;

sReg1 := GetOpName(i,listTriad,1);

sReg2 := GetOpName(i,listTriad,2);

if sReg1 = '' then

listCode.Add(Format(#9'cmp'#9'eax,%s'#9'{ %s }',

[sReg2,listTriad[i].MakeString(i)]))

else

if sReg2 = '' then

listCode.Add(Format(#9'cmp'#9'%s,eax'#9'{ %s }',

[sReg1,listTriad[i].MakeString(i)]))

else

begin

sReg1 := MakeMove(sReg1,sPrev,sVal,flagOpt);

if sReg1 <> '' then listCode.Add(sReg1);

listCode.Add(Format(#9'cmp'#9'eax,%s'#9'{ %s }',

[sReg2,listTriad[i].MakeString(i)]));

end;

listCode.Add(Format(#9'set%s'#9'al',[sOp]));

listCode.Add(#9'and'#9'eax,1');

if listTriad[i].Info <> 0 then

begin

sReg1 := GetRegName(listTriad[i].Info);

listCode.AddObject(Format(#9'mov'#9'%s,eax',[sReg1]),

TObject(PChar(sReg1)));

end;

end;

begin

iCnt := listTriad.Count-1;

for i:=0 to iCnt do

begin

if listTriad[i].IsLinked then

listCode.Add(Format('@M%d:',[i+1]));

case listTriad[i].TrdType of

TRD_IF:

begin

if listTriad[i][1].OpType = OP_CONST then

begin

if listTriad[i][1].ConstVal = 0 then

listCode.Add(Format(#9'jmp'#9'@M%d'#9'{ %s }',

[listTriad[i][2].TriadNum+1,

listTriad[i].MakeString(i)]));

end

else

begin

sR := GetOpName(i,listTriad,1);

if sR = '' then

(* listCode.Add(#9'test'#9'eax,eax') *)

else

listCode.Add(Format(#9'cmp'#9'%s,0',[sR]));

listCode.Add(Format(#9'jnz'#9'@F%d'#9'{ %s }',

[i,listTriad[i].MakeString(i)]));

listCode.Add(Format(#9'jmp'#9'@M%d',

[listTriad[i][2].TriadNum+1]));

listCode.Add(Format('@F%d:',[i]));

end;

end;

TRD_OR: MakeOper2('or','');

TRD_XOR: MakeOper2('xor','');

TRD_AND: MakeOper2('and','');

TRD_NOT: MakeOper1('not','and',1);

TRD_LT: MakeCompare('l');

TRD_GT: MakeCompare('g');

TRD_EQ: MakeCompare('e');

TRD_NEQ: MakeCompare('ne');

TRD_ADD: MakeOper2('add','');

TRD_SUB: MakeOper2('sub','neg');

TRD_UMIN: MakeOper1('neg','',2);

TRD_ASSIGN:

begin

TakePrevAsm;

sR := GetOpName(i,listTriad,2);

if sR <> '' then

begin

sVal := MakeMove(sR,sPrev,sVal,flagOpt);

if sVal <> '' then listCode.Add(sVal);

end;

sVal := listTriad[i][1].VarLink.VarName;

if sVal = NAME_FUNCT then sVal := NAME_RESULT;

sVal := Format(#9'mov'#9'%s,eax'#9'{ %s }',

[sVal,listTriad[i].MakeString(i)]);

listCode.AddObject(sVal,TObject(PChar(sR)));

end;

TRD_JMP: listCode.Add(

Format(#9'jmp'#9'@M%d'#9'{ %s }',

[listTriad[i][2].TriadNum+1,

listTriad[i].MakeString(i)]));

TRD_NOP: listCode.Add(Format(#9'nop'#9#9'{ %s }',

[listTriad[i].MakeString(i)]));

end{case};

end{for};

Result := listCode.Count;

end;

end.

Размещено на Allbest.ru


Подобные документы

  • Взаимосвязь стадий процесса проектирования сложных программных систем. Создание компилятора подмножества языка высокого уровня (Pascal) на язык Ассемблера. Структура входных и выходных данных, алгоритмы их обработки. Рабочая документация программы.

    курсовая работа [256,7 K], добавлен 27.07.2014

  • Разработка анализирующей части компилятора для выполнения проверки исходной программы на соответствие грамматике языка, правилам семантики и построения внутреннего представления. Описание анализаторов: лексического, синтаксического и семантического.

    контрольная работа [704,9 K], добавлен 01.02.2013

  • Логические конструкции в системе программирования Паскаль. Команды языка программирования, использование функций, процедур. Постановка и решение задач механики в среде системы Паскаль. Задачи статики, кинематики, динамики решаемые с помощью языка Паскаль.

    курсовая работа [290,9 K], добавлен 05.12.2008

  • Лингвистическая концепция языка Паскаль. Интегрированная инструментальная оболочка. Основы построения программ на ТП 7.0. Алфавит языка и специфика использования символов. Простые типы данных: константы и переменные. Циклические конструкции и операции.

    курсовая работа [284,6 K], добавлен 02.07.2011

  • Общая характеристика языков программирования. Описание языка Паскаль: основные субъекты языка; структура Паскаль-программы; типизация и объявление данных. Операторы присваивания и выражения. Структурные операторы, организация ветвлений и циклов.

    дипломная работа [276,6 K], добавлен 26.01.2011

  • Основные понятия теории грамматик простого и операторного предшествования, алгоритмы синтаксического разбора предложения для классов КС-грамматик; разработка дерева вывода для грамматики входного языка в форме Бэкуса-Наура с указанием шагов построения.

    лабораторная работа [28,0 K], добавлен 24.07.2012

  • Создание приложения, исполняющего трансляцию программы из языка Паскаль в язык Си: разработка алгоритма реализации задачи, описание необходимых констант, переменных, функций и операторов, представление листинга программы и распечатка результатов.

    курсовая работа [305,9 K], добавлен 03.07.2011

  • Структура, классификация и требования к реализации компилятора. Проектирование и реализация анализирующей части компилятора языка С++. Способы реализации лексического анализа. Алгоритм работы синтаксического анализатора. Принципы программной реализации.

    курсовая работа [774,2 K], добавлен 26.01.2013

  • Основные сведения о системе программирования Турбо Паскаль. Структура программы на Паскале и ее компоненты. Особенности и элементы языка Турбо Паскаль. Порядок выполнения операций в арифметическом выражении, стандартные функции и оператор присваивания.

    лекция [55,7 K], добавлен 21.05.2009

  • Транслятор как программа или техническое средство, выполняющее трансляцию программы. Рассмотрение основных особенностей постройки лексического анализатора. Знакомство с этапами разработки транслятора с ограниченного подмножества языка высокого уровня.

    курсовая работа [580,5 K], добавлен 06.08.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.