- •Постановка задачи.
- •Теоретический раздел. Основные понятия.
- •Некоторые возможности Макроязыка
- •Структуры данных Макропроцессора
- •Основные алгоритмы программы.
- •Руководство пользователя.
- •Описание макроязыка.
- •Описание разработанных модулей.
- •Описание разработанных тестов.
- •Список использованной литературы.
- •Листинг программы. Модуль mp.
- •Модуль Assembler.
- •Модуль Main.
- •Модуль MacroGen.
- •Модуль Expr.
- •Модуль Strings.
Модуль Main.
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, MacroGen, Grids, ExtCtrls, Buttons, Expr;
type
TForm1 = class(TForm)
firstStepButton: TButton;
Shape2: TShape;
errorsMemo: TMemo;
Shape4: TShape;
secondStepButton: TButton;
marksGrid: TStringGrid;
Shape6: TShape;
localsGrid: TStringGrid;
Shape8: TShape;
stepButton: TButton;
outputGrid: TStringGrid;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Shape1: TShape;
Shape3: TShape;
MDefNameGrid: TStringGrid;
Label5: TLabel;
Label6: TLabel;
exitButton: TButton;
Shape5: TShape;
macroDefGrid: TStringGrid;
Label7: TLabel;
stepModeCheckbox: TCheckBox;
srcCodeMemo: TMemo;
loadButton: TButton;
OpenDialog1: TOpenDialog;
procedure firstStepButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure secondStepButtonClick(Sender: TObject);
procedure stepButtonClick(Sender: TObject);
procedure exitButtonClick(Sender: TObject);
procedure stepModeCheckboxClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure loadButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
TMO_FILE_NAME = 'TMO.txt';
TIM_FILE_NAME = 'TIM.txt';
var
Form1: TForm1;
inputFileName : string = 'input.txt';
outputFileName : string = 'output.txt';
numSrcStr : integer;
srcCode : array [0..MAX_SRC_LEN - 1] of string;
function loadSrcCode(fileName: string): integer;
procedure outResultInFiles;
implementation
{$R *.dfm}
function loadSrcCode(fileName: string): integer;
var
i : integer;
srcFile : text;
begin
assignFile(srcFile, fileName);
reset(srcFile);
i := 0;
while (not eof(srcFile)) do
begin
readln(srcFile, srcCode[i]);
inc(i);
end;
result := i;
for i := 0 to result - 1 do
begin
srcCode[i] := ansiUpperCase(srcCode[i]);
end;
closeFile(srcFile);
end;
procedure outErrors(result: TResult);
begin
if (result.code = NORM_RESULT) then
form1.errorsMemo.Lines.SetText('Ошибок не найдено')
else
form1.errorsMemo.Lines.SetText(PAnsiChar(ERR_DESC[result.code - 1] + ' : ' + result.additionalInfo));
end;
procedure clearOutputs;
var
i: integer;
begin
for i := 0 to form1.macroDefGrid.RowCount - 1 do
form1.macroDefGrid.Rows[i].Clear;
for i := 0 to form1.outputGrid.RowCount - 1 do
form1.outputGrid.Rows[i].Clear;
for i := 0 to form1.marksGrid.RowCount - 1 do
form1.marksGrid.Rows[i].Clear;
for i := 0 to form1.localsGrid.RowCount - 1 do
form1.localsGrid.Rows[i].Clear;
form1.errorsMemo.Clear;
end;
procedure outResultInFiles;
var
outputFile : textFile; interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, ExtCtrls, StdCtrls, AVLTree, Assembler, macroGen, strings;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
InputGrid: TStringGrid;
Label1: TLabel;
Panel3: TPanel;
Label2: TLabel;
OpCodeGrid: TStringGrid;
Label3: TLabel;
TempGrid: TStringGrid;
Label4: TLabel;
SymbNameGrid: TStringGrid;
Label7: TLabel;
OutputMemo: TMemo;
FirstParseButton: TButton;
SecondParseButton: TButton;
errMemo: TMemo;
Label5: TLabel;
firstStepButton: TButton;
secondStepButton: TButton;
srcCodeMemo: TMemo;
macroDefGrid: TStringGrid;
marksGrid: TStringGrid;
localsGrid: TStringGrid;
MDefNameGrid: TStringGrid;
stepModeCheckBox: TCheckBox;
stepButton: TButton;
Label6: TLabel;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Label11: TLabel;
Button1: TButton;
Button2: TButton;
OpenDialog1: TOpenDialog;
procedure FirstParseButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure SecondParseButtonClick(Sender: TObject);
procedure InputGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure OpCodeGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure TempGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
procedure firstStepButtonClick(Sender: TObject);
procedure secondStepButtonClick(Sender: TObject);
procedure stepButtonClick(Sender: TObject);
procedure stepModeCheckBoxClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
TMO_FILE_NAME = 'TMO.txt';
TIM_FILE_NAME = 'TIM.txt';
var
Form1: TForm1;
inputFileName : string = 'input.txt';
macroOutputFileName : string = 'macroOutput.txt';
asmOutputFileName : string = 'asmOutput.txt';
numSrcStr : integer;
srcCode : array [0..MAX_SRC_LEN - 1] of string;
function loadSrcCode(fileName: string): integer;
procedure outResultInFiles;
implementation
{$R *.dfm}
procedure outResultInFiles;
var
outputFile : textFile;
i : integer;
numCurrOutputStr,
numCurrMacroDefStr,
numCurrMacroDesc : integer;
currOutput : array [0..MAX_OUTPUT_LEN - 1] of string;
currMacroDef : array [0..MAX_MACRO_DEF_STR - 1] of TMacroDefStr;
currMacroDesc : array [0..MAX_MACRO_DESC - 1] of TMacroDesc;
begin
assignFile(outputFile, macroOutputFileName);
rewrite(outputFile);
getCurrOutput(currOutput, numCurrOutputStr);
for i := 0 to numCurrOutputStr - 1 do
begin
writeln(outputFile, currOutput[i]);
end;
closeFile(outputFile);
assignFile(outputFile, asmOutputFileName);
rewrite(outputFile);
for i := 0 to numLines - 1 do
begin
writeln(outputFile, Output[i]);
end;
closeFile(outputFile);
assignFile(outputFile, TMO_FILE_NAME);
rewrite(outputFile);
getCurrMacroDef(currMacroDef, numCurrMacroDefStr);
for i := 0 to numCurrMacroDefStr - 1 do
begin
writeln(outputFile, intToStr(i) + ' ' + currMacroDef[i].str);
end;
closeFile(outputFile);
assignFile(outputFile, TIM_FILE_NAME);
rewrite(outputFile);
getCurrMacroDesc(currMacroDesc, numCurrMacroDesc);
for i := 0 to numCurrMacroDesc - 1 do
begin
writeln(outputFile, currMacroDesc[i].name + ' ' + intToStr(currMacroDesc[i].startAddr) + ' ' +
intToStr(currMacroDesc[i].endAddr));
end;
closeFile(outputFile);
end;
function loadSrcCode(fileName: string): integer;
var
i : integer;
srcFile : text;
begin
assignFile(srcFile, fileName);
reset(srcFile);
i := 0;
while (not eof(srcFile)) do
begin
readln(srcFile, srcCode[i]);
inc(i);
end;
result := i;
for i := 0 to result - 1 do
begin
srcCode[i] := ansiUpperCase(srcCode[i]);
end;
closeFile(srcFile);
end;
procedure outErrors(result: TResult);
begin
if (result.code = NORM_RESULT) then
form1.errMemo.Lines.SetText('Ошибок не найдено')
else
form1.errMemo.Lines.SetText(PAnsiChar(ERR_DESC[result.code - 1] + ' : ' + result.additionalInfo));
end;
procedure clearOutputs;
var
i: integer;
begin
for i := 0 to form1.macroDefGrid.RowCount - 1 do
form1.macroDefGrid.Rows[i].Clear;
for i := 0 to form1.marksGrid.RowCount - 1 do
form1.marksGrid.Rows[i].Clear;
for i := 0 to form1.localsGrid.RowCount - 1 do
form1.localsGrid.Rows[i].Clear;
form1.errMemo.Clear;
end;
procedure updateOutputs;
var
selRect : TGridRect;
outputFile : textFile;
i,
currStrNum,
numCurrMacroMarks,
numCurrLocals,
numCurrOutputStr,
numCurrMacroDefStr,
numCurrMacroDesc : integer;
currMacroMarks : array [0..MAX_MARKS - 1] of TMacroMark;
currLocals : array [0..MAX_LOCALS - 1] of TParamPair;
currOutput : array [0..MAX_OUTPUT_LEN - 1] of string;
currMacroDef : array [0..MAX_MACRO_DEF_STR - 1] of TMacroDefStr;
currMacroDesc : array [0..MAX_MACRO_DESC - 1] of TMacroDesc;
begin
getCurrMacroMarks(currMacroMarks, numCurrMacroMarks);
form1.marksGrid.RowCount := numCurrMacroMarks;
for i := 0 to numCurrMacroMarks - 1 do
begin
form1.marksGrid.Cells[0, i] := currMacroMarks[i].name;
form1.marksGrid.Cells[1, i] := intToStr(currMacroMarks[i].addr);
end;
getCurrLocals(currLocals, numCurrLocals);
form1.localsGrid.RowCount := numCurrLocals;
for i := 0 to numCurrLocals - 1 do
begin
form1.localsGrid.Cells[0, i] := currLocals[i].name;
form1.localsGrid.Cells[1, i] := currLocals[i].val;
end;
getCurrMacroDef(currMacroDef, numCurrMacroDefStr);
form1.macroDefGrid.RowCount := numCurrMacroDefStr;
for i := 0 to numCurrMacroDefStr - 1 do
begin
form1.macroDefGrid.Cells[0, i] := intToStr(i);
form1.macroDefGrid.Cells[1, i] := currMacroDef[i].str;
end;
getCurrMacroDesc(currMacroDesc, numCurrMacroDesc);
form1.MDefNameGrid.RowCount := numCurrMacroDesc;
for i := 0 to numCurrMacroDesc - 1 do
begin
form1.MDefNameGrid.Cells[0, i] := currMacroDesc[i].name;
form1.MDefNameGrid.Cells[1, i] := intToStr(currMacroDesc[i].startAddr);
form1.MDefNameGrid.Cells[2, i] := intToStr(currMacroDesc[i].endAddr);
end;
currStrNum := getCurrStrNum;
if (not inMacroCall) then
begin
form1.srcCodeMemo.SelStart := form1.srcCodeMemo.Perform(EM_LINEINDEX, currStrNum, 0);
form1.srcCodeMemo.SelLength := length(form1.srcCodeMemo.Lines[currStrNum]);
form1.srcCodeMemo.SetFocus;
end else
begin
selRect.Left := 0;
selRect.Right := 0;
selRect.Top := currStrNum;
selRect.Bottom := currStrNum;
form1.macroDefGrid.Selection := selRect;
end;
{
assignFile(outputFile, outputFileName);
rewrite(outputFile);
getCurrOutput(currOutput, numCurrOutputStr);
for i := 0 to numCurrOutputStr - 1 do
begin
writeln(outputFile, currOutput[i]);
end;
closeFile(outputFile); }
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i: byte;
begin
InputGrid.ColWidths[0] := 20;
for i := 1 to InputGrid.RowCount - 1 do
InputGrid.Cells[0, i] := IntToStr(i);
InputGrid.Cells[1, 0] :='MARK';
InputGrid.Cells[2, 0] :='MOPCODE';
InputGrid.Cells[3, 0] :='OPD1';
InputGrid.Cells[4, 0] :='OPD2';
OpCodeGrid.DefaultColWidth := OpCodeGrid.Width div 4 - 2;
OpCodeGrid.Cells[0, 0] := 'NAME';
OpCodeGrid.Cells[1, 0] := 'CODE';
OpCodeGrid.Cells[2, 0] := 'LEN';
OpCodeGrid.Cells[3, 0] := 'DIR';
TempGrid.ColWidths[0] := 20;
for i := 1 to TempGrid.RowCount - 1 do
TempGrid.Cells[0, i] := IntToStr(i);
TempGrid.Cells[1, 0] :='ADDR';
TempGrid.Cells[2, 0] :='OPCODE';
TempGrid.Cells[3, 0] :='OPD1';
TempGrid.Cells[4, 0] :='OPD2';
SymbNameGrid.DefaultColWidth := SymbNameGrid.Width div 2 - 2;
SymbNameGrid.Cells[0, 0] := 'NAME';
SymbNameGrid.Cells[1, 0] := 'ADDR';
for i := 0 to NumOps - 1 do
begin
OpCodeGrid.Cells[0, i + 1] := OpCodeTable[i].Name;
OpCodeGrid.Cells[1, i + 1] := OpCodeTable[i].Code;
OpCodeGrid.Cells[2, i + 1] := IntToStr(OpCodeTable[i].Len);
if (OpCodeTable[i].IsDir) then
OpCodeGrid.Cells[3, i + 1] := '1'
else
OpCodeGrid.Cells[3, i + 1] := '0';
end;
ErrMemo.Lines.Clear;
ErrMemo.Lines.Clear;
form1.macroDefGrid.ColWidths[0] := 20;
form1.macroDefGrid.ColWidths[1] := form1.macroDefGrid.Width - 25;
form1.marksGrid.DefaultColWidth := form1.marksGrid.Width div 2;
form1.localsGrid.DefaultColWidth := form1.localsGrid.Width div 2;
form1.MDefNameGrid.DefaultColWidth := form1.MDefNameGrid.Width div 3;
numSrcStr := loadSrcCode(inputFileName);
form1.srcCodeMemo.Clear;
for i := 0 to numSrcStr - 1 do
begin
form1.srcCodeMemo.Lines.Add(srcCode[i]);
end;
setSuspendable(form1.stepModeCheckbox.Checked);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SymbNameTree.Destroy;
end;
var
Index: byte;
procedure FillSymbNameTable(CurrNode: TPNode);
begin
if (CurrNode <> nil) then
begin
Form1.SymbNameGrid.Cells[0, Index + 1] := CurrNode.Key;
Form1.SymbNameGrid.Cells[1, Index + 1] := CurrNode.Inf;
inc(Index);
if (CurrNode^.Left <> nil) then
FillSymbNameTable(CurrNode^.Left);
if (CurrNode^.Right <> nil) then
FillSymbNameTable(CurrNode^.Right);
end;
end;
procedure TForm1.FirstParseButtonClick(Sender: TObject);
var
i: byte;
Header: string;
Error: TError;
begin
SymbNameTree.RemoveAll;
FirstParse(InputTable, TempTable, SymbNameTree, NumSymbNames, Error, NumLines, ProgLen, Header);
for i := 0 to MaxLines - 1 do
Output[i] := '';
Output[0] := Header;
ErrMemo.Lines.Clear;
ErrMemo.Lines.Clear;
if (Error.ErrType <> eNoErr) then
begin
ErrMemo.Lines.Add('Строка ' + IntToStr(Error.StrNum + 1) + ': ' + ErrText[Error.ErrType]);
SecondParseButton.Enabled := false;
end else
begin
ErrMemo.Lines[0] := 'Ошибок не найдено';
SecondParseButton.Enabled := true;
end;
for i := 1 to NumLines - 2 do
begin
TempGrid.Cells[1, i + 1] := TempTable[i].SymbName;
TempGrid.Cells[2, i + 1] := TempTable[i].MOpCode;
TempGrid.Cells[3, i + 1] := TempTable[i].Opd1;
TempGrid.Cells[4, i + 1] := TempTable[i].Opd2;
end;
Index := 0;
symbNameGrid.RowCount := 100;
FillSymbNameTable(SymbNameTree.GetRoot);
end;
procedure TForm1.SecondParseButtonClick(Sender: TObject);
var
i: byte;
Error: TError;
begin
SecondParse(TempTable, Output, Error, SymbNameTree, NumSymbNames, NumLines);
ErrMemo.Lines.Clear;
if (Error.ErrType <> eNoErr) then
ErrMemo.Lines.Add('Строка ' + IntToStr(error.StrNum + 1) + ': ' + ErrText[Error.ErrType])
else
ErrMemo.Lines[0] := 'Ошибок не найдено';
secondStepButton.Enabled := false;
firstParseButton.Enabled := false;
secondParseButton.Enabled := false;
OutputMemo.Lines.Clear;
for i := 0 to NumLines - 1 do
OutputMemo.Lines.Add(Output[i]);
Index := 0;
FillSymbNameTable(SymbNameTree.GetRoot);
outResultInFiles;
end;
procedure TForm1.InputGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
begin
case (ACol) of
1: InputTable[ARow - 1].SymbName := Value;
2: InputTable[ARow - 1].MOpCode := Value;
3: InputTable[ARow - 1].Opd1 := Value;
4: InputTable[ARow - 1].Opd2 := Value;
end;
end;
procedure TForm1.OpCodeGridSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
begin
case (ACol) of
0: OpCodeTable[ARow - 1].Name := Value;
1: OpCodeTable[ARow - 1].Code := Value;
2: OpCodeTable[ARow - 1].Len := StrToInt(Value);
3: if (Value = '1') then
OpCodeTable[ARow - 1].IsDir := true
else
OpCodeTable[ARow - 1].IsDir := false;
4: OpCodeTable[ARow - 1].Opd1 := StrToInt(Value);
5: OpCodeTable[ARow - 1].Opd2 := StrToInt(Value);
end;
end;
procedure TForm1.TempGridSetEditText(Sender: TObject; ACol, ARow: Integer;
const Value: String);
begin
case (ACol) of
1: TempTable[ARow - 1].SymbName := Value;
2: TempTable[ARow - 1].MOpCode := Value;
3: TempTable[ARow - 1].Opd1 := Value;
4: TempTable[ARow - 1].Opd2 := Value;
end;
end;
procedure TForm1.firstStepButtonClick(Sender: TObject);
var
result : TResult;
i : integer;
begin
clearOutputs;
secondStepButton.Enabled := false;
firstParseButton.Enabled := false;
secondParseButton.Enabled := false;
for i := 0 to srcCodeMemo.Lines.Count - 1 do
begin
srcCode[i] := srcCodeMemo.Lines.Strings[i];
end;
numSrcStr := srcCodeMemo.Lines.Count;
form1.stepButton.Enabled := true;
result := doFirstStep(srcCode, numSrcStr);
if (result.code = NORM_RESULT) then
secondStepButton.Enabled := true;
updateOutputs;
outErrors(result);
form1.stepButton.Enabled := false;
end;
procedure TForm1.secondStepButtonClick(Sender: TObject);
var
i, charPos: integer;
currLexem: string;
result: TResult;
numCurrOutputStr : integer;
currOutput : array [0..MAX_OUTPUT_LEN - 1] of string;
begin
form1.stepButton.Enabled := true;
result := doSecondStep(srcCode, numSrcStr);
if (result.code = NORM_RESULT) then
firstParseButton.Enabled := true
else
secondStepButton.Enabled := false;
updateOutputs;
outErrors(result);
form1.firstStepButton.Enabled := true;
form1.stepButton.Enabled := false;
getCurrOutput(currOutput, numCurrOutputStr);
numLines := numCurrOutputStr;
for i := 0 to numLines - 1 do
begin
InputTable[i].SymbName := '';
InputTable[i].MOpCode := '';
InputTable[i].Opd1 := '';
InputTable[i].Opd2 := '';
end;
for i := 0 to numLines - 1 do
begin
charPos := 1;
currLexem := getNextLexem(currOutput[i], charPos, COMMON_SEPARATOR);
if ((currLexem <> '') and (currLexem[1] = ASM_MARK_SYMBOL)) then
begin
InputTable[i].SymbName := currLexem;
InputTable[i].MOpCode := ansiUpperCase(getNextLexem(currOutput[i], charPos, COMMON_SEPARATOR));
end else
InputTable[i].MOpCode := ansiUpperCase(currLexem);
InputTable[i].Opd1 := getNextLexem(currOutput[i], charPos, COMMON_SEPARATOR);
InputTable[i].Opd2 := trim(getNextLexem(currOutput[i], charPos, ''));
InputGrid.Cells[1, i + 1] := InputTable[i].SymbName;
InputGrid.Cells[2, i + 1] := InputTable[i].MOpCode;
InputGrid.Cells[3, i + 1] := InputTable[i].Opd1;
InputGrid.Cells[4, i + 1] := InputTable[i].Opd2;
end;
if (numLines > 0) then
begin
InputGrid.RowCount := numLines + 1;
TempGrid.RowCount := numLines + 1;
for i := 1 to InputGrid.RowCount - 1 do
InputGrid.Cells[0, i] := IntToStr(i);
end;
for i := 1 to TempGrid.RowCount - 1 do
begin
TempGrid.Cells[0, i] := IntToStr(i);
TempGrid.Cells[1, i] := '';
TempGrid.Cells[2, i] := '';
TempGrid.Cells[3, i] := '';
TempGrid.Cells[4, i] := '';
end;
end;
procedure TForm1.stepButtonClick(Sender: TObject);
begin
resume;
updateOutputs;
end;
procedure TForm1.stepModeCheckBoxClick(Sender: TObject);
begin
setSuspendable(form1.stepModeCheckbox.Checked);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
breakProcess;
application.Terminate;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
breakProcess;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i: integer;
begin
if (openDialog1.Execute) then
begin
numSrcStr := loadSrcCode(openDialog1.FileName);
form1.srcCodeMemo.Clear;
for i := 0 to numSrcStr - 1 do
begin
form1.srcCodeMemo.Lines.Add(srcCode[i]);
end;
end;
end;
end.
