Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.03.2014, 17:27   #1
ink_envy
Новичок
Джуниор
 
Регистрация: 15.03.2014
Сообщений: 2
По умолчанию Pascal, форматирование программ.

Задача - написать простейший форматтер программ на паскале, вот то что есть, вроде со всем разобрался, но есть небольшие проблемы, если присутствует, допустим, полный блок if внутри блока for, отступы неверно расставляются. И не понимаю как сделать отступы после "незакрывающихся" ключевых слов типа var, const, что бы потом всё заново начиналось с 1 бегина. Помогите, пожалуйста. 1 - сам код программы, 2 - результат выполнения на одной из программ.

Код:
const
 s_name = 'input.pas';
 d_name = 'output.pas';
 
 StartersCount = 4;
 Starters: array[1 .. StartersCount] of string =
   ('do', 'repeat', 'begin', 'case');
 
 EndersCount = 2;
 Enders: array[1 .. EndersCount] of string =
   ('end', 'until');
 
 SpecialCount = 3;
 Special:array[1 .. SpecialCount] of string = 
   ('if', 'var', 'const');

var
  fin, fout: text;
  mark:string;
  str:string;
  i:integer;
  Tab, forTab:integer;
  
  
function AddSpace(str:string; spaces:integer):string; {Добавляем нужно количество пробелов к строке}
var i:integer;
begin
 result:=str;
 if spaces < 1 then exit;
 for i:=1 to spaces do
 result:= ' ' + result;
end;

function FirstWord(str:string):string;
begin
  result:=copy(str, 1, pos(' ', str));
end;

function findMark(str:string):byte;  {Проверяем строку на наличие ключевых}
var i:integer;
begin
 result:=0;
 for i:=1 to SpecialCount do
   if pos(Special[i],str) <> 0 then result:= 3;
 for i:=1 to StartersCount do
   if pos(Starters[i],str) <> 0 then result:= 1;
 for i:=1 to EndersCount do
   if pos(Enders[i],str) <> 0 then result:= 2;
end;


begin
 Tab:= 0;
 if not fileexists(s_name) then
   begin
     writeln( 'Cannot open source file ', s_name );
     halt(100);
   end;
 assign(fin, s_name);
 reset(fin);

 assign(fout, d_name);
 rewrite(fout);
 if not fileexists(d_name) then
   begin
     writeln( 'Cannot create destination file ', d_name );
     halt(101)
   end;
   
 while not seekeof(fin) do
  begin
    readln(fin, str);
    trim(str);
    
    if findMark(str) = 2 then dec(Tab, 2);
    str:= AddSpace(str, Tab);
    writeln(fout,str);
    if findMark(str) = 1 then inc(Tab, 2);
    
    
    
  if Tab < 0 then Tab:=0; 
  end;
 closefile(fin);
 closefile(fout);
end.

Код:
program kod;
const
ms: array[1..8] of string = ('/e', '/p', '/w', '!w', '/r', '/f', '/v', '/b');
ms1: array[1..8] of string = ('end', 'program', 'writeln', 'while', 'readln', 'for', 'var', 'begin');
var
f: text;
s, s1: string;
i, k: integer;
begin
  assign(f, 'KOD.txt');
  reset(f);
  while not eof(f) do 
    begin
      readln(f, s);
      for i := 1 to 8 do 
        if pos(ms[i], s) > 0 then 
        begin
          k := pos(ms[i], s);
          delete(s, k, 2);
          insert(ms1[i], s, k);
        end;
        writeln(s);
      end;
      close(f);
    end.
ink_envy вне форума Ответить с цитированием
Старый 15.03.2014, 23:54   #2
ink_envy
Новичок
Джуниор
 
Регистрация: 15.03.2014
Сообщений: 2
По умолчанию

ну хотя бы на мысль натолкните
ink_envy вне форума Ответить с цитированием
Старый 16.03.2014, 01:31   #3
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

Слишком у тебя просто) Слишком мало возможных вариантов.

При чтении строки нужно определять, что если она является комментарием, то писать ее без изменений и исключать из логики обработки, как будто ее вовсе нету.

Первым делом прочитать весь файл и за каждым begin поставить перенос строки (если его нету). Перед каждым end - тоже (если его нету). Естессно, с тестом на закоменченность, begin и end же вполне себе такие литературные английские слова.

Например, если строка содержит do и заканчивается двоеточием, то увеличивать последующий отступ не надо, иначе - если следующая за do строка пустая, то делаем ничего и ищем строку, которая с символами (но не комментарий!), если найденная строка содержит begin, то увеличиваем отступ и выходим из этой кучи ифов, иначе если найденная строка начинается с ключевых слов, то пихаем в стек состояние - "идет обработка do" и начинаем обработку в соответствии с найденным ключ.словом, иначе входим в цикл: если строка первая - увеличиваем отступ, далее пишем найденную строку, а если найденная строка заканчивается точкасзапятой, то уменьшаем отступ и выходим из цикла... Предположим, тут закончилась обработка случая с do - тогда вытаскиваем из стека предыдущее состояние и продолжаем обработку в соответствии с этим состоянием...

если встретилось одно из спец.ключ.слов (const, var), то делать все следующие строки с отступом до тех пор, пока не встретилась строка, начинающаяся с любого ключ слов (включая procedure и function) - тогда уменьшать отступ.

Кароч, темный сумерек)

Последний раз редактировалось Smogg; 16.03.2014 в 01:36.
Smogg вне форума Ответить с цитированием
Старый 16.03.2014, 02:34   #4
Smogg
Участник клуба
 
Регистрация: 14.06.2011
Сообщений: 1,138
По умолчанию

А если покороче - то тебе надо ввести "состояние программы". Пусть будут два - нормальное, обработка constvar (желательно еще и третье - многострочный коммент, но с ним достаточно хитро и без стека не обойтись).

тогда логика будет такая:
цикл вайл нот(еоф)
если строка пустая - пишем без изменений и continue;
если строка - однострочный коммент, то пишем без изменений и continue;
если строка начинается с var|const, то делаем отступ = 0, ставим состояние "constvar", сохраняем строку, увеличиваем отступ и continue;
если строка начинается с ваще любого ключ.слова и программа в состоянии "constvar", то уменьшаем отступ, ставим состояние "нормально" и продолжаем обработку;
если строка содержит do и оканчивается на точкасзапятой, то сохраняем и continue; иначе просто сохраняем и проверяем сразу же след строку - если a) след строка начинается с begin, то сохраняем begin, потом увеличиваем отступ и continue; b) оканчивается на точкасзапятой то сначала увеличиваем отступ, затем сохраняем, уменьшаем отступ и continue;

ну и дальше - как у тебя

Последний раз редактировалось Smogg; 16.03.2014 в 20:40.
Smogg вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание программ на PASCAL домашняя контрольная*( BBC25 Помощь студентам 3 27.01.2011 23:20
Форматирование Pascal-кода в Word InternetStranger Общие вопросы Delphi 4 20.05.2010 01:21