Создание нового языка программирования - с чего начать: различия между версиями

Материал из Вики проекта PascalABC.NET
Перейти к навигацииПерейти к поиску
Строка 64: Строка 64:
Как и в Yacc, в правилах доступны $$ (левая часть правила), $1 - первый параметр и т.д.
Как и в Yacc, в правилах доступны $$ (левая часть правила), $1 - первый параметр и т.д.


====Как генерируется парсер====
===Как генерируется парсер===
Вначале мы подаем файл .grm программе Gold Parser Builder или ее консольной версии. Если ошибок нет, то генерируется файл .cgt - это откомпилированный файл грамматики. Он не содержит правил.
 
Затем по файлу .cgt и файлу .pgt с помощью программы createskelprog_main.exe генерируется '''каркас парсера''' на конкретном языке (в нашем случае - на C#).
 
 
 
Для каждого языка может быть несколько движков парсера. Для PascalABC.NET выбран движок Morozov C# Engine со страницы [http://www.devincook.com/goldparser/engine/c-sharp/index.htm]. Для генерации каркаса парсера движок парсера использует откомпилированный файл грамматики .cgt и так называемый '''скелет парсера''', хранящийся в файле .pgt. '''Скелет парсера''' - это заготовка, из которой получается каркас парсера - текст программы на целевом языке. К скелету добавляется часть, связанная с конкретными правилами грамматики, при этом каждому правилу грамматики соответствует отдельный метод.
 
К сожалению, все генерируемые методы - пустые. Их и надо заполнить действиями по генерации синтаксического дерева программы. При изменении грамматики такой подход чрезвычайно неудобен, именно поэтому Ткачук создал программу, которая по файлу грамматики и по получаемому '''каркасу парсера''' на C# вписывает в этот каркас правила, содержащиеся в комментариях в .grm файле в виде !* *! Это делает
 
Для автоматического /


===Основные узлы синтаксического дерева===
===Основные узлы синтаксического дерева===

Версия от 20:03, 1 мая 2010

Мы будем создавать парсер языка - программу, переводящую текст программы на языке программирования, в так называемое синтаксическое дерево. По-существу, парсер является первой частью компилятьра, его front-endом.

Папка с грамматикой

В папке с грамматикой - 2 файла - .grm и .pgt. .grm содержит файл с грамматикой в формате Gold Parser Builder, дополненный шаблонами действий (действия - в стиле Yacc). Шаблоны действий хранятся в виде комментариев Gold Parser Builder, так что на компиляцию им грамматики не влияют.

.pgt - это шаблон для создания скелета парсера, имеется для различных языков, мы используем для C#. Это означает, что сами парсеры

Все остальные файлы, если они есть, - можно убить - они генерируются автоматически.

По .grm файлу Gold Parser Builder автоматически создает .cgt файл - это файл откомпилированной грамматики - пока без правил. Они будут учтены позже.

Шаблоны в .grm файле

Шаблоны создавались Ткачуком для облегчения автоматической генерации кода. Рассмотрим пример:

!<%NAME%> %CODE%
!*
[TERMINALTEMPLATE]
		{
			%NAME% _%NAME%=new %NAME%(%PARAMS%);
			_%NAME%.source_context=parsertools.GetTokenSourceContext();
			%CODE%
			return _%NAME%;
		}
*!

и связанный с ним код правила для простого токена (терминального символа):

tkIf 			= 'if'                          !*<token_info>*!

Здесь - первая строка

!<%NAME%> %CODE%

задает вид правой части: <token_info>. В данном случае %NAME%=token_info, %CODE% - пустой

Все терминальные символы подвергаются действию этого шаблона. В результате в данном случае <token_info> переходит в

token_info _token_info=new token_info(%PARAMS%);
_token_info.source_context=parsertools.GetTokenSourceContext();
// пусто
return _token_info;

%PARAMS% - это параметр в круглых скобках в <> в правилах. Поскольку правило имеет вид <token_info> и не содержит круглых скобок, то здесь здесь %PARAMS% - пустой.

source_context - это объект класса SourceСontext, хранящий строку и столбец начала и конца узла в синтаксическом дереве.

Шаблон для нетерминала

Рассмотрим нетерминал:

<if_then_else_branch>
        ::= tkThen <then_branch>        !*3if_node<null,(statement)$2,null>
								parsertools.create_source_context($$,$1,parsertools.sc_not_null($2,$1));

Цифра 3 говорит о том, что используется шаблон нетерминала №3:

!*
[NONTERMINALTEMPLATE3]         
		{
			%NAME% _%NAME%=new %NAME%(%PARAMS%);
			%CODE%
			return _%NAME%;
		}
*!

Если цифра не присутствует, то шаблон не применяется.

Как и в Yacc, в правилах доступны $$ (левая часть правила), $1 - первый параметр и т.д.

Как генерируется парсер

Вначале мы подаем файл .grm программе Gold Parser Builder или ее консольной версии. Если ошибок нет, то генерируется файл .cgt - это откомпилированный файл грамматики. Он не содержит правил.

Затем по файлу .cgt и файлу .pgt с помощью программы createskelprog_main.exe генерируется каркас парсера на конкретном языке (в нашем случае - на C#).


Для каждого языка может быть несколько движков парсера. Для PascalABC.NET выбран движок Morozov C# Engine со страницы [1]. Для генерации каркаса парсера движок парсера использует откомпилированный файл грамматики .cgt и так называемый скелет парсера, хранящийся в файле .pgt. Скелет парсера - это заготовка, из которой получается каркас парсера - текст программы на целевом языке. К скелету добавляется часть, связанная с конкретными правилами грамматики, при этом каждому правилу грамматики соответствует отдельный метод.

К сожалению, все генерируемые методы - пустые. Их и надо заполнить действиями по генерации синтаксического дерева программы. При изменении грамматики такой подход чрезвычайно неудобен, именно поэтому Ткачук создал программу, которая по файлу грамматики и по получаемому каркасу парсера на C# вписывает в этот каркас правила, содержащиеся в комментариях в .grm файле в виде !* *! Это делает

Для автоматического /

Основные узлы синтаксического дерева