Научная статья на тему 'Методы реализации синтаксически сахарных расширений в компиляторах'

Методы реализации синтаксически сахарных расширений в компиляторах Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
298
27
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
КОМПИЛЯТОР / СИНТАКСИЧЕСКОЕ ДЕРЕВО / СЕМАНТИЧЕСКОЕ ДЕРЕВО / РАСШИРЕНИЕ ЯЗЫКА ПРОГРАММИРОВАНИЯ / ПАТТЕРН ВИЗИТОР / СИНТАКСИЧЕСКИЙ САХАР / PASCALABC.NET / COMPILER / SYNTAX TREE / SEMANTIC TREE / PROGRAMMING LANGUAGE EXTENSION / VISITOR PATTERN / SYNTACTIC SUGAR

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Михалкович Станислав Станиславович

Рассматривается один из способов расширения языка программирования реализация новых конструкций как синтаксического сахара. Синтаксически сахарные конструкции выражаются через конструкции базового языка. Предложены несколько паттернов реализации синтаксического сахара, отличающихся действиями, проводимыми на синтаксическом и семантическом уровнях, исследована их эффективность. Приводятся результаты применения предложенных подходов к реализации ряда синтаксически сахарных конструкций в компиляторе PascalABC.NET.

i Надоели баннеры? Вы всегда можете отключить рекламу.

Похожие темы научных работ по компьютерным и информационным наукам , автор научной работы — Михалкович Станислав Станиславович

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

METHODS OF IMPLEMENTATION OF SYNTACTIC SUGAR EXTENSIONS IN COMPILERS

The paper considers one of the ways of extending a programming language the implementation of a new language elements as a syntactic sugar. During compilation syntactic sugar nodes are transformed into the ones of a basic language. The paper proposes some design patterns of the implementation of syntactic sugar constructions, with different actions on a sintactic and semantic levels. As a results of a proposed approach the implementation of a number of syntactic sugar constructions in the PascalABC.NET compiler is presented.

Текст научной работы на тему «Методы реализации синтаксически сахарных расширений в компиляторах»

ISSN 0321-2653 ИЗВЕСТИЯ ВУЗОВ. СЕВЕРО-КАВКАЗСКИЙ РЕГИОН._ТЕХНИЧЕСКИЕ НАУКИ. 2017. № 3

ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION. TECHNICAL SCIENCE. 2017. No 3

УДК 004.43 DOI: 10.17213/0321-2653-2017-3-49-55

МЕТОДЫ РЕАЛИЗАЦИИ СИНТАКСИЧЕСКИ САХАРНЫХ РАСШИРЕНИЙ В КОМПИЛЯТОРАХ

© 2017г. С.С. Михалкович

Южный федеральный университет, г. Ростов-на-Дону, Россия

METHODS OF IMPLEMENTATION OF SYNTACTIC SUGAR EXTENSIONS IN COMPILERS

S.S. Mikhalkovich

Southern Federal University, Rostov-on-Don, Russia

Михалкович Станислав Станиславович - канд. физ.-мат. наук, доцент, кафедра «Алгебра и дискретная математика», Институт математики, механики и компьютерных наук имени И.И. Воровича, Южный федеральный университет, г. Ростов-на-Дону, Россия. E-mail: [email protected]

Mikhalkovich Stanislav Stanislavovich - Candidate of Physical and Mathematical Sciences, assistant professor, department «Algebra and discrete mathematics», I.I. Vorovich Institute of Mathematics, Mechanics, and Computer Science, Southern Federal University, Rostov-on-Don, Russia. E-mail: [email protected]

Рассматривается один из способов расширения языка программирования - реализация новых конструкций как синтаксического сахара. Синтаксически сахарные конструкции выражаются через конструкции базового языка. Предложены несколько паттернов реализации синтаксического сахара, отличающихся действиями, проводимыми на синтаксическом и семантическом уровнях, исследована их эффективность. Приводятся результаты применения предложенных подходов к реализации ряда синтаксически сахарных конструкций в компиляторе PascalABC.NET.

Ключевые слова: компилятор; синтаксическое дерево; семантическое дерево; расширение языка программирования; паттерн визитор; синтаксический сахар; PascalABC.NET.

The paper considers one of the ways of extending a programming language - the implementation of a new language elements as a syntactic sugar. During compilation syntactic sugar nodes are transformed into the ones of a basic language. The paper proposes some design patterns of the implementation of syntactic sugar constructions, with different actions on a sintactic and semantic levels. As a results of a proposed approach the implementation of a number of syntactic sugar constructions in the PascalABC.NET compiler is presented.

Keywords: compiler; syntax tree; semantic tree; programming language extension; visitor pattern; syntactic sugar; PascalABC.NET.

1. Введение

Естественный путь развития любого языка программирования - его расширение новыми конструкциями. В настоящее время имеется множество исследований в этой области, которые делают акцент либо на алгоритмы трансформации программ, либо на специализированные языки расширения базовых языков, обладающие свойствами модульности и комбини-

руемости, либо на расширяемых классах грамматик.

В работе [1] дано систематическое описание способов реализации языков предметной области (DSL - Domain Specific Languages), один из которых - реализация DSL как встроенного расширения основного языка (DSEL - Domain Specific Embedding Languages). Одним из первых отметил важность создания DSEL встраиванием в основной язык P. Hudak [2], обратив внимание

ISSN0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.

на существенное снижение стоимости разработки ПО при использовании DSEL. В статье [3] описываются теоретические аспекты Stratego + SDF - системы трансформации программ и синтаксических деревьев, на которой основаны многие современные разработки. Как показано в [4] применительно к Scala, если язык достаточно богат синтаксическими конструкциями, то его расширения можно описывать в терминах самого языка. С 2011 г. развивается система SugarJ, первоначально основанная на языке Java и опирающаяся на систему Stratego. Авторы работы [5] предлагают в SugarJ расширять базовый язык с помощью специальных синтаксических библиотек, которые можно подключать в любом контексте и комбинировать произвольным образом. Развитием системы SugarJ является система Sugar* [6], где идеи расширения с помощью синтаксических библиотек распространяются на ряд других языков (Haskell, Prolog, JavaScript, System F®). Авторы [7] концентрируются на создании специальных APEG-грамматик, позволяющих проводить модульное расширение языка без грамматических конфликтов. Одна из последних публикаций по указанной тематике [8] улучшает результаты, полученные в работах [5, 6], и представляет систему SoundX, осуществляющую проверки типов в терминах расширенного, а не базового языка.

Следует отметить, что несмотря на гибкость и модульность описываемых в [3-8] систем и подходов, все они так или иначе ориентированы на конкретную систему и не предоставляют в явной форме универсальные способы реализации синтаксического сахара в стороннем компиляторе. В настоящей статье предложен ряд паттернов проектирования и реализация внутренних структур компилятора языка программирования общего назначения для реализации синтаксического сахара, дана их сравнительная характеристика.

2. Архитектура компилятора PascalABC.NET

2.1. Общее описание. Изложение далее опирается на реализацию компилятора языка программирования общего назначения PascalABC.NET, разрабатываемого под свободной лицензией [9]. Архитектура данного компилятора в значительной степени стандартная и будет использоваться здесь для иллюстрации способов реализации синтаксического сахара.

TECHNICAL SCIENCE. 2017. No 3

Язык PascalABC.NET разрабатывался первоначально в качестве учебного языка как замена устаревшему Free Pascal и как альтернатива языку Delphi. Поскольку его реализация опирается на платформу .NET, то в нем появились также типичные для .NET конструкции: интерфейсы, обработка исключений, обобщенные классы и функции, лямбда-выражения, методы расширения, перегрузка операций и др. Впоследствии после ряда усовершенствований PascalABC.NET приблизился по выразительности к языку C#, а также пополнился рядом собственных конструкций, таких как кортежи, срезы, последовательности, многие из которых реализовывались методом синтаксического сахара.

2.2. Синтаксическое дерево. Компилятор PascalABC.NET пользуется LALR(1) парсером для преобразования текста программы в синтаксическое дерево (AST-дерево). Узлы синтаксического дерева связаны иерархией наследования и генерируются автоматически из некоторого описания. Автоматический метод генерации узлов позволяет добавлять в них многочисленные универсальные методы, связанные с обходом подузлов. Отдельная группа методов связана с изменением узлов синтаксического дерева. Кроме узлов, автоматически генерируются также несколько стандартных визиторов, являющихся основой обхода синтаксических деревьев при реализации синтаксического сахара (в работе [10] дан обзор современных модификаций паттерна «визитор»).

2.3. Семантическое дерево. После построения синтаксического дерева на следующем этапе компиляции специальный визитор обходит построенное синтаксическое дерево и преобразует его в семантическое. Узлы семантического дерева не являются украшенными синтаксическими узлами, как принято делать в ряде компиляторов, а образуют отдельную иерархию. Такое же решение принято в компиляторе Roslyn [11] и удобно с точки зрения отделения синтаксического и семантического уровней.

2.4. Формализация представления деревьев. Все узлы AST-дерева - наследники абстрактного узла syntax_node и являются либо листовыми, либо содержат дочерние подузлы. Например, узел, описывающий условный оператор, имеет вид:

If(Expr, StatThen, StatElse),

где Expr - узел условного выражения в операторе if, StatThen и StatElse - узлы операторов в

ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.

ветвях then и else соответственно. Таким образом, AST-дерево удобно записывать в виде эквивалентного терма. Например, терм:

StatList(Assign(Id('a'),Const(1)),Call(Id('write'),ExprList(Id('a')))) описывает программу

begin

a := 1; write(a);

end

Запись терма принято называть абстрактным синтаксисом в противовес конкретному синтаксису, с помощью которого записана программа. Имена Const, StatList, Id и другие в записи терма являются по существу именами конструкторов соответствующих узлов синтаксического дерева.

3. Реализация синтаксического сахара

3.1. Общая схема. Пусть базовый язык без расширений представлен синтаксическими узлами с типами tb...,tn. В процессе расширения языка появляются новые синтаксические узлы с типами s1,. sk, которые мы будем называть сахарными. На этапе устранения синтаксического сахара (десахаризации) специальный визитор обходит каждый сахарный узел и заменяет его на поддерево, состоящее из узлов базового языка.

Упрощённо такой визитор состоит из множества методов visit для каждого типа сахарного узла Sj. Пусть узел типа sj имеет подузлы nb...,nr, принадлежащие вообще говоря к типам расширенного языка, тогда соответствующий метод visit имеет следующую структуру:

visit (sug: si) {

Сконструировать несахарный узел unsug = t(sug.n1,... sug.nr);

Заменить в синтаксическом дереве sug на unsug

visit (sug.n1); ... visit (sug.nr);

}

где t - тип узла базового языка. Нетрудно видеть, что при таком подходе количество сахарных узлов с каждым выполнением метода visit уменьшается на 1. Кроме того, для каждого узла (в том числе и сахарного) обходятся все его подузлы и таким образом все узлы посещаются по одному разу. Поэтому данный алгоритм корректен.

На практике могут использоваться несколько устраняющих синтаксический сахар визиторов, каждый из которых работает для своей группы сахарных узлов. Как будет показано далее, в ряде случаев последовательность применения таких визиторов значения не имеет.

3.2. Проблема семантических проверок. Основная проблема реализации, приведенной в

TECHNICAL SCIENCE. 2017. No 3

предыдущем пункте, - необходимость дополнительных семантических проверок, которые невозможно выполнить на синтаксическом уровне. Рассмотрим пример:

i++ ^ i += 1

Реализация постфиксного инкремента i++ (отсутствующая в базовом языке) осуществляется заменой на оператор += (имеющийся в базовом языке). В абстрактном синтаксисе преобразование выглядит так:

inc_node(var) ^ assignplus_node(var, int_const(1)).

Здесь для простоты узел var имеет тип var_node и может быть использован как первый параметр конструктора assignplus_node.

К сожалению, такая замена неэквивалентна: оператор += может работать с вещественными и строковыми переменными, а ++ должен работать только для целых. Поэтому необходима дополнительная семантическая проверка.

Есть два основных пути решения этой проблемы: проверка непосредственно в визиторе преобразования в семантическое дерево и отложенная проверка с включением в синтаксическое дерево специального проверочного узла.

Способ 1. Проверка в визиторе преобразования в семантическое дерево. Семантическая проверка выполняется в соответствующем методе visit визитора преобразования в семантическое дерево непосредственно перед генерацией семантического узла (далее приводится текст на псевдокоде, близком к языку C#):

visit (n: inc_node) {

IslntType(n.var.type); // если тип переменной - не целый,

то ошибка

var unsug = assignplus_node(n.var, int_const(1)); visit (unsug);

}

Заметим, что узел t принадлежит базовому языку, и генерацию семантического узла для него выполняет вызов visit (t).

Способ 2. Проверка в специальном узле синтаксического дерева. На первом этапе визитор трансформации синтаксического дерева меняет синтаксическое дерево, обходя его, заменяя сахарные узлы на несахарные (как было описано в п. 3.1), и добавляет специальный проверочный узел:

visit (n: inc_node) {

var check = sem_check_statement(n); var unsug = assignplus_node(n.var, int_const(1)); ReplaceInSynTree(n, SeqStatements(check, unsug)); visit (unsug);

}

ISSN0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.

Здесь ReplaceInSynTree меняет в синтаксическом дереве сахарный узел n на два последовательных узла: проверочный узел check и несахарный узел t. Заметим, что обход дерева устроен таким образом, что заменяющие узлы не обходятся повторно.

На втором этапе визитор преобразования в семантическое дерево при обходе специального синтаксического узла sem_check_statement выполняет необходимые семантические проверки:

visit (n: sem_check_statement) { if (n.statement is inc_node)

CheckIntTypeOrError((n as inc_node).var.type);

}

3.3. Примеры синтаксически сахарных конструкций. Рассмотрим примеры реализации синтаксического сахара. В каждом примере выделим особенности реализации, в основном связанные с семантическими проверками:

1. Тип последовательности Конкретный синтаксис:

sequence of T ^ IEnumerable<T>

Абстрактный синтаксис (генерация узлов синтаксического дерева):

sequence_node(t) ^ generic_type_node(Id('IEnumerable'), GenericParamLi st(t))

Особенность данного примера - в том, что никаких семантических проверок делать не надо.

2. Кортежи

Конкретный синтаксис:

(1,2) ^ Tuple.Create(1,2)

В данном примере также отсутствуют семантические проверки, однако имеется ограничение платформы .NET: в кортеже могут быть максимум 7 значений. Данная проверка выполняется непосредственно перед созданием синтаксического узла, т.е. на самом раннем этапе.

3. Типы кортежей Конкретный синтаксис:

(T1, T2) ^ Tuple<T1,T2>

Особенностью данного примера является то, что синтаксис типов кортежей (integer,real) конкурирует с синтаксисом перечислимого типа (Mon, Tue, Wed, Thi, Fri), уже имеющимся в базовом языке Паскаль. Выбор между конструкциями здесь возможен только на семантическом уровне: если все элементы перечисления являются именами типов или составными именами, то это тип кортежа или ошибка, в противном случае - тип перечисления или ошибка. Данный анализ не может быть осуществлён на синтаксическом уровне без существенных издержек.

TECHNICAL SCIENCE. 2017. No 3

Поэтому при реализации выбран способ 1. На синтаксическом уровне вначале генерируется узел enum_or_tuple_type_node, который после семантических проверок заменяется либо на enum_type_node, либо на tuple_type_node и обходится. После этого метод visit(node: tuple_type) реализуется так, как описано в способе 1.

4. Кортежное присваивание Конкретный синтаксис:

(a,b) := t ^ var #t1 := t; a := #t1.Item1; b := #t1.Item2;

Здесь один оператор заменяется на последовательность операторов, при этом генерируется имя новой переменной, которое не должно совпадать с уже существующими именами. При реализации используется способ 2, осуществляющий максимальное количество действий на синтаксическом уровне. Семантическая проверка в специальном узле выполняет следующие действия: t имеет тип Tuple и у t элементов не меньше, чем переменных в левой части.

Обратим внимание, что если семантическую проверку не сделать, то компилятор тем не менее выведет сообщение об ошибке, но в терминах программы, написанной на базовом языке. Например, если t имеет тип integer, то сообщение об ошибке будет иметь вид: «Item1 не объявлен в типе integer», что резко снижает качество компилятора. Обратим также внимание, что других семантических проверок делать не надо - они будут корректно выполнены позже для дерева, не содержащего сахарные узлы. Например, если тип t.Item1 не совместим по присваиванию с типом a, то выведется верное сообщение об ошибке «тип ... нельзя преобразовать к типу ...».

3.4. Синтаксический сахар и библиотечные функции. В язык PascalABC.NET введены срезы вида a[0:5:2] или a[::-1] или a[1:], где a -строка, одномерный динамический массив или список. С точки зрения компилятора срезы представляют собой синтаксически сахарные выражения, реализуемые способом 2 с некоторыми особенностями.

Первая особенность заключается в том, что узел выражения в синтаксическом дереве в отличие от узла оператора может быть заменён только на один узел, поэтому дополнительные семантические действия выполняются немного по-другому. Сахарный узел выражения заменяется на специальный узел sugared_expression, который хранит как компоненты сахарного узла, так и заменяющий узел. При обходе узла sugared_expression семантическим визитором осуществляется семантическая проверка

ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.

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

Вторая особенность состоит в том, что алгоритм вырезания среза из контейнера - достаточно сложный и реализуется в виде метода расширения соответствующего типа, который написан на PascalABC.NET и размещается в системном модуле. В частности, сахарное выражение a[f,t,step] заменяется на вызов метода a.SystemSlice(f,t,step), реализация которого занимает более полусотни строк кода на PascalABC.NET. В этом случае генерация синтаксического дерева осуществляется не вручную, а автоматически компилятором, что существенно повышает простоту реализации.

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

3.5. Реализация оператора yield. Оператор yield, участвующий в построении функций-генераторов последовательностей, реализуется генерацией достаточно большого количества кода и содержит в реализации ряд новых идей. Приведём минимальный код с оператором yield на языке PascalABC.NET:

function Squares: sequence of integer; begin for var i:=1 to 10 do yield i*i end;

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

При удалении сахара из данного кода происходит «взрыв синтаксиса»: он заменяется примерно на полсотни строк кода, написанного на базовом языке. Точнее, преобразованию подвергается соответствующее синтаксическое дерево, но для удобства мы будем говорить именно о трансформации текста программы. Тело функции Squares заменяется на Result := new #clYield1(), где класс #clYield1 генерируется во внешнем контексте до описания функции Squares. Этот класс реализует интерфейс IEnimerable<integer> и имеет в своём составе около десяти методов, основной из которых содержит код функции Squares, очищенный от

TECHNICAL SCIENCE. 2017. No 3

управляющих конструкций: все управляющие конструкции переведены в конструкции if и goto специальным Lowering-преобразованием. При этом все локальные переменные выносятся на внешний уровень и становятся полями сгенерированного класса #clYield1. После этого преобразования по полученному коду специальный алгоритм строит конечный автомат, сохраняющий своё состояние между вызовами метода, и именно код конечного автомата становится результатом устранения синтаксического сахара в теле функции Squares.

Отметим, что в промышленном компиляторе Roslyn [11] конструкция yield реализована на семантическом уровне. В компиляторе PascalABC.NET удалось реализовать конструкцию yield практически полностью на синтаксическом уровне способом 2 с небольшими семантическими проверками.

Основная сложность реализации yield -анализ всех захваченных в теле функции-генератора имён для определения вида имени: в зависимости от того, является ли имя именем вызываемой функции, именем локальной или глобальной переменной, полем класса, необходимо генерировать разный код. Анализ вида имени производится на синтаксическом уровне специальными визиторами, накапливающими легковесную семантическую информацию об этих именах. Такой способ работает гораздо быстрее тяжеловесных алгоритмов на этапе семантики, что позволяет добиться упрощения реализации и приемлемого быстродействия.

При реализации yield имеются также немногочисленные семантические действия, отличные от семантических проверок типов. Одно из основных действий - автовывод типов для переменных в теле yield. Поясним сказанное на примере. Пусть тело функции-генератора содержит переменные, тип которых явно не описан, например:

var a := sin(1) + 1;

Данный тип без проблем автовыводится в компиляторе базового языка на семантическом уровне по типу выражения в правой части. При реализации yield проблема заключается в том, что описание переменной a поднимается до поля класса, где тип должен быть указан явно: type #clYield1 = class a: ???;

и затем в теле функции-генератора описание переменной с инициализацией заменяется просто на оператор присваивания:

a := sin(1) + 1;

ISSN0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.

Решение заключается в том, чтобы заменить ??? на тип autotype, который меняется на конкретный тип при первом присваивании на тип правой части. Это достигается минимальной модификацией кода метода visit(assign_node) визитора преобразования в семантическое дерево.

3.6. Реализация оператора yield sequence.

Оператор yield sequence позволяет возвращать в функциях-генераторах не единичный элемент, а последовательность. Соответствующее преобразование, записанное в конкретном синтаксисе, крайне просто:

yield sequence s ^ foreach var #x in s do yield #x

Данное преобразование практически не требует семантических проверок и иллюстрирует перевод одной сахарной конструкции в другую. Нетрудно видеть, что при реализации способом 2 визитор для замены указанной конструкции должен располагаться перед визитором для yield. Таким образом, данный пример иллюстрирует, что раскрытие некоторых сахарных конструкций может осуществляться только в определенном порядке.

3.7. Оптимизации. В некоторых случаях приводимые способы обработки синтаксических и семантических деревьев могут быть использованы для целей, отличных от реализации синтаксического сахара. Например, следующий код

foreach var x in a do

действия с x

для массивов может быть преобразован с целью оптимизации в код

for var i := 0 to a.Length - 1 do действия с a[i]

Для этого используется способ 1: в методе visit(foreach_node) визитора преобразования в семантическое дерево проверяется тип a, и если это - динамический массив, то узел foreach_node заменяется на узел for_node, после чего последний обходится тем же визитором. К сожалению, данное преобразование неэквивалентно: в цикле foreach запрещено менять переменную x, поэтому проверку изменения x в теле цикла следует провести перед заменой кода.

Заключение

С проблемами расширения языка программирования сталкивается каждый разработчик компиляторов. Многие новые конструкции языка реализуются как синтаксический сахар: преобразованием синтаксических деревьев. В

TECHNICAL SCIENCE. 2017. No 3

настоящей работе показано, что синтаксически сахарные конструкции могут быть раскрыты преимущественно на синтаксическом уровне с минимальными семантическими действиями. Предложены два основных паттерна очистки кода от синтаксического сахара (см. п. 3.2, способы 1 и 2). Выявлены действия, которые необходимо выполнять на семантическом уровне, минимизировано количество таких действий, локализованы места их вызова. Показано, что в большинстве случаев семантические действия сводятся к проверке типов или каких-то характеристик типов (является ли тип массивом, приводится ли тип к целому и т.д.). Показано, что в этих случаях на синтаксическом уровне достаточно вводить специальные проверочные узлы, которые будут обрабатываться на семантике. Рассмотрены также ситуации, когда невозможно обойтись преобразованием синтаксических деревьев (случаи пересечения синтаксиса с базовым языком), и ситуации, когда требуются дополнительные действия на семантическом уровне (преимущественно связанные с автовыводом типа).

Отметим, что одна из наиболее мощных на сегодняшний день система SugarJ [5], реализующая близкие к настоящей статье концепции для языка Java, производит очистку от сахарных конструкций на уровне исходного кода, после чего запускает базовый компилятор Java, что менее эффективно, чем встраивание обработки синтаксического сахара в компилятор. Кроме того, SugarJ формирует сообщения об ошибках в терминах кода базового языка [8], что обесценивает возможности её практического использования. Отметим также, что наиболее идеологически близкая к компилятору PascalABC.NET система Roslyn [11] практически не содержит публикаций по реализации сложных синтаксически сахарных конструкций. Таким образом, данная статья заполняет определенный вакуум в описании внутренних механизмов реализации синтаксического сахара и ее результаты могут быть использованы при реализации расширений языка в других компиляторах.

Литература

1. Spinellis D. Notable design patterns for domain specific languages // Journal of Systems and Software, February 2001, Vol. 56. Issue 1. P. 91 - 99.

2. Hudak P. Modular domain specific languages and tools // Proceedings of International Conference on Software Reuse. IEEE, 1998. P. 134 - 142.

ISSN 0321-2653 IZVESTIYA VUZOV. SEVERO-KAVKAZSKIIREGION.

3. Bravenboer M., A. van Dam, Olmos K., Visser E. Program Transformation with Scoped Dynamic Rewrite Rules // Journal Fundamenta Informaticae - Program Transformation: Theoretical Foundations and Basic Techniques. Part 2. 2006. Vol. 69. Issue 1 - 2. P. 123 - 178.

4. Hofer C., Ostermann K. Modular domain-specific language components in Scala // Proceedings of the ninth international conference on Generative programming and component engineering GPCE '10. 2010. P. 83 - 92.

5. Erdweg S., Rendel T., Kästner C., Ostermann K. SugarJ: library-based syntactic language extensibility // Proceedings of the 2011 ACM International Conference on Object-oriented Programming, Systems, Languages, and Applications. ACM. 2011. P. 391-406.

6. Erdweg S., Rieger F. A Framework for Extensible Languages // In Proceedings of Conference on Generative Programming: Concepts & Experiences (GPCE). ACM. 2013. P. 3 - 12.

7. Reis L., V. Di Iorio, Bigonha R. An on-the-fly grammar modification mechanism for composing and defining

TECHNICAL SCIENCE. 2017. No 3

extensible languages // Computer Languages, Systems & Structures, July 2015. Vol. 42. P. 46 - 59.

8. Lorenzen F., Erdweg S. Sound Type-Dependent Syntactic Language Extension // Proceedings of Symposium on Principles of Programming Languages (POPL). ACM, 2016. Р. 204 - 216.

9. Бондарев И.В., Михалкович С.С. Система программирования PascalABC.NET - новые возможности 2015-16 гг. // XXIII науч. конф. «Современные информационные технологии: тенденции и перспективы развития»: Материалы конф. Ростов н/Д, 21 - 22 апреля 2016 г. С. 69 - 71.

10. Pati T., Hill J. H. A survey report of enhancements to the visitor software design pattern // Software: Practice and Experience. 2014. Vol. 44, Issue 6, P. 699 - 733.

11. The .NET Compiler Platform «Roslyn» URL: https://github.com/dotnet/roslyn (дата обращения: 01.02.2017).

References

1. Spinellis D. Notable design patterns for domain specific languages // Journal of Systems and Software, February 2001. Vol. 56 Is. 1. Pp. 91-99.

2. Hudak P. Modular domain specific languages and tools // Proceedings of International Conference on Software Reuse. IEEE, 1998. Pp. 134-142.

3. Bravenboer M., Dam A. van, Olmos K., Visser E. Program Transformation with Scoped Dynamic Rewrite Rules // Journal Fundamenta Informaticae - Program Transformation: Theoretical Foundations and Basic Techniques. Part 2. 2006. Vol. 69. Is. 1 - 2. Pp. 123-178.

4. Hofer C., Ostermann K. Modular domain-specific language components in Scala // Proceedings of the ninth international conference on Generative programming and component engineering GPCE '10. Pp. 83-92.

5. Erdweg S., Rendel T., Kästner C., Ostermann K. SugarJ: library-based syntactic language extensibility // Proceedings of the 2011 ACM International Conference on Object-oriented Programming, Systems, Languages, and Applications. ACM, 2011. Pp. 391406.

6. Erdweg S., Rieger F. A Framework for Extensible Languages // In Proceedings of Conference on Generative Programming: Concepts & Experiences (GPCE). ACM, 2013. Pp. 3-12.

7. Reis L., Iorio V. Di., Bigonha R. An on-the-fly grammar modification mechanism for composing and defining extensible languages // Computer Languages, Systems & Structures, July 2015, Vol. 42, Pp. 46-59.

8. Lorenzen Florian, Erdweg Sebastian. Sound Type-Dependent Syntactic Language Extension // Proceedings of Symposium on Principles of Programming Languages (POPL). ACM, 2016. Pp. 204-216.

9. Bondarev I.V., Mikhalkovich S.S. [The programming system of PascalABC.NET — new opportunities of 2015-16]. XXIII Nauchnaya konferentsiya «Sovremennye informatsionnye tekhnologii: tendentsii i perspektivy razvitiya» [XXIII Scientific conference "Modern information technologies: tendencies and prospects of development]. Rostov-on-Don, 2016, pp. 69-71. [In Russ.]

10. Tanumoy Pati, Hill James H. A survey report of enhancements to the visitor software design pattern // Software: Practice and Experience, 2014. Vol. 44, Is. 6, Pp. 699-733.

11. The .NET Compiler Platform "Roslyn" Available at: https://github.com/dotnet/roslyn (accessed 01.02.2017).

Поступила в редакцию /Received 03 мая 2017 г. /May 03, 2017

i Надоели баннеры? Вы всегда можете отключить рекламу.