From cb19a36d4f73911443aabd00b280b0e37a605c97 Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Mon, 3 Mar 2025 20:19:04 +0300 Subject: [PATCH 1/6] add xbsl language --- lib/rouge/demos/xbsl | 8 ++ lib/rouge/lexers/xbsl.rb | 168 +++++++++++++++++++++++++++++++++++++++ spec/lexers/xbsl_spec.rb | 14 ++++ spec/visual/samples/xbsl | 141 ++++++++++++++++++++++++++++++++ 4 files changed, 331 insertions(+) create mode 100644 lib/rouge/demos/xbsl create mode 100644 lib/rouge/lexers/xbsl.rb create mode 100644 spec/lexers/xbsl_spec.rb create mode 100644 spec/visual/samples/xbsl diff --git a/lib/rouge/demos/xbsl b/lib/rouge/demos/xbsl new file mode 100644 index 0000000000..bef6ff569b --- /dev/null +++ b/lib/rouge/demos/xbsl @@ -0,0 +1,8 @@ +метод Скрипт() + пер Результат = 0 + если Результат == 0 + для Счетчик = 1 по 5 + Результат += 1 + ; + ; +; \ No newline at end of file diff --git a/lib/rouge/lexers/xbsl.rb b/lib/rouge/lexers/xbsl.rb new file mode 100644 index 0000000000..85d4aa9457 --- /dev/null +++ b/lib/rouge/lexers/xbsl.rb @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +module Rouge + module Lexers + class XBsl < RegexLexer + title "XBSL" + desc "The 1C:Enterprise Element programming language" + tag 'xbsl' + filenames '*.xbsl' + + KEYWORDS = /(?<=[^\wа-яё]|^)(?: + вконце | finally | возврат | return + | выбор | case | выбросить | throw + | для | for | если | if + | знч | val | и | and + | из | in | или | or + | импорт | import | иначе | else + | исключение | exception | исп | use + | как | as | когда | when + | конст | const | конструктор | constructor + | метод | method | не | not + | неизвестно | unknown | новый | new + | обз | req | область | scope + | пер | var | перечисление | enum + | по | to | поймать | catch + | пока | while | попытка | try + | прервать | break | продолжить | continue + | статический | static | структура | structure + | умолчание | default | это | is + | этот | this + )(?=[^\wа-яё]|$)/ix + + state :root do + # date + rule %r/(Дата|Date|Время|Time|ДатаВремя|DateTime|ЧасовойПояс)(\{)(.*)(\})/ do |m| + token Name::Class, m[1] + token Punctuation, m[2] + token Literal::Date, m[3] + token Punctuation, m[4] + end + + # binary + rule %r/(Байты|Bytes|Ууид|Uuid)(\{)(.*)(\})/ do |m| + token Name::Class, m[1] + token Punctuation, m[2] + token Literal::Number::Bin, m[3] + token Punctuation, m[4] + end + + # string + rule %r/\"/, Literal::String, :stringinter + + # number + rule %r/\b(-*\d+[\.]?\d*)\b/, Literal::Number + rule %r/\b(-*0x[0-9a-f]+)\b/, Literal::Number + rule %r/\b(-*0b[01]+)\b/, Literal::Number + + # new + rule %r/(новый|new)(\s+)([\wа-яё\.]+)/i do |m| + token Keyword::Declaration, m[1] + token Text, m[2] + token Name::Class, m[3] + end + + # type, recurs + rule %r/([\<:])/, Punctuation, :typestate + rule %r/\b(as|как)\b/, Keyword, :typestate + + # method + rule %r/(метод|method)(\s+)([\wа-яё]+)/i do |m| + token Keyword, m[1] + token Text, m[2] + token Name::Function, m[3] + end + + # class + rule %r/^(\s*(?:структура|structure)\s+)([\wа-яё]+)/i do |m| + token Keyword, m[1] + token Name::Entity, m[2] + end + + # import + rule %r/(импорт|import)(\s+[\wа-яё\.]+)/i do |m| + token Keyword::Namespace, m[1] + token Name::Namespace, m[2] + end + + # scope + rule %r/\b(область|scope)\b/, Comment::Preproc + + # exception + rule %r/(попытка|поймать|исключение|try|catch|exception|вконце|finally)\s/, Name::Exception + + # const + rule %r/(const|конст)(\s+[\wа-яё]+)/i do |m| + token Keyword::Constant, m[1] + token Name::Constant, m[2] + end + + # comment + rule %r(//.*$), Comment::Single + rule %r(\/\*[.\s\n\w\W]*?\*\/), Comment::Multiline + + # query + rule %r/(Запрос|Query)(\s*)(\{)/ do |m| + token Keyword::Type, m[1] + token Literal::String::Other, m[2] + token Literal::String::Delimiter, m[3] + push :queryinter + end + + rule %r/\b(знч|val)(\s+[\wа-яё]+)/ do |m| + token Keyword::Constant, m[1] + token Name::Variable, m[2] + end + + rule %r/\b(пер|var|исп|use)(\s+[\wа-яё]+)/ do |m| + token Keyword::Variable, m[1] + token Name::Variable, m[2] + end + + rule %r/\n/, Text + rule %r/[^\S\n]+/, Text + + rule %r/[\[\]:(),;{}\|]/, Punctuation + rule %r/[-+\/*%=<>.?&!]/, Operator + rule KEYWORDS, Keyword + rule %r/[\wа-яё]+/i, Name::Variable + rule %r/@[\wа-яё]+/i, Name::Tag + + end + + state :typestate do + rule %r/=/, Operator, :pop! + rule %r/\s*[0-9.xb]+/, Literal::Number, :pop! + + rule %r/([\wа-яё \t|\?\.]+)/i, Name::Class + + rule %r/\,\)\(\n]/, Punctuation, :pop! + :pop! + end + + state :stringinter do + rule %r/[%\$]*"/, Literal::String, :pop! + rule %r/(\\.)/, Literal::String::Symbol + + rule %r/([^\$%"\\]+)/, Literal::String + rule %r/([%\$](?>[^a-zа-яё_\{"]))/i, Literal::String + + rule %r/(\\.)/, Literal::String::Symbol + rule %r/([%\$](?:[\wа-яё]+|\{[^\}]+\}))/i, Literal::String::Interpol + end + + state :queryinter do + rule %r/[%\$]*\}/, Literal::String::Delimiter, :pop! + rule %r/(\\.)/, Literal::String::Symbol + + rule %r/([^\$%\{\\]+)/, Generic::Emph + rule %r/([%\$](?>[^a-zа-яё_\{"]))/i, Generic::Emph + + rule %r/(\\.)/, Literal::String::Symbol + rule %r/([%\$](?:[\wа-яё]+|\{[^\}]+\}))/i, Literal::String::Interpol + end + end + end +end diff --git a/spec/lexers/xbsl_spec.rb b/spec/lexers/xbsl_spec.rb new file mode 100644 index 0000000000..7bb83f57e1 --- /dev/null +++ b/spec/lexers/xbsl_spec.rb @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- # +# frozen_string_literal: true + +describe Rouge::Lexers::Bsl do + let(:subject) { Rouge::Lexers::XBsl.new } + + describe 'guessing' do + include Support::Guessing + + it 'guesses by filename' do + assert_guess :filename => 'foo.xbsl' + end + end +end diff --git a/spec/visual/samples/xbsl b/spec/visual/samples/xbsl new file mode 100644 index 0000000000..0bea855818 --- /dev/null +++ b/spec/visual/samples/xbsl @@ -0,0 +1,141 @@ +import Библиотека + +импорт Товары.МодульОбъекта.ОписаниеТовара + +метод Метод1(Параметр1: Тип1, Параметр2: Массив<Строка|Число>): Тип2? + + пер А: Число + А = 15 // целое десятичное число + А = 3.141592654 // дробное десятичное число + А = 15/7 // выражение с использованием десятичных чисел + А = 0xff // шестнадцатеричное число + А = -0xff // отрицательное шестнадцатеричное число + А = 0b10101 // двоичное число + + пер а: Число = 123.456 + пер б = а.Представление("'Результат: '6.2") + + // Полная форма - %{выражение} + пер Длина = 100 + пер Ширина = 30 + пер Сообщение = "Площадь равна %{Длина * Ширина} м2" + + // С форматированием - ${выражение|формат} + пер Сейчас = ДатаВремя.Сейчас() + пер Сообщение = "Текущая дата ${Сейчас|дд ММММ гггг, дддд}" +; + +метод Скрипт() + пер а: Число = 2 + пер б: Число = 3 + Консоль.Записать(а > б) // Выдаст значение Ложь типа Булево + Консоль.Записать(а < 123) // Выдаст значение Истина типа Булево + + знч Стр1 = "%0" + знч Стр2 = "$0" + знч Стр3 = "50% заряда" + знч Стр4 = "цена 10$" + область + // вариант 1 + пер ИмяПользователя: Строка + пер Приветствие = "Привет, %ИмяПользователя!" + ИмяПользователя = "Ипполит" + ; +; + + +структура ПользовательПриложения + пер Имя: Строка + пер Ид: Ууид + пер ДоступКПриложению: Булево = Истина + + // Возвращает значение: "Вторая строка" + знч СтрокаДва = новый Строка(Байты{feff04120442043e04400430044f0020044104420440043e043a0430}, + Кодировка.Utf16) + + ДанныеСообщений.Добавить("{\n \"date\" : \"%ДатаСообщения\",\n\"headers\" : %Заголовки,\n\"body\" : %Тело\n}") + + + если ФильтроватьПоВозрасту + СотрудникиПоследовательность = СотрудникиПоследовательность.Фильтровать(а -> а.Возраст > 30) + ; + + знч Запрос = Запрос{ВЫБРАТЬ + Лог.ЗаголовкиСообщения КАК Заголовки, + Лог.ТелоСообщения КАК Тело, + Лог.МеткаВремени КАК ДатаСообщения + ИЗ + Лог КАК Лог + ГДЕ + Лог.ИдентификаторСодержимогоСообщения == %ИдентификаторОбъекта + И Лог.МеткаВремени >= %ДатаОт + И Лог.МеткаВремени <= %ДатаДо} + + пер КонкретныйИдентификатор = новый Ууид("550e8400-e29b-41d4-a716-446655440000") + пер КонкретныйИдентификатор2 = Ууид{550e8400-e29b-41d4-a716-446655440000} + + метод Скрипт() + пер МоментСоздания = новый ДатаВремя(2019, 05, 01, 23, 30, 40, 345) + пер МоментСозданияФормат = МоментСоздания.ВМомент(ЧасовойПояс{UTC}) + + пер ДатаСоздания = новый ДатаВремя(2019, 5, 1, 23, 30, 40) + пер ДатаСозданияФормат = ДатаСоздания.Представление("дд ММММ гггг', 'ЧЧ:мм:сс") + + пер Период = Строки.Шаблон("С %0 по %1 года", [ДатаНачалаФормат, ДатаОкончанияФормат]) + + пер ОкончаниеРаботы = Время{18:00} + + пер Значение3: Строка|Число|Неопределено + ; + + метод НайтиПользователя(Ид: ИдПользователя): ОписаниеПользователяСервиса + знч ОписаниеПользователя = ПользователиСервиса.Найти(Ид) + + // Метод вернет "никогда", если "ОписаниеПользователя" неопределено + возврат ОписаниеПользователя != Неопределено ? ОписаниеПользователя : ВыброситьИсключение("Пользователь не найден!") + ; +; + +метод ЭтоМассив(Параметр: Объект) + пер ТипПараметра = Параметр.ПолучитьТип() + пер Результат: Строка + если Параметр это не ЧитаемыйМассив<Объект> + Результат = "Это не массив!" + иначе если Параметр это ЧитаемыйМассив<Строка> + Результат = "Это массив строк!" + иначе если Параметр это ЧитаемыйМассив<Число> + Результат = "Это массив чисел!" + иначе + Результат = "Это массив!" + ; + + пер Значение = Ссылка.ЗагрузитьОбъект()?.РеквизитСсылка?.ЗагрузитьОбъект()?.РеквизитЧисло ?? 0 +; + + +метод ПримерНаЗакрываемыйТип() + попытка + пер Файл = Файлы.Создать(СредаИсполнения.ПолучитьПеременную("temp") + "\\test.txt") + исп Поток = Файл.ОткрытьПотокЗаписи() + Поток.Записать("1-я строка\н") + Поток.Записать("2-я строка\н") + Поток.Записать("3-я строка\н") + пер Успех = "Файл записан!" + поймать Искл: Исключение + // попадем сюда, если хоть какое-то исключение случилось + // здесь поток записи уже закрыт + // переменная Поток здесь уже отсутствует + пер Ошибка = Искл.ПоследовательностьВызовов + "\н" + Искл.Описание + вконце + // попадем сюда в любом случае + // здесь поток записи уже закрыт! + // переменная Поток здесь уже отсутствует + пер Конец = "Файловый поток закрыт, переменная недоступна (выход из области видимости)" + ; +; + +перечисление ОперационныеСистемы + Linux, + macOS, + Windows умолчание +; From ad07037fc9f9e3f30ce8ff9de0fe14468e1eb813 Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Tue, 4 Mar 2025 06:52:59 +0300 Subject: [PATCH 2/6] add sbsl exten --- lib/rouge/lexers/xbsl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rouge/lexers/xbsl.rb b/lib/rouge/lexers/xbsl.rb index 85d4aa9457..65fb1435d5 100644 --- a/lib/rouge/lexers/xbsl.rb +++ b/lib/rouge/lexers/xbsl.rb @@ -7,7 +7,7 @@ class XBsl < RegexLexer title "XBSL" desc "The 1C:Enterprise Element programming language" tag 'xbsl' - filenames '*.xbsl' + filenames '*.xbsl', '*.sbsl' KEYWORDS = /(?<=[^\wа-яё]|^)(?: вконце | finally | возврат | return From c3a502b846107e33c4994fa250e3b9f6354a113a Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Mon, 10 Mar 2025 08:34:40 +0300 Subject: [PATCH 3/6] Update xbsl_spec.rb --- spec/lexers/xbsl_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lexers/xbsl_spec.rb b/spec/lexers/xbsl_spec.rb index 7bb83f57e1..8c3d7571ab 100644 --- a/spec/lexers/xbsl_spec.rb +++ b/spec/lexers/xbsl_spec.rb @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # frozen_string_literal: true -describe Rouge::Lexers::Bsl do +describe Rouge::Lexers::XBsl do let(:subject) { Rouge::Lexers::XBsl.new } describe 'guessing' do From d312347f38454f601b41027efbd1f03adeeffa62 Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Mon, 17 Mar 2025 20:39:16 +0300 Subject: [PATCH 4/6] =?UTF-8?q?1.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=80=D0=B0=D1=81=D0=BA=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=202.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=20=D1=80=D0=B0=D1=81=D0=BA=D1=80=D0=B0=D1=81=D0=BA=D0=B0=20?= =?UTF-8?q?=D1=82=D0=B8=D0=BF=D0=BE=D0=B2=203.=20=D0=A4=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/rouge/lexers/xbsl.rb | 218 ++++++++++++++++++++++----------------- spec/visual/samples/xbsl | 74 +++++++++++-- 2 files changed, 186 insertions(+), 106 deletions(-) diff --git a/lib/rouge/lexers/xbsl.rb b/lib/rouge/lexers/xbsl.rb index 65fb1435d5..51c79b6845 100644 --- a/lib/rouge/lexers/xbsl.rb +++ b/lib/rouge/lexers/xbsl.rb @@ -9,7 +9,7 @@ class XBsl < RegexLexer tag 'xbsl' filenames '*.xbsl', '*.sbsl' - KEYWORDS = /(?<=[^\wа-яё]|^)(?: + KEYWORDS = /\b(?: вконце | finally | возврат | return | выбор | case | выбросить | throw | для | for | если | if @@ -29,87 +29,150 @@ class XBsl < RegexLexer | статический | static | структура | structure | умолчание | default | это | is | этот | this - )(?=[^\wа-яё]|$)/ix + )\b/ix + + QUERY_KEYWORDS = /\b(?: + ВЫБРАТЬ | SELECT | ВСТАВИТЬ | INSERT | ИЗМЕНИТЬ | UPDATE | РАЗРЕШЕННЫЕ | ALLOWED + | ПЕРВЫЕ | TOP | РАЗЛИЧНЫЕ | DISTINCT | ОБРЕЗАТЬ | TRUNCATE | УДАЛИТЬ | DELETE + | УНИЧТОЖИТЬ | DROP | ПОМЕСТИТЬ | INTO | ИНДЕКСИРОВАТЬ | INDEX | УСТАНОВИТЬ | SET + | СОЗДАТЬ\\s+ВРЕМЕННУЮ\\s+ТАБЛИЦУ | CREATE\\s+TEMPORARY\\s+TABLE + | СОЗДАТЬ\\s+ИНДЕКС | CREATE\\s+INDEX + | ИЗ | FROM | ГДЕ | WHERE | СОЕДИНЕНИЕ | JOIN | ЛЕВОЕ | LEFT + | ПРАВОЕ | RIGHT | ПОЛНОЕ | FULL | ВНУТРЕННЕЕ | INNER | ОБЪЕДИНИТЬ | UNION + | ВСЕ | ALL | УПОРЯДОЧИТЬ | ORDER | СГРУППИРОВАТЬ | GROUP | ИМЕЮЩИЕ | HAVING + | ИЕРАРХИИ | HIERARCHY | ПО | ON | BY | ВОЗР | ASC | УБЫВ | DESC + | ДЛЯ | FOR | КАК | AS | ЕСТЬ | IS | В | IN + | ВЫРАЗИТЬ | CAST | ВЫБОР | CASE | КОГДА | WHEN | ТОГДА | THEN + | ИНАЧЕ | ELSE | КОНЕЦ | END | НЕ | NOT | ИЛИ | OR + | И | AND | ССЫЛКА | REFS | СПЕЦСИМВОЛ | ESCAPE |NULL + | ПОДОБНО | LIKE | МЕЖДУ | BETWEEN + )\b/ix state :root do - # date - rule %r/(Дата|Date|Время|Time|ДатаВремя|DateTime|ЧасовойПояс)(\{)(.*)(\})/ do |m| - token Name::Class, m[1] - token Punctuation, m[2] - token Literal::Date, m[3] - token Punctuation, m[4] + rule /(импорт|import)(\s+[\wа-яё\.]+)/i do |m| + token Keyword::Namespace, m[1] + token Name::Namespace, m[2] end - # binary - rule %r/(Байты|Bytes|Ууид|Uuid)(\{)(.*)(\})/ do |m| + mixin :query + + mixin :statements + + mixin :value_types + + mixin :comments + + rule /@[\wа-яё]+\b/i, Name::Tag + rule KEYWORDS, Keyword + mixin :literals + rule %r/(\")/, Punctuation, :string_end + mixin :other_text + rule /[\(\)\[\]]/, Punctuation + end + + state :literals do + rule %r/(?<=[^\wа-яё\.]|^)((\d+\.?\d*)|(0x[0-9a-f]+)|(0b[0-1]+))(?=[^\wа-яё\.]|$)/, Literal::Number + rule %r/(Истина|True|Ложь|False|Неопределено|Undefined)/, Keyword::Constant + rule %r/(\b[\wа-яё]+\b)(\s*\{)(.*?)(\})/i do |m| token Name::Class, m[1] token Punctuation, m[2] - token Literal::Number::Bin, m[3] + token Keyword::Constant, m[3] token Punctuation, m[4] - end + end + end - # string - rule %r/\"/, Literal::String, :stringinter + state :string_end do + rule %r/(\\.)/, Literal::String::Symbol + rule %r/([%\$])(?=\")/, Literal::String + rule %r/([^\"%\$]+?)/i, Literal::String + rule %r/([%\$][0-9\s])/, Literal::String + rule %r/([%\$](?:[\wа-яё]+|\{[^\}]+\}))/i, Generic::Inserted + rule %r/(\")/, Punctuation, :pop! + end - # number - rule %r/\b(-*\d+[\.]?\d*)\b/, Literal::Number - rule %r/\b(-*0x[0-9a-f]+)\b/, Literal::Number - rule %r/\b(-*0b[01]+)\b/, Literal::Number + state :other_text do + rule /\s+/, Text::Whitespace + rule /[\wа-яё]+/i, Name::Variable + rule %r/(->)/, Name::Function::Magic + rule %r/[:,;\|]/, Punctuation + rule %r/[-+\/*%=<>.?&!]/, Operator + rule %r/(?<=[^\wа-яё\.]|^)(не|not|и|and|или|or)(?=[^\wа-яё\.]|$)/, Operator + end - # new - rule %r/(новый|new)(\s+)([\wа-яё\.]+)/i do |m| - token Keyword::Declaration, m[1] - token Text, m[2] + state :comments do + rule %r(//.*$), Comment::Single + rule %r(\/\*[.\s\n\w\W]*?\*\/), Comment::Multiline + end + + state :query do + rule %r/\b(Запрос|Query)(\s*\{)/i do |m| + token Name::Class, m[1] + token Punctuation, m[2] + push :query_end + end + + rule %r/\b(новый|new)(\s*)\b(Запрос|Query)(\s*\(\s*\")/i do |m| + token Keyword, m[1] + token Text::Whitespace, m[2] token Name::Class, m[3] + token Punctuation, m[4] + push :query_end_bracket end + end - # type, recurs - rule %r/([\<:])/, Punctuation, :typestate - rule %r/\b(as|как)\b/, Keyword, :typestate + state :query_end do + mixin :query_body + rule %r/(\s*\})/, Punctuation, :pop! + end - # method - rule %r/(метод|method)(\s+)([\wа-яё]+)/i do |m| - token Keyword, m[1] - token Text, m[2] - token Name::Function, m[3] + state :query_end_bracket do + mixin :query_body + rule %r/(\s*\"\s*\))/, Punctuation, :pop! + end + + state :query_body do + mixin :comments + mixin :literals + rule %r/[%\$][\wа-яё]+\b/i, Generic::Inserted + rule %r/([%\$](?:[\wа-яё]+|\{[^\}]+\}))/i, Generic::Inserted + mixin :query_func + rule QUERY_KEYWORDS, Keyword + mixin :other_text + end + + state :query_func do + rule %r/\b([\wа-я]+\s*)(\()/i do |m| + token Name::Function, m[1] + token Punctuation, m[2] + push :query_func_end end + end - # class - rule %r/^(\s*(?:структура|structure)\s+)([\wа-яё]+)/i do |m| + state :query_func_end do + mixin :query_body + rule %r/(\))/, Punctuation, :pop! + end + + state :statements do + rule %r/^(\s*(?:структура|structure|перечисление|enum)\s+)([\wа-яё]+)/i do |m| token Keyword, m[1] token Name::Entity, m[2] end - - # import - rule %r/(импорт|import)(\s+[\wа-яё\.]+)/i do |m| - token Keyword::Namespace, m[1] - token Name::Namespace, m[2] - end - - # scope + rule %r/\b(область|scope)\b/, Comment::Preproc - # exception rule %r/(попытка|поймать|исключение|try|catch|exception|вконце|finally)\s/, Name::Exception - # const + rule %r/(новый|new)(\s+[\wа-яё\.]+)/i do |m| + token Keyword::Declaration, m[1] + token Name::Class, m[2] + end + rule %r/(const|конст)(\s+[\wа-яё]+)/i do |m| token Keyword::Constant, m[1] token Name::Constant, m[2] end - # comment - rule %r(//.*$), Comment::Single - rule %r(\/\*[.\s\n\w\W]*?\*\/), Comment::Multiline - - # query - rule %r/(Запрос|Query)(\s*)(\{)/ do |m| - token Keyword::Type, m[1] - token Literal::String::Other, m[2] - token Literal::String::Delimiter, m[3] - push :queryinter - end - rule %r/\b(знч|val)(\s+[\wа-яё]+)/ do |m| token Keyword::Constant, m[1] token Name::Variable, m[2] @@ -119,49 +182,14 @@ class XBsl < RegexLexer token Keyword::Variable, m[1] token Name::Variable, m[2] end - - rule %r/\n/, Text - rule %r/[^\S\n]+/, Text - - rule %r/[\[\]:(),;{}\|]/, Punctuation - rule %r/[-+\/*%=<>.?&!]/, Operator - rule KEYWORDS, Keyword - rule %r/[\wа-яё]+/i, Name::Variable - rule %r/@[\wа-яё]+/i, Name::Tag - end - state :typestate do - rule %r/=/, Operator, :pop! - rule %r/\s*[0-9.xb]+/, Literal::Number, :pop! - - rule %r/([\wа-яё \t|\?\.]+)/i, Name::Class - - rule %r/\,\)\(\n]/, Punctuation, :pop! - :pop! - end - - state :stringinter do - rule %r/[%\$]*"/, Literal::String, :pop! - rule %r/(\\.)/, Literal::String::Symbol - - rule %r/([^\$%"\\]+)/, Literal::String - rule %r/([%\$](?>[^a-zа-яё_\{"]))/i, Literal::String - - rule %r/(\\.)/, Literal::String::Symbol - rule %r/([%\$](?:[\wа-яё]+|\{[^\}]+\}))/i, Literal::String::Interpol - end - - state :queryinter do - rule %r/[%\$]*\}/, Literal::String::Delimiter, :pop! - rule %r/(\\.)/, Literal::String::Symbol - - rule %r/([^\$%\{\\]+)/, Generic::Emph - rule %r/([%\$](?>[^a-zа-яё_\{"]))/i, Generic::Emph - - rule %r/(\\.)/, Literal::String::Symbol - rule %r/([%\$](?:[\wа-яё]+|\{[^\}]+\}))/i, Literal::String::Interpol + state :value_types do + rule %r/(:\s*)([\wа-яё\?\.\ \t|<>]+)([,\)=]|$)/i do |m| + token Punctuation, m[1] + token Keyword::Type, m[2] + token Punctuation, m[3] + end end end end diff --git a/spec/visual/samples/xbsl b/spec/visual/samples/xbsl index 0bea855818..de8852c9a0 100644 --- a/spec/visual/samples/xbsl +++ b/spec/visual/samples/xbsl @@ -1,8 +1,16 @@ -import Библиотека +import Библиотека /* тест */ -импорт Товары.МодульОбъекта.ОписаниеТовара +импорт Товары.МодульОбъекта.ОписаниеТовара// dfdf -метод Метод1(Параметр1: Тип1, Параметр2: Массив<Строка|Число>): Тип2? +конст Б = Истина + +/* Многострочный + комментарий +/* может содержать + любые символы * / */ +@ВПодсистеме @клиент //sdddsds +метод Метод1(Параметр1 : Тип1, + Параметр2: Массив<Строка | Число|?> = "Значение по умолчанию"): Тип2<Тип2<Тип3|Тип4>> пер А: Число А = 15 // целое десятичное число @@ -12,11 +20,10 @@ import Библиотека А = -0xff // отрицательное шестнадцатеричное число А = 0b10101 // двоичное число - пер а: Число = 123.456 пер б = а.Представление("'Результат: '6.2") // Полная форма - %{выражение} - пер Длина = 100 + пер Длина:Число = 100 пер Ширина = 30 пер Сообщение = "Площадь равна %{Длина * Ширина} м2" @@ -25,9 +32,10 @@ import Библиотека пер Сообщение = "Текущая дата ${Сейчас|дд ММММ гггг, дддд}" ; -метод Скрипт() +статический метод Скрипт() пер а: Число = 2 пер б: Число = 3 + б++ Консоль.Записать(а > б) // Выдаст значение Ложь типа Булево Консоль.Записать(а < 123) // Выдаст значение Истина типа Булево @@ -43,8 +51,13 @@ import Библиотека ; ; +метод РассчитатьСебестоимость(Нал_ог: Число = 1, //comment + Наценка: Число = 10, /*inline*/ Цена: Строка = "Строка"): Число + возврат Цена - (Цена * Наценка / 100 + Цена * Налог / 100) +; структура ПользовательПриложения + обз пер Переменная: Строка пер Имя: Строка пер Ид: Ууид пер ДоступКПриложению: Булево = Истина @@ -63,13 +76,21 @@ import Библиотека знч Запрос = Запрос{ВЫБРАТЬ Лог.ЗаголовкиСообщения КАК Заголовки, Лог.ТелоСообщения КАК Тело, - Лог.МеткаВремени КАК ДатаСообщения + Лог.МеткаВремени КАК ДатаСообщения // комментарий ИЗ Лог КАК Лог ГДЕ Лог.ИдентификаторСодержимогоСообщения == %ИдентификаторОбъекта - И Лог.МеткаВремени >= %ДатаОт - И Лог.МеткаВремени <= %ДатаДо} + //И Лог.МеткаВремени >= %{ДатаОт} + И Лог.МеткаВремени <= %ДатаДо + И Лог.МеткаВремени != 7 + } + + знч Запрос2 = новый Запрос(" + ВЫБРАТь ПЕРВЫЕ 1 Поле, Поле2 ИЗ Таблица ГДЕ Поле НЕ ЕСТЬ NULL + ИМЕЮЩИЕ ПО СУММА(Поле2 * ВЫБОР КОГДА ИСТИНА НЕ ЕСТЬ NULL ТОГДА 1 ИНАЧЕ 42 КОНЕЦ) > 42 + / КОЛИЧЕСТВО(%Делитель) + ") пер КонкретныйИдентификатор = новый Ууид("550e8400-e29b-41d4-a716-446655440000") пер КонкретныйИдентификатор2 = Ууид{550e8400-e29b-41d4-a716-446655440000} @@ -85,7 +106,7 @@ import Библиотека пер ОкончаниеРаботы = Время{18:00} - пер Значение3: Строка|Число|Неопределено + пер Значение3: Строка|Число|Неопределено = МоментСоздания("ы") ; метод НайтиПользователя(Ид: ИдПользователя): ОписаниеПользователяСервиса @@ -132,10 +153,41 @@ import Библиотека // переменная Поток здесь уже отсутствует пер Конец = "Файловый поток закрыт, переменная недоступна (выход из области видимости)" ; + + пер А = Момент{2019-05-01 23:30:40.345 UTC+3} + пер Б = Момент(Дата{2019-05-01},Время{23:30:40},ЧасовойПояс{UTC+3}) ; перечисление ОперационныеСистемы Linux, - macOS, + macOS, // для ОС Apple Windows умолчание + + @сервер + метод МетодПеречисления(): Булево + ; + + статический метод МетодПеречисления2(): Булево + ; ; + + +структура Продажа + обз пер Товар: Строка = "Пустая" + обз пер Дата: Дата + + @ИменованныеПараметры + конструктор + + // Простой метод + метод ВСтроку(): Строка + возврат Товар + " " + Дата + ; + + // Статический метод + @Аннотация1(Параметр11 = @Аннотация2(Параметр21 = "ЗначениеПараметра")) + статический метод ИзСтроки(СтрокаПродажи: Строка): Продажа + знч Части = СтрокаПродажи.Разделить(" ") + возврат новый Продажа(Части[0], новый Дата(Части[1])) + ; +; \ No newline at end of file From 64c4f85da04df3d170bcbe695c9c78ca86c0ac1f Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Thu, 10 Apr 2025 07:25:19 +0300 Subject: [PATCH 5/6] Update xbsl --- lib/rouge/demos/xbsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rouge/demos/xbsl b/lib/rouge/demos/xbsl index bef6ff569b..6b09d90dec 100644 --- a/lib/rouge/demos/xbsl +++ b/lib/rouge/demos/xbsl @@ -5,4 +5,4 @@ Результат += 1 ; ; -; \ No newline at end of file +; From 9d3b94b2779e4b9e88ecfc5dfeeee47aa5895853 Mon Sep 17 00:00:00 2001 From: Maximov Valery Date: Thu, 10 Apr 2025 07:26:00 +0300 Subject: [PATCH 6/6] Update xbsl --- spec/visual/samples/xbsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/visual/samples/xbsl b/spec/visual/samples/xbsl index de8852c9a0..504e4d1a0c 100644 --- a/spec/visual/samples/xbsl +++ b/spec/visual/samples/xbsl @@ -190,4 +190,4 @@ import Библиотека /* тест */ знч Части = СтрокаПродажи.Разделить(" ") возврат новый Продажа(Части[0], новый Дата(Части[1])) ; -; \ No newline at end of file +;