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

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

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 15.07.2009, 08:37   #1
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию Разбор программы на логические блоки в один проход

Вопрос заключается в следующем. У меня имеется набросок интерпретатора, который должен разбирать программу на следующие структуры - фрагменты (аналоги Begin-end Паскаля), циклы (несколько видов) и условия. Все почти аналогично Паскалю - за заголовоком цикла следует фрагмент, условие может быть как в короткой форме так и в длинной (то есть условие - блок истинной ветви - блок ложной ветви).
Перед стартом программа анализирует входящий поток программы (из компонента не важно Memo или RichEdit) и расталкивает код по фрагментам в отдельные структуры. Это у меня работает. Я настроил и работу с фрагментами и циклами (то есть вместо ссылки на фрагмент после цикла сразу следует ссылка на цикл, а в нем уже находится вся остальная информация). Но как осуществить работу с условием?
Интерпретатор имеет процедуры которые однозначно могут определить идентификатор строки (однозначно указывающий что это цикл такой-то, что это комментарий и пр.), а также извлечь все входящие параметры для данной строки (имена переменных, логические условия и пр.).
То есть для примера строка Если Х=100 То Х=1000 или Если х=100 ТОГДА х=1000 одназначно вернет идентификатор условия и заполнит специальную структуру параметрами Х=100 и Х=1000. Вместо такой короткой формы я могу автоматически создать ссылку на условие и коротку часть поместить в фрагмент Х=1000. Почти наверняка я смогу осуществить и прикрепленный фрагмент истинной ветви. Но как прикрепить фрагмент ложной ветви?
Общая схема такова
Условный оператор (его обозначение не имеет значение, поскольку его можно изменить в любое время)
Фрагмент
Бла-бла
Конец фрагмента
Иначе
Фрагмент
Бла-Бла
Конец фрагмента

Все операторы условны их наименования и порядок следования параметров в них можно легко изменить.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 15.07.2009, 09:07   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Но как прикрепить фрагмент ложной ветви?
Ну так же точно как ты прикрепил ТОГДА...
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.07.2009, 09:12   #3
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Тогда задается в одной строке с условием, ложная ветвь по аналогии с Else (ИНАЧЕ) всегда должна находиться на новой строке. Вообще синтаксис требует от программиста ВСЕГДА разносить на фрагменты условие если для него предусмотрена ложная ветвь.
Например, такая конструкция будет неверна - Если х=10 то х=100 Иначе х=1000
Цель таких заморочек заставить программиста писать "понятные" для других программы (а не только для него в текущий момент времени), короче выдрессировать его к определенному стилю.
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 15.07.2009, 09:43   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Ну тогда полюбому следующая строка после Если х=10
Будет BEGIN
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.07.2009, 09:54   #5
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Код:
// Получение структуры программы
procedure TValentina.Scaning           (Source: TStrings; var Errs: TStringList);
var
Dlina, i, Id, num, x, Tip: Integer;
Stroka, Stroka2, buf, StrCyc, Uslov: String;
F: TStringList;                   // Стек вложенных фрагментов
begin
// Подготовим отчет
Errs.Clear;
F:=TStringList.Create;
f.Add('-1');
Tip:=0;
num:=0;
// Определим число строк в списке
Dlina:=Source.Count-1;
// В списке есть строки?
If Dlina<0 then Exit;
// Сканируем на максимально возможном варианте
for i:=0 to Dlina do
begin
// Получим строку
Stroka:=Source.Strings[i];
// Обработаем строку
Stroka2:=CutNLex(Normalize(Stroka));
Stroka:=AnsiUpperCase(Stroka2);
// Получим ID строки
Id:=GetIdStroka(Stroka);
// Перед нами начало фрагмента?
if Id=3 then
begin
// Этот фрагмент принадлежит еще кому-нибудь?
if Tip=0 then
begin
// Добавляем ссылку на фрагмент
AddTxtFrag(Prog.Kod, IntToStr(num), '+ фрагмент '+IntToStr(Prog.Kod.Count));
end
Else
begin
// Надеемся на ИНАЧЕ
If Tip=5 then Tip=4;
end;
// Генерируем новое имя
num:=Prog.Kod.Count;
// Создаем новый фрагмент
buf:=IntToStr(num);
AddFrag(Prog.Kod, buf);
// Записываем его в счетчик фрагментов
F.Add(buf);     
end;
// Завершение фрагмента
if Id=4 then
begin
// Удаляем данные о фрагменте из стека
x:=F.Count-1;
// Контроль границ списка
if x<0 then
begin
// Готовим сообщение об ошибке
Errs.Add('Строка '+IntToStr(i)+' : '+Source.Strings[i]);
Errs.Add('Обнаружена лишняя нижняя граница фрагмента');
Exit;
end;
F.Delete(x);
// Данный фрагмент будет текущим
x:=F.Count-1;
// Контроль границ списа
if x<0 then
begin
// Готовим сообщение об ошибке
Errs.Add('Строка '+IntToStr(i)+' : '+Source.Strings[i]);
Errs.Add('Обнаружена лишняя нижняя граница фрагмента');                      Exit;
                  end;
                  num:=StrToInt(F.Strings[x]);
             end;
             // Если перед нами цикл
             if (Id>4) and (Id<9) then
             begin

                  // Создаем цикл
                  // Готовим строку с параметрами
                  If id=5 then StrCyc:='4';
                  if id=6 then StrCyc:='1';
                  if id=7 then StrCyc:='3';
                  if id=8 then StrCyc:='0';
                  // Получим параметры цикла
                  GetParams(Stroka);
                  // Строка с параметрами
                  Inc(num);                  StrCyc:=IntToStr(num)+#9+ParamConstr.Param[1]+#9+ParamConstr.Param[2]+#9+ParamConstr.Param[3]+#9+ParamConstr.Param[4]+#9+StrCyc+#9+IntToStr(num);

                  // Создаем новый цикл
                  AddCyclStr (Prog.Kod.CyclCol, StrCyc);
                  // Добавим ссылку на цикл
                  AddTxtFrag(Prog.Kod, IntToStr(num-1), '+ цикл '+IntToStr(num));
                  // Признак что перед нами цикл
                  Tip:=1;
             end;
             // Если перед нами условный блок
             if id=9 then
             begin
                // Мы еще в цикле?
                if Tip=1 then
                begin
                    // Добавим сообщение об ошибке
                    Errs.Add('Строка '+IntToStr(i)+' : '+Source.Strings[i]);
                    Errs.Add('За заголовком цикла встретилось условие');
                end;
                // Получим параметры условия
                GetParams(Stroka);
                // Готовим строку с параметрами
                Inc(num);                Uslov:=IntToStr(num)+#9+ParamConstr.Param[1]+#9+IntToStr(num)+#9+IntToStr(num+1);
                // Создаем новое условие
                AddUslStr(Prog.Kod.UslCol, Uslov);                
                // Добавим ссылку на условие
                AddTxtFrag(Prog.Kod, IntToStr(num-1), '+ условие '+IntToStr(num));
                // Признак что перед нами цикл
                Tip:=5;
             end;
             // Добавление содержимого строки
             if (id<3) or (id>8) then
             begin
                // Дополнительный анализ для цикла
                if (Tip=1) and (Stroka2<>'') then
                begin
                    // Добавим сообщение об ошибке
                    Errs.Add('Строка '+IntToStr(i)+' : '+Source.Strings[i]);
                    Errs.Add('За заголовком цикла допускается использование пустых строк и тела фрагмента');
                end
                Else
                begin
                    AddTxtFrag(Prog.Kod, IntToStr(num), Stroka2);
                end;
             end;
        end;
        // Освобождаем память
        F.Free;
end;
Вот код.

Код должен допускать сразу после если либо начало нового фрагмента либо пустые строки. Условия проверяются в строке if id=9 then (код не рабочий). Какие будут предложения? Id для иначе = 54
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика

Последний раз редактировалось Stilet; 15.07.2009 в 10:09.
Utkin вне форума Ответить с цитированием
Старый 15.07.2009, 10:25   #6
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Тест:
Фрагмент
Содержимое пустого фрагмента
конец фрагмента

Фрагмент

Цикл: х от 10 до 1000+12
Фрагмент
Сало маслом не испортишь
Конец фрагмента

конец фрагмента

Фрагмент
Если х=10 тогда
фрагмент
Условие истинной ветви
конец фрагмента
конец фрагмента

Результаты теста:
0
1
2
3
4

Содержимое фрагментов

Содержимое фрагмента: 0
Информация о фрагменте 0
=================================== ==========================
Содержимое пустого фрагмента
=================================== ==========================
=================================== =================

Содержимое фрагмента: 1
Информация о фрагменте 1
=================================== ==========================

+ цикл 2

=================================== ==========================
=================================== =================

Содержимое фрагмента: 2
Информация о фрагменте 2
=================================== ==========================
Сало маслом не испортишь
=================================== ==========================
=================================== =================

Содержимое фрагмента: 3
Информация о фрагменте 3
=================================== ==========================
+ условие 4
=================================== ==========================
=================================== =================

Содержимое фрагмента: 4
Информация о фрагменте 4
=================================== ==========================
Условие истинной ветви
=================================== ==========================
=================================== =================


Список циклов:
2

Содержимое циклов

Содержимое цикла: 2
Параметры цикла
Х
10
1000 + 12

Тело: 2
Тип цикла: 4
=================================== =================


Список условий:
4

Содержимое условий

Содержимое условия: 4
Условие: Х = 10
Истинная ветвь: 4
Ложная ветвь: 5
=================================== =================
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 15.07.2009, 10:40   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Давай так, я покажу как я понимаю проблему и ее решение, а ты потом в меня помидорами покидаешся
Попробуй на вкус пример.
Вложения
Тип файла: rar компиляторы - Парсер.rar (2.3 Кб, 16 просмотров)
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.07.2009, 13:54   #8
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

Помидорами не буду . Мельком глянул, сейчас буду расковыривать, позже обязательно отчитаюсь о результатах .
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Старый 15.07.2009, 14:17   #9
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
позже обязательно отчитаюсь о результатах
Давай, может оптимизируешь. Там я навскидку чисто идею выдал, так что пара багов будут, но смысл остается тот же - брать текст от ключевого слова до завершающего ключевого слова.

И это только для IF такое, но можно и под FOR подстроить.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.07.2009, 14:21   #10
Utkin
Старожил
 
Аватар для Utkin
 
Регистрация: 04.02.2009
Сообщений: 17,351
По умолчанию

С циклами проблем нет .
В общем-то уперся в ту же проблему. Ложная ветвь в условии может быть, а может и не быть. Как это отследить? И отсюда встает проблема ошибок, в твоем примере я пишу els вместо else и все равно получаю параметры, а это не есть хорошо.
Хорошо два условия следуют подряд - первое без ложной ветви, второе с ложной ветвью. Твой алгоритм найдет результат некорректно .
Маньяк-самоучка
Utkin появился в результате деления на нуль.
Осторожно! Альтернативная логика
Utkin вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Разбор кода программы на Bison+Flex Corol Помощь студентам 2 03.07.2009 09:57
Разбиение текста на блоки. gosu Общие вопросы C/C++ 11 04.06.2009 19:12
Как имея один exe файл получить исходник программы? Skoroxod Общие вопросы Delphi 4 20.02.2009 10:41
один файл, две программы... Deathwatcher Общие вопросы Delphi 0 18.11.2008 12:39
Сортирование масивов за один проход NightWishMaster Паскаль, Turbo Pascal, PascalABC.NET 10 18.10.2007 08:05