Delphi - сбориник статей

История


Занимаясь разработкой трансляторов на Delphi, рано или поздно сталкиваешься с пакетом TP Lex and Yacc (автор Albert Graef). Пакет этот максимально повторяет оригинальные Lex и Yacc, генерирующие код на языке C. Этот факт при переходе на язык Pascal порождает ряд проблем, а точнее неудобств, которые связаны с различиями в трансляции и структуре языков C и Pascal. Оригинальный Yacc, равно как и TP Yacc, генерируют выходной файл, содержащий функцию yyparse. Тоже самое делает и Lex. И если в языке C полученный файл является самодостаточной синтаксической единицей, то в Pascal этот файл еще надо как-то "прикрутить" к проекту. Вариантов сделать это не так много. В Pascal объявление функции должно находиться в том же синтаксическом модуле, что и ее реализация, поэтому сгенерированный файл либо сам должен быть модулем, либо должен включаться в уже заготовленный модуль директивой {$I }.

В первом случае .y файл выглядит примерно так:

%{
 unit <имя файла>;
 interface
 uses
   <список модулей>;
 function yyparse: Integer;
 implementation
 %}
   <Определения>
 %%
   <Продукции>


 %%
 end.

Во втором случае надо уже два (как минимум) файла:

файл модуля <parser.pas>

 unit <имя файла>;
 interface
 uses
   <список модулей>;
 function yyparse: Integer;
 implementation
 {$I <parser_y.pas>}
 end.

и файл parser_y.y (этот файл нельзя называть parser.y, что было бы вполне логичным, из-за конфликта имен).

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

В первом случае имеет место заметное замусоривание исходного файла анализатора, которое увеличивает сложность и без того непростого модуля транслятора. Во втором случае сильно усложняется отладка и сопровождение проекта (за счет увеличения количества файлов). В Pascal не очень приветствуются включаемые файлы - механизм их использования и отладки довольно слабый.



Содержание раздела