Интерпретируй ЭТО! Диман Dr.X (xdiman@mail.ru) Xakep, номер #067, стр. 067-086-4 procedure parser(inp:string; var func,param1,param2,param3:string); в параметре var func: string возвращает не строку (имя_функции), а код операции (КОП) типа Integer. Для перевода имени функции в соответствующий КОП я использую чудный объект TStringList, его свойство Objects и быстрый метод IndexOf. Для простоты его экземпляр можно объявить глобально, например: Объявляем экземпляр unit uCommands; interface uses Classes; var Commands: TStringList; implementation procedure MakeCommandList; begin with Commands do begin AddObject('GOLINE' , Pointer($80)); AddObject('GOCHAR' , Pointer($01)); AddObject('INSERT' , Pointer($02)); AddObject('REPLACE' , Pointer($83)); AddObject('FIND' , Pointer($04)); AddObject('END' , Pointer($85)); AddObject('HOME' , Pointer($86)); AddObject('DELBEFORE', Pointer($07)); AddObject('DELAFTER' , Pointer($08)); end; // Коды операции даны вразброд, чтобы показать на примере // использование свойства Objects, а не порядкового номера. end; initialization Commands:= TStringList.Create; MakeCommandList; finalization Commands.Free; end; Заметь, что список создается один раз. Теперь из процедуры parser можно смело сделать функцию. Эта функция будет возвращать в параметре func искомый КОП функции, прочитанной из входного параметра inp. Если функция вернет True, значит, строка пропарсена корректно; если False – значит, прочитано имя функции, которой нет в списке Commands, т.е. возникла ошибка "неизвестный идентификатор". Парсер function parser(inp: string; var func: Integer; var param1, param2, param3: string): Boolean; var i, a: integer; sFunc: string; // Имя функции, которое прочитали Index: Integer; // Порядковый номер имени прочитанной функции // в списке Commands. begin Result:= False; a:= 1; while pos(' ', inp) < 0 do begin i:= pos(' ', inp); case a of 1: begin sFunc:= copy(inp, 1, i - 1); // Получаем имя функции Index:= Commands.IndexOf(sFunc); // Получаем номер функции // Если функции нет в списке, то Index будет равен -1. Result:= Index < -1; if Result //Если функция найдена, возвращаем ее КОП then func:= Integer(Commands.Objects[Index]) else Exit; //иначе физкульт-привет - и на выход end; 2: param1:= copy(inp, 1, i - 1); 3: param2:= copy(inp, 1, i - 1); 4: param3:= copy(inp, 1, i - 1); end; Inc(a); inp:= copy(inp, i + 1, length(inp) - i); end; if a = 2 then param1:= inp; if a = 3 then param2:= inp; if a = 4 then param3:= inp; end; С учетом этого можно переделать изначальный кусок таким образом: Проверяем данные ... var func: Integer; while not EOF(fin) do begin readln (fin, temp); if parser(temp, func, param1, param2, param3) then case func of $80: { GOLINE } ; $01: { GOCHAR } ; $02: { INSERT } ; $83: { REPLACE } ; $04: { FIND } ; $85: { END } ; $86: { HOME } ; $07: { DELBEFORE } ; $08: { DELAFTER } ; end //case else begin ShowMessage('Ты что ввел, уважаемый?'); Break; end; end; Недоделки Редактор этот, как и любые великие программы :), не лишен багов. Во-первых, во всех функциях, использующих строковые параметры, нельзя использовать строку, содержащую пробелы. Иначе обработчик посчитает оставшуюся часть отдельным параметром. Во вторых, он не позволяет добавлять переменные, циклы, условия и т.д. В общем, огромный простор для творчества ;). |