diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\321\201\320\265\321\200\320\222\321\201\321\202\321\200\320\276\320\265\320\275\320\275\320\276\320\263\320\276\320\257\320\267\321\213\320\272\320\260.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\321\201\320\265\321\200\320\222\321\201\321\202\321\200\320\276\320\265\320\275\320\275\320\276\320\263\320\276\320\257\320\267\321\213\320\272\320\260.os" index 4172d16..29ca6e0 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\321\201\320\265\321\200\320\222\321\201\321\202\321\200\320\276\320\265\320\275\320\275\320\276\320\263\320\276\320\257\320\267\321\213\320\272\320\260.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\237\320\260\321\200\321\201\320\265\321\200\320\222\321\201\321\202\321\200\320\276\320\265\320\275\320\275\320\276\320\263\320\276\320\257\320\267\321\213\320\272\320\260.os" @@ -70,6 +70,8 @@ Перем Парсер_ПеременныеРазрешены; // булево Перем Парсер_СписокДиректив; // массив (ОбъявлениеДирективы) Перем Парсер_СписокАннотаций; // массив (ОбъявлениеАннотации) +Перем Парсер_СписокПроизвольныхАннотаций; // массив (ОбъявлениеПроизвольнойАннотации) +Перем Парсер_АннотацииМодуля; // массив (ОбъявлениеПроизвольнойАннотации) Перем Парсер_Интерфейс; // массив (ЭлементОкружения) Перем Парсер_Ошибки; // таблица Перем Парсер_Замены; // таблица @@ -272,6 +274,7 @@ Поля.Добавить("Переменные"); // массив (ОбъявлениеПеременнойМодуля, ОбъявлениеАвтоПеременной) Поля.Добавить("Операторы"); // массив (один из #Операторы) Поля.Добавить("Интерфейс"); // массив (ЭлементОкружения) + Поля.Добавить("Аннотации"); // массив (ОбъявлениеПроизвольнойАннотации) Парсер_Узлы.Вставить("ЭлементОкружения", Новый ТаблицаЗначений); // Узел хранит информацию об объекте области видимости. @@ -316,6 +319,33 @@ Поля.Добавить("Начало"); // один из ТаблицаТокенов Поля.Добавить("Конец"); // один из ТаблицаТокенов + Парсер_Узлы.Вставить("ПараметрАннотации", Новый ТаблицаЗначений); + // Хранит информацию о параметре аннотации. + // Пример: + //
+	// &Аннотация(Идентификатор, "Значение", ИмяПараметра = Значение)
+	// 
+ Поля = Парсер_Узлы.ПараметрАннотации.Колонки; + Поля.Добавить("Тип"); // строка (один из Типы) + Поля.Добавить("ТипПараметра"); // строка: "Идентификатор", "Значение", "Именованный" + Поля.Добавить("Имя"); // строка (для именованных параметров) + Поля.Добавить("Значение"); // неопределено, структура (один из #Выражения) или строка для идентификатора + + Парсер_Узлы.Вставить("ОбъявлениеПроизвольнойАннотации", Новый ТаблицаЗначений); + // Хранит информацию об объявлении произвольной аннотации. + // Пример: + //
+	// &АннотацияДляМетода
+	// &ЕщеОднаАннотация(1, 2, "Привет")
+	// &АннотацияПараметра(Признак = Истина)
+	// 
+ Поля = Парсер_Узлы.ОбъявлениеПроизвольнойАннотации.Колонки; + Поля.Добавить("Тип"); // строка (один из Типы) + Поля.Добавить("Имя"); // строка (имя аннотации) + Поля.Добавить("Параметры"); // массив (ПараметрАннотации) + Поля.Добавить("Начало"); // один из ТаблицаТокенов + Поля.Добавить("Конец"); // один из ТаблицаТокенов + Парсер_Узлы.Вставить("ОбъявлениеСпискаПеременныхМодуля", Новый ТаблицаЗначений); // Хранит информацию об инструкции объявления переменных уровня модуля. // Пример: @@ -342,6 +372,7 @@ Поля.Добавить("Тип"); // строка (один из Типы) Поля.Добавить("Имя"); // строка Поля.Добавить("Директивы"); // массив (ОбъявлениеДирективы) + Поля.Добавить("Аннотации"); // массив (ОбъявлениеПроизвольнойАннотации) Поля.Добавить("Экспорт"); // булево Поля.Добавить("Начало"); // один из ТаблицаТокенов Поля.Добавить("Конец"); // один из ТаблицаТокенов @@ -368,6 +399,7 @@ Поля = Парсер_Узлы.ОбъявлениеЛокальнойПеременной.Колонки; Поля.Добавить("Тип"); // строка (один из Типы) Поля.Добавить("Имя"); // строка + Поля.Добавить("Аннотации"); // массив (ОбъявлениеПроизвольнойАннотации) Поля.Добавить("Начало"); // один из ТаблицаТокенов Поля.Добавить("Конец"); // один из ТаблицаТокенов @@ -404,6 +436,7 @@ Поля.Добавить("Имя"); // строка Поля.Добавить("ПоЗначению"); // булево Поля.Добавить("Значение"); // неопределено, структура (ВыражениеУнарное, ВыражениеЛитерал) + Поля.Добавить("Аннотации"); // массив (ОбъявлениеПроизвольнойАннотации) Поля.Добавить("Начало"); // один из ТаблицаТокенов Поля.Добавить("Конец"); // один из ТаблицаТокенов @@ -1143,8 +1176,8 @@ // Другие - // // ~ & & - |Комментарий, Метка, Аннотация, Директива, НачалоТекста, КонецТекста," + // // ~ & & & # + |Комментарий, Метка, Аннотация, АннотацияПроизвольная, АннотацияМодуля, Директива, НачалоТекста, КонецТекста," ); @@ -1154,7 +1187,8 @@ Функция Типы() Экспорт Возврат Перечисление(Новый Структура, "Модуль, ЭлементОкружения, ОбъявлениеГлобальногоОбъекта, ОбъявлениеГлобальногоМетода, - |ОбъявлениеДирективы, ОбъявлениеАннотации, ОбъявлениеПеременнойМодуля, ОбъявлениеСпискаПеременныхМодуля, + |ОбъявлениеДирективы, ОбъявлениеАннотации, ОбъявлениеПроизвольнойАннотации, ПараметрАннотации, + |ОбъявлениеПеременнойМодуля, ОбъявлениеСпискаПеременныхМодуля, |ОбъявлениеСпискаЛокальныхПеременных, ОбъявлениеЛокальнойПеременной, ОбъявлениеАвтоПеременной, |ОбъявлениеПараметра, ОбъявлениеМетода, ОбъявлениеСигнатурыПроцедуры, ОбъявлениеСигнатурыФункции, |ВыражениеЛитерал, ВыражениеПоле, ВыражениеИндекс, ВыражениеИдентификатор, @@ -1454,8 +1488,8 @@ ИначеЕсли Аннотации.Свойство(Парсер_Литерал) Тогда Парсер_Токен = Токены.Аннотация; Иначе - Ошибка(3, Парсер_Литерал, Ложь); - Парсер_Токен = Токены.Директива; + // Произвольная аннотация - не выдаем ошибку + Парсер_Токен = Токены.АннотацияПроизвольная; КонецЕсли; ИначеЕсли ПредыдущийСимвол = "#" Тогда @@ -1487,7 +1521,9 @@ Если ИнструкцииПрепроцессора.Свойство(Парсер_Литерал, Парсер_Токен) Тогда Парсер_Токен = "_" + Парсер_Токен; Иначе - Ошибка(5, Парсер_Литерал, Истина); + // Возможно, это аннотация модуля - не выдаем ошибку сразу, + // синтаксический анализатор решит, является ли это аннотацией модуля + Парсер_Токен = Токены.АннотацияМодуля; КонецЕсли; ИначеЕсли ПредыдущийСимвол = "~" Тогда @@ -1729,6 +1765,7 @@ Модуль.Переменные = Переменные; Модуль.Операторы = Операторы; Модуль.Интерфейс = Парсер_Интерфейс; + Модуль.Аннотации = Парсер_АннотацииМодуля; Если СтрогийРежим Тогда Для Каждого ЭлементОкружения Из Парсер_Неизвестные Цикл ТочкиВызова = Парсер_ТочкиВызова[ЭлементОкружения.Значение]; @@ -2230,11 +2267,18 @@ #Область РазборОбъявлений Функция РазобратьОбъявленияМодуля(Переменные) - Перем Объявления, ОбъявлениеДирективы; + Перем Объявления, ОбъявлениеДирективы, АннотацииМодуля; Объявления = Новый Массив; + АннотацииМодуля = Новый Массив; + // Обработка аннотаций модуля с символом # в начале файла + Пока Парсер_Токен = Токены.АннотацияМодуля Цикл + АннотацииМодуля.Добавить(РазобратьПроизвольнуюАннотацию()); + КонецЦикла; + Парсер_АннотацииМодуля = АннотацииМодуля; // Сохраняем для использования в Разобрать() Пока Истина Цикл Парсер_СписокДиректив = Новый Массив; Парсер_СписокАннотаций = Новый Массив; + Парсер_СписокПроизвольныхАннотаций = Новый Массив; Пока Истина Цикл Если Парсер_Токен = Токены.Директива Тогда ОбъявлениеДирективы = Парсер_Узлы.ОбъявлениеДирективы.Добавить(); @@ -2244,6 +2288,8 @@ ОбъявлениеДирективы.Конец = Парсер_ДанныеТекущегоТокена; Парсер_СписокДиректив.Добавить(ОбъявлениеДирективы); СледующийТокен(); + ИначеЕсли Парсер_Токен = Токены.АннотацияПроизвольная Тогда + Парсер_СписокПроизвольныхАннотаций.Добавить(РазобратьПроизвольнуюАннотацию()); ИначеЕсли Парсер_Токен = Токены.Аннотация Тогда Аннотация = Аннотации[Парсер_Литерал]; НачалоАннотации = Парсер_ДанныеТекущегоТокена; @@ -2347,6 +2393,7 @@ ОбъявлениеПеременнойМодуля.Тип = Типы.ОбъявлениеПеременнойМодуля; ОбъявлениеПеременнойМодуля.Имя = Имя; ОбъявлениеПеременнойМодуля.Директивы = Парсер_СписокДиректив; + ОбъявлениеПеременнойМодуля.Аннотации = Парсер_СписокПроизвольныхАннотаций; ОбъявлениеПеременнойМодуля.Экспорт = ЕстьЭкспорт; ОбъявлениеПеременнойМодуля.Начало = Начало; ОбъявлениеПеременнойМодуля.Конец = Парсер_ДанныеПредыдущегоТокена; @@ -2392,13 +2439,19 @@ КонецФункции // РазобратьОбъявлениеСпискаЛокальныхПеременных() Функция РазобратьОбъявлениеЛокальнойПеременной() - Перем Имя, ОбъявлениеЛокальнойПеременной, Начало; + Перем Имя, ОбъявлениеЛокальнойПеременной, Начало, АннотацииПеременной; + // Собираем аннотации перед переменной + АннотацииПеременной = Новый Массив; + Пока Парсер_Токен = Токены.АннотацияПроизвольная Цикл + АннотацииПеременной.Добавить(РазобратьПроизвольнуюАннотацию()); + КонецЦикла; Начало = Парсер_ДанныеТекущегоТокена; Ожидать(Токены.Идентификатор); Имя = Парсер_Литерал; ОбъявлениеЛокальнойПеременной = Парсер_Узлы.ОбъявлениеЛокальнойПеременной.Добавить(); ОбъявлениеЛокальнойПеременной.Тип = Типы.ОбъявлениеЛокальнойПеременной; ОбъявлениеЛокальнойПеременной.Имя = Имя; + ОбъявлениеЛокальнойПеременной.Аннотации = АннотацииПеременной; ОбъявлениеЛокальнойПеременной.Начало = Начало; ОбъявлениеЛокальнойПеременной.Конец = Начало; Если Парсер_Переменные.Свойство(Имя) Тогда @@ -2427,12 +2480,20 @@ ЕстьЭкспорт = Истина; СледующийТокен(); КонецЕсли; + // Объединяем старые и произвольные аннотации + ВсеАннотации = Новый Массив; + Для Каждого Аннотация Из Парсер_СписокАннотаций Цикл + ВсеАннотации.Добавить(Аннотация); + КонецЦикла; + Для Каждого Аннотация Из Парсер_СписокПроизвольныхАннотаций Цикл + ВсеАннотации.Добавить(Аннотация); + КонецЦикла; Если Парсер_ЭтоФункция Тогда Сигнатура = Парсер_Узлы.ОбъявлениеСигнатурыФункции.Добавить(); Сигнатура.Тип = Типы.ОбъявлениеСигнатурыФункции; Сигнатура.Имя = Имя; Сигнатура.Директивы = Парсер_СписокДиректив; - Сигнатура.Аннотации = Парсер_СписокАннотаций; + Сигнатура.Аннотации = ВсеАннотации; Сигнатура.Параметры = Параметры; Сигнатура.Экспорт = ЕстьЭкспорт; Сигнатура.Начало = Начало; @@ -2442,7 +2503,7 @@ Сигнатура.Тип = Типы.ОбъявлениеСигнатурыПроцедуры; Сигнатура.Имя = Имя; Сигнатура.Директивы = Парсер_СписокДиректив; - Сигнатура.Аннотации = Парсер_СписокАннотаций; + Сигнатура.Аннотации = ВсеАннотации; Сигнатура.Параметры = Параметры; Сигнатура.Экспорт = ЕстьЭкспорт; Сигнатура.Начало = Начало; @@ -2511,7 +2572,12 @@ КонецФункции // РазобратьПараметры() Функция РазобратьОбъявлениеПараметра() - Перем Имя, ОбъявлениеПараметра, ПоЗначению, Начало; + Перем Имя, ОбъявлениеПараметра, ПоЗначению, Начало, АннотацииПараметра; + // Собираем аннотации перед параметром + АннотацииПараметра = Новый Массив; + Пока Парсер_Токен = Токены.АннотацияПроизвольная Цикл + АннотацииПараметра.Добавить(РазобратьПроизвольнуюАннотацию()); + КонецЦикла; Начало = Парсер_ДанныеТекущегоТокена; Если Парсер_Токен = Токены.Знач Тогда ПоЗначению = Истина; @@ -2528,6 +2594,7 @@ ОбъявлениеПараметра.Имя = Имя; ОбъявлениеПараметра.ПоЗначению = ПоЗначению; ОбъявлениеПараметра.Значение = РазобратьВыражениеУнарное(); + ОбъявлениеПараметра.Аннотации = АннотацииПараметра; ОбъявлениеПараметра.Начало = Начало; ОбъявлениеПараметра.Конец = Парсер_ДанныеПредыдущегоТокена; Иначе @@ -2536,6 +2603,7 @@ ОбъявлениеПараметра.Имя = Имя; ОбъявлениеПараметра.ПоЗначению = ПоЗначению; ОбъявлениеПараметра.Значение = Неопределено; + ОбъявлениеПараметра.Аннотации = АннотацииПараметра; ОбъявлениеПараметра.Начало = Начало; ОбъявлениеПараметра.Конец = Парсер_ДанныеПредыдущегоТокена; КонецЕсли; @@ -2550,6 +2618,72 @@ Возврат ОбъявлениеПараметра; КонецФункции // РазобратьОбъявлениеПараметра() +Функция РазобратьПроизвольнуюАннотацию() + Перем Имя, Параметры, Параметр, ОбъявлениеАннотации, Начало, ТипПараметра, ИмяПараметра, ЗначениеПараметра; + Начало = Парсер_ДанныеТекущегоТокена; + Имя = Парсер_Литерал; // Имя аннотации уже в Парсер_Литерал + СледующийТокен(); + Параметры = Новый Массив; + Если Парсер_Токен = Токены.ЛеваяКруглаяСкобка Тогда + СледующийТокен(); + Пока Парсер_Токен <> Токены.ПраваяКруглаяСкобка Цикл + Параметр = Парсер_Узлы.ПараметрАннотации.Добавить(); + Параметр.Тип = Типы.ПараметрАннотации; + Если Парсер_Токен = Токены.Идентификатор Тогда + ИмяПараметра = Парсер_Литерал; + СледующийТокен(); + Если Парсер_Токен = Токены.ЗнакРавно Тогда + // Именованный параметр: Имя = Значение + ТипПараметра = "Именованный"; + СледующийТокен(); + ЗначениеПараметра = РазобратьВыражениеУнарное(); + Параметр.ТипПараметра = ТипПараметра; + Параметр.Имя = ИмяПараметра; + Параметр.Значение = ЗначениеПараметра; + Иначе + // Просто идентификатор без значения + ТипПараметра = "Идентификатор"; + Параметр.ТипПараметра = ТипПараметра; + Параметр.Имя = ИмяПараметра; + Параметр.Значение = Неопределено; + КонецЕсли; + ИначеЕсли Парсер_Токен = Токены.Строка Или Парсер_Токен = Токены.Число Или + Парсер_Токен = Токены.Истина Или Парсер_Токен = Токены.Ложь Или + Парсер_Токен = Токены.Неопределено Или Парсер_Токен = Токены.Null Тогда + // Значение (литерал) + ТипПараметра = "Значение"; + ЗначениеПараметра = РазобратьВыражениеУнарное(); + Параметр.ТипПараметра = ТипПараметра; + Параметр.Имя = ""; + Параметр.Значение = ЗначениеПараметра; + Иначе + // Другое выражение (например, унарное) + ТипПараметра = "Значение"; + ЗначениеПараметра = РазобратьВыражениеУнарное(); + Параметр.ТипПараметра = ТипПараметра; + Параметр.Имя = ""; + Параметр.Значение = ЗначениеПараметра; + КонецЕсли; + Параметры.Добавить(Параметр); + Если Парсер_Токен = Токены.Запятая Тогда + СледующийТокен(); + ИначеЕсли Парсер_Токен <> Токены.ПраваяКруглаяСкобка Тогда + Ошибка(6, Неопределено, Истина); + Прервать; + КонецЕсли; + КонецЦикла; + Ожидать(Токены.ПраваяКруглаяСкобка); + СледующийТокен(); + КонецЕсли; + ОбъявлениеАннотации = Парсер_Узлы.ОбъявлениеПроизвольнойАннотации.Добавить(); + ОбъявлениеАннотации.Тип = Типы.ОбъявлениеПроизвольнойАннотации; + ОбъявлениеАннотации.Имя = Имя; + ОбъявлениеАннотации.Параметры = Параметры; + ОбъявлениеАннотации.Начало = Начало; + ОбъявлениеАннотации.Конец = Парсер_ДанныеПредыдущегоТокена; + Возврат ОбъявлениеАннотации; +КонецФункции // РазобратьПроизвольнуюАннотацию() + #КонецОбласти // РазборОбъявлений #Область РазборОператоров