This topic has missing or partial documentation. Please help us improve it.
Первая стадия конвейера байткод-компиляции — Ruby-парсер. Парсер получает
файл или String с исходником и передает следующей стадии, генератору,
полученное AST (Abstract Syntax Tree, дерево абстрактного синтаксиса).
Сам парсер (он называется «Melbourne»), состоит из C-части, которая представляет собой, в сущности, парсер MRI, и Ruby-части, которая отвечает за создание Ruby-AST. C-часть общается с Ruby, вызывая специфический метод для каждого узла дерева.
Каждый из таких методов имеет сигнатуру, содержащую всю информацию о текущем
обрабатываемом участке дерева. Например, если в Ruby-коде есть выражение if,
C-парсер вызовет process_if с номером строки, параметром, представляющим
условие, параметрами, представляющими тело if-выражения и секции else,
если таковая присутствует.
def process_if(line, cond, body, else_body)
AST::If.new line, cond, body, else_body
end
Все возможные методы process_ можно посмотреть в исходниках Rubinius в файле
lib/melbourne/processor.rb.
Обратите внимание: во многих случаях парсер передает результат выполнения
одного process_ как аргумент следующему. Например, в случае выражения true
if 1 парсер сперва вызывает process_lit(line 1), а затем
process_true(line). Также вызывается process_nil(line), потому что
парс-дерево изначально содержит nil для представления тела подвыражения
else. После этого вызывается process_if с номером строки и результатами
process_lit, process_true и process_nil.
Описанный процесс рекурсивно строит древовидную структуру, которую Rubinius впоследствии передаст следующей стадии, Генератору.
lib/melbourne/processor.rb: Ruby-интерфейс к C-парсеру. В этом файле
содержатся методы, начинающиеся с process_, которые и вызываются
C-парсером для каждого узла парс-дерева.lib/compiler/ast/*: определения каждого из типов узлов AST, используемых в
melbourne.Существует два способа настройки для этой стадии компиляции. Самый простой — это настройка создания AST через преобразования AST
Еще можно создать субкласс класса Melbourne и определить собственные
обработчики методов process_. Этот способ относится к «продвинутым» и к
настоящему времени не документирован.