В данном разделе будут рассмотрены исходные тексты, лежащие в каталоге src
дистрибутива Рефала-05.
Компилятор построен как набор повторно используемых компонент: синтаксического дерева, лексического и синтаксического анализаторов, генератора кода и набора утилитарных функций. Эти компоненты можно использовать как библиотеки при написании других инструментальных средств для работы с Рефалом-05. Мотивация такого подхода описана в первом разделе.
Все компоненты, рассматриваемые здесь, написаны на общем подмножестве Рефала-05
и Рефала-5, а это значит, что их можно использовать и при программировании
на Рефале-5 тоже. Более того, если для раскрутки компилятора использовался
Рефал-5, то скомпилированные .rsl-ки рассматриваемых библиотек лежат в папке
bin, а это значит, что её можно добавить в переменную REF5RSL. Об этом
говорилось в разделе установки, но повторить лишним
не будет.
Интерфейс рассматриваемых библиотек может меняться в будущих версиях, что не всегда будет вовремя отражаться в документации. Поэтому сверяйтесь с комментариями в исходных текстах.
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),
вторая возвращает сгенерированный текст как последовательность строк.
R05-ParserВ этом компоненте три похожие функции:
<R05-Parse-File e.SourceFile>
== Success e.R05-AST
== Fails e.Errors
(использует LoadFile → файл № 39)
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, в частности, добавляет узлы Extern для используемых встроенных
функций, пустые локальные функции для используемых имён и выполняет
дополнительные семантические проверки.
refal05cФормально он не предназначен для повторного использования, как остальные
компоненты — он содержит функцию $ENTRY GO и связывает рассмотренные выше
библиотеки в единое целое.
Но, при желании, его можно использовать как компонент, подменив зависимые
компоненты на альтернативные компоненты с тем же интерфейсом. Например,
если реализовать в собственном коде функцию R05-Generate-ToFile, то можно
собрать компилятор с альтернативным кодогенератором.
Однако, этот способ использования не поддерживается и не рекомендуется.