Рефал-05

Библиотека компонентов компилятора

В данном разделе будут рассмотрены исходные тексты, лежащие в каталоге src дистрибутива Рефала-05.

Компилятор построен как набор повторно используемых компонент: синтаксического дерева, лексического и синтаксического анализаторов, генератора кода и набора утилитарных функций. Эти компоненты можно использовать как библиотеки при написании других инструментальных средств для работы с Рефалом-05. Мотивация такого подхода описана в первом разделе.

Все компоненты, рассматриваемые здесь, написаны на общем подмножестве Рефала-05 и Рефала-5, а это значит, что их можно использовать и при программировании на Рефале-5 тоже. Более того, если для раскрутки компилятора использовался Рефал-5, то скомпилированные .rsl-ки рассматриваемых библиотек лежат в папке bin, а это значит, что её можно добавить в переменную REF5RSL. Об этом говорилось в разделе установки, но повторить лишним не будет.

Интерфейс рассматриваемых библиотек может меняться в будущих версиях, что не всегда будет вовремя отражаться в документации. Поэтому сверяйтесь с комментариями в исходных текстах.

Фреймворк для построения компилятора Рефала-05 — компонент R05-CompilerUtils

Компонент зависит от LibraryEx.

Данный компонент содержит несколько функций, упрощающих написание инструментальных средств, совместимых по поведению с Рефалом-05.

Функция R05-LoadPath

<R05-LoadPath> == e.Folders

e.Folders ::= (e.Folder)*
e.Folder ::= s.CHAR+

Функция возвращает пути поиска, заданные в переменных окружения R05PATH и REF5RSL.

Функции R05-FindFiles-Default и R05-FindFiles

<R05-FindFiles-Default e.Files> == t.FoundFile*
<R05-FindFiles (e.Folders) e.Files> == t.FoundFile*

e.Files ::= (e.FileName)*

t.FoundFile ::=
    (Source (e.Source) e.Output)
  | (Output e.Output)
  | (NotFound e.FileName)

e.Source, e.Output, e.FileName ::= s.CHAR+

Функции производят поиск указанных файлов в каталогах поиска. Первая функция R05-FindFiles-Default осуществляет поиск в каталогах по умолчанию, возвращаемых функцией R05-LoadPath. Вторая функция осуществляет поиск в каталогах, указанных пользователем.

Функция R05-CCompile

<R05-CCompile e.CSources> == e.RetCode

e.CSources ::= (s.CHAR* '.c')*
e.RetCode ::= '-'? s.NUMBER

Выполняет компиляцию исходных текстов на Си компилятором, заданным в переменной окружения R05CCOMP, с флагами, заданными в R05CFLAGS. Функция автоматически добавляет к командной строке компилятора каталоги, возвращаемые функцией R05-LoadPath как каталоги поиска заголовочных файлов (используется опция -Iкаталог).

Если переменная R05CCOMP установлена и непустая, то возвращаемое значение функции совпадает с возвращаемым значением функции System, при помощи которой активируется командная строка.

Если переменная R05CCOMP не установлена или пустая, то возвращаемое значение всегда 0.

Компиляция синтаксического дерева в код на Си — компонент R05-Generator

В этом компоненте всего две похожие функции

<R05-Generate-ToFile (e.OutputFile) e.Tree> == пусто
(использует SaveFile → файл № 39)

<R05-Generate-ToLines e.Tree> == (s.CHAR*)*

Обе функции принимают синтаксическое дерево и формируют код на Си. Первая функция записывает исходный текст в файл (используя SaveFile, т.е. файл № 39), вторая возвращает сгенерированный текст как последовательность строк.

Синтаксический анализ Рефала-05 — компонент R05-Parser

В этом компоненте три похожие функции:

<R05-Parse-File e.SourceFile>
  == Success e.Tree
  == Fails e.Errors

e.Errors ::= ((s.Row s.Col) e.Message)*

Функция выполняет синтаксический анализ указанного источника, и, если не было синтаксических ошибок, возвращает дерево, в противном случае возвращает список ошибок.

<R05-PrepareAST e.Refal5-AST>
  == Success e.R05-AST
  == Fails e.Errors

Функция преобразует e.Refal5-AST (определено в refal-5-framework/R5FW-Parser-Defs.md) в синтаксическое дерево Рефала-05, в частности, раскрывает псевдокомментарии *$ENUM, *$EENUM и *$EXTERN и выполняет дополнительные семантические проверки.

Главный файл компилятора — компонент refal05c

Формально он не предназначен для повторного использования, как остальные компоненты — он содержит функцию $ENTRY Go и связывает рассмотренные выше библиотеки в единое целое.

Но, при желании, его можно использовать как компонент, подменив зависимые компоненты на альтернативные компоненты с тем же интерфейсом. Например, если реализовать в собственном коде функцию R05-Generate-ToFile, то можно собрать компилятор с альтернативным кодогенератором.

Однако, этот способ использования не поддерживается и не рекомендуется.