types;
38 | /**
39 | * Если описание параметров содержит только ссылку, то здесь будет ее значение
40 | *
41 | * TODO Временное решение, надо будет продумать в следующем релизе
42 | */
43 | private final String link;
44 | /**
45 | * Признак того, что параметр является гиперссылкой
46 | */
47 | private final boolean isHyperlink;
48 |
49 | protected ParameterDescription(String name,
50 | List types,
51 | String link,
52 | boolean isHyperlink) {
53 | this.name = name;
54 | this.types = types;
55 | this.link = link;
56 | this.isHyperlink = isHyperlink;
57 | }
58 |
59 | public String getName() {
60 | return name;
61 | }
62 |
63 | public List getTypes() {
64 | return types;
65 | }
66 |
67 | public String getLink() {
68 | return link;
69 | }
70 |
71 | public boolean isHyperlink() {
72 | return isHyperlink;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/github/_1c_syntax/bsl/parser/description/BSLDescriptionReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description;
23 |
24 | import org.antlr.v4.runtime.Token;
25 |
26 | import javax.annotation.Nullable;
27 | import java.util.List;
28 |
29 | /**
30 | * Читатель объектов описания по набору токенов из текста
31 | */
32 | public final class BSLDescriptionReader {
33 |
34 | private BSLDescriptionReader() {
35 | // utility class
36 | }
37 |
38 | /**
39 | * Возвращает объект описания метода по списку токенов описания
40 | *
41 | * @param tokens Список токенов описания метода
42 | * @return Объект описания
43 | */
44 | public static MethodDescription parseMethodDescription(List tokens) {
45 | return new MethodDescription(tokens);
46 | }
47 |
48 | /**
49 | * Возвращает объект описания переменной по списку токенов описания
50 | *
51 | * @param tokens Список токенов описания переменной
52 | * @return Объект описания
53 | */
54 | public static VariableDescription parseVariableDescription(List tokens) {
55 | return new VariableDescription(tokens);
56 | }
57 |
58 | /**
59 | * Возвращает объект описания переменной по списку токенов описания и токену "висящего" описания
60 | *
61 | * @param tokens Список токенов описания переменной
62 | * @param trailing Токен "висящего" описания
63 | * @return Объект описания
64 | */
65 | public static VariableDescription parseVariableDescription(List tokens, @Nullable Token trailing) {
66 | return new VariableDescription(tokens, trailing);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/github/_1c_syntax/bsl/parser/description/support/TypeDescription.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description.support;
23 |
24 | import java.util.List;
25 |
26 | /**
27 | * Описание типа параметра, прочитанного из описания метода
28 | */
29 | public class TypeDescription {
30 | /**
31 | * Имя типа. На данный момент может быть строковый массив перечисления типов а также гиперссылка на метод
32 | */
33 | private final String name;
34 | /**
35 | * Описание типа. Может быть пустым
36 | */
37 | private final String description;
38 | /**
39 | * Параметры (ключи или поля) типа для сложных типов данных. Может быть пустым
40 | */
41 | private final List parameters;
42 | /**
43 | * Если описание параметров содержит только ссылку, то здесь будет ее значение
44 | *
45 | * TODO Временное решение, надо будет продумать в следующем релизе
46 | */
47 | private final String link;
48 | /**
49 | * Признак того, что параметр является гиперссылкой
50 | */
51 | private final boolean isHyperlink;
52 |
53 | protected TypeDescription(String name,
54 | String description,
55 | List parameters,
56 | String link,
57 | boolean isHyperlink) {
58 | this.name = name;
59 | this.description = description;
60 | this.parameters = parameters;
61 | this.link = link;
62 | this.isHyperlink = isHyperlink;
63 | }
64 |
65 | public String getName() {
66 | return name;
67 | }
68 |
69 | public String getDescription() {
70 | return description;
71 | }
72 |
73 | public List getParameters() {
74 | return parameters;
75 | }
76 |
77 | public String getLink() {
78 | return link;
79 | }
80 |
81 | public boolean isHyperlink() {
82 | return isHyperlink;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/github/_1c_syntax/bsl/parser/description/SourceDefinedSymbolDescription.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description;
23 |
24 | import com.github._1c_syntax.bsl.parser.description.support.SimpleRange;
25 | import org.antlr.v4.runtime.Token;
26 |
27 | /**
28 | * Базовый интерфейс объектов, имеющих описание
29 | */
30 | public interface SourceDefinedSymbolDescription {
31 |
32 | /**
33 | * Содержит полное описание (весь текст).
34 | *
35 | * @return Строка с описанием
36 | */
37 | String getDescription();
38 |
39 | /**
40 | * Содержит часть строки после ключевого слова, в которой должно быть
41 | * описание причины устаревания либо альтернативы.
42 | *
43 | * @return Строка с описанием причины устаревания
44 | */
45 | String getDeprecationInfo();
46 |
47 | /**
48 | * Признак устаревания.
49 | *
50 | * @return Признак устаревания: True - устарел
51 | */
52 | boolean isDeprecated();
53 |
54 | /**
55 | * Описание назначения (при наличии).
56 | *
57 | * @return Строка с описанием
58 | */
59 | String getPurposeDescription();
60 |
61 | /**
62 | * Если описание содержит только ссылку, то здесь будет ее значение
63 | *
64 | * TODO Временное решение, надо будет продумать кошерное решение
65 | *
66 | * @return Строка с текстом ссылки (без префикса см./see)
67 | */
68 | String getLink();
69 |
70 | /**
71 | * Диапазон, в котором располагается описание.
72 | *
73 | * @return Область описания
74 | */
75 | SimpleRange getSimpleRange();
76 |
77 | /**
78 | * Проверяет вхождение области заданной двумя пограничными токенами в область описания
79 | *
80 | * @param first Токен левого верхнего угла области
81 | * @param last Токен нижнего правого узла области
82 | * @return Признак вхождения
83 | */
84 | default boolean contains(Token first, Token last) {
85 | return SimpleRange.containsRange(getSimpleRange(), SimpleRange.create(first, last));
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/description/support/SimpleRangeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description.support;
23 |
24 | import org.junit.jupiter.api.Test;
25 |
26 | import static org.assertj.core.api.Assertions.assertThat;
27 |
28 | class SimpleRangeTest {
29 |
30 | @Test
31 | void containsRange() {
32 | var range1 = new SimpleRange(1, 2, 3, 4);
33 | var range2 = new SimpleRange(2, 3, 4, 5);
34 | var range3 = new SimpleRange(0, 0, 6, 6);
35 | var range4 = new SimpleRange(1, 3, 4, 7);
36 |
37 | assertThat(SimpleRange.containsRange(range1, range2)).isFalse();
38 | assertThat(SimpleRange.containsRange(range1, range3)).isFalse();
39 | assertThat(SimpleRange.containsRange(range2, range1)).isFalse();
40 | assertThat(SimpleRange.containsRange(range2, range3)).isFalse();
41 | assertThat(SimpleRange.containsRange(range3, range1)).isTrue();
42 | assertThat(SimpleRange.containsRange(range3, range2)).isTrue();
43 |
44 | assertThat(SimpleRange.containsRange(range4, range1)).isFalse();
45 | assertThat(SimpleRange.containsRange(range4, range2)).isTrue();
46 | assertThat(SimpleRange.containsRange(range4, range3)).isFalse();
47 | assertThat(SimpleRange.containsRange(range4, range4)).isTrue();
48 | }
49 |
50 | @Test
51 | void equalsRange() {
52 | var range1 = new SimpleRange(1, 2, 3, 4);
53 | var range2 = new SimpleRange(2, 3, 4, 5);
54 | var range21 = new SimpleRange(2, 3, 4, 5);
55 |
56 | assertThat(range1.equals(range2)).isFalse();
57 | assertThat(range1.equals(range1)).isTrue();
58 | assertThat(range2.equals(range21)).isTrue();
59 | assertThat(range2.equals("range21")).isFalse();
60 | }
61 |
62 | @Test
63 | void toStringRange() {
64 | var range1 = new SimpleRange(1, 2, 3, 4);
65 | var range2 = new SimpleRange(2, 3, 4, 5);
66 | var range21 = new SimpleRange(2, 3, 4, 5);
67 |
68 | assertThat(range1.toString())
69 | .contains("startLine=1")
70 | .contains("endLine=3")
71 | .contains("startCharacter=2")
72 | .contains("endCharacter=4");
73 | assertThat(range2).hasToString(range21.toString());
74 | }
75 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/src/test/resources/sdbl/select01.sdbl:
--------------------------------------------------------------------------------
1 | ВЫБРАТЬ
2 | ДокументыРасчетаСебестоимости.Ссылка КАК ДокументДвижения
3 | ПОМЕСТИТЬ ВТОкруглениеСебестоимостьТоваров
4 | ИЗ
5 | ВТКэшРасчетныеОстаткиСебестоимостьТоваров КАК Себестоимость
6 | ЛЕВОЕ СОЕДИНЕНИЕ ВТДокументыРасчетаСебестоимости КАК ДокументыРасчетаСебестоимости
7 | ПО Себестоимость.Организация = ДокументыРасчетаСебестоимости.Организация
8 | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.КлючиАналитикиУчетаНоменклатуры.Остатки() КАК Аналитика
9 | ПО Аналитика.Ссылка = Себестоимость.АналитикаУчетаНоменклатуры
10 |
11 | ГДЕ
12 | Себестоимость.Количество = 0
13 | И (Себестоимость.Стоимость МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
14 | И Себестоимость.СтоимостьБезНДС МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
15 | И Себестоимость.ДопРасходы МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
16 | И Себестоимость.ДопРасходыБезНДС МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
17 | И Себестоимость.СтоимостьРегл МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
18 | И Себестоимость.СтоимостьУпр МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
19 | И Себестоимость.ПостояннаяРазница МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
20 | И Себестоимость.ВременнаяРазница МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
21 | И Себестоимость.СтоимостьЗабалансовая МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
22 | И Себестоимость.Трудозатраты МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
23 | И Себестоимость.ПостатейныеПостоянныеСНДС МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
24 | И Себестоимость.ПостатейныеПостоянныеБезНДС МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
25 | И Себестоимость.ПостатейныеПеременныеСНДС МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
26 | И Себестоимость.ПостатейныеПеременныеБезНДС МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
27 | И Себестоимость.СтоимостьЗабалансоваяРегл МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
28 | И Себестоимость.ДопРасходыРегл МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
29 | И Себестоимость.ТрудозатратыРегл МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
30 | И Себестоимость.ПостатейныеПостоянныеРегл МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
31 | И Себестоимость.ПостатейныеПеременныеРегл МЕЖДУ -&ЗначениеПогрешностиСебестоимостьРегл И &ЗначениеПогрешностиСебестоимостьРегл
32 | И Себестоимость.СтоимостьУпр МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
33 | И Себестоимость.ДопРасходыУпр МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
34 | И Себестоимость.ТрудозатратыУпр МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
35 | И Себестоимость.ПостатейныеПостоянныеУпр МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр
36 | И Себестоимость.ПостатейныеПеременныеУпр МЕЖДУ -&ЗначениеПогрешностиСебестоимостьУпр И &ЗначениеПогрешностиСебестоимостьУпр)
--------------------------------------------------------------------------------
/src/test/resources/methodDescription/example9.bsl:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////
2 | // Copyright 2017-2021 Vladimir Bondarevskiy
3 | // https://sonar.openbsl.ru/project/issues?files=src%2Fru%2FCommonModules%2F%D0%9A%D0%BE%D0%BD%D0%BD%D0%B5%D0%BA%D1%82%D0%BE%D1%80HTTP%2FExt%2FModule.bsl&id=connector
4 | ///////////////////////////////////////////////////////////////////////////////////////////////////////
5 | // Конструктор дополнительных параметров
6 | //
7 | // Возвращаемое значение:
8 | // Структура - позволяет задать дополнительные параметры:
9 | // * Заголовки - Соответствие - см. описание Сессия.Заголовки.
10 | // * Аутентификация - Структура - см. описание Сессия.Аутентификация
11 | // * Прокси - ИнтернетПрокси - см. описание Сессия.Прокси.
12 | // * ПараметрыЗапроса - Структура, Соответствие - см. описание Сессия.ПараметрыЗапроса.
13 | // * ПроверятьSSL - Булево - см. описание Сессия.ПроверятьSSL.
14 | // * КлиентскийСертификатSSL - СертификатКлиентаФайл, СертификатКлиентаWindows - Значение по умолчанию: Неопределено.
15 | // * Cookies - Массив - см. описание Сессия.Cookies.
16 | // * Таймаут - Число - время ожидания осуществляемого соединения и операций, в секундах.
17 | // Значение по умолчанию - 30 сек.
18 | // * РазрешитьПеренаправление - Булево - Истина - редиректы будут автоматически разрешены.
19 | // Ложь - будет выполнен только один запрос к серверу.
20 | // * Json - Структура, Соответствие - данные, которые необходимо сериализовать в JSON.
21 | // * ПараметрыПреобразованияJSON - Структура - задает параметры преобразования JSON:
22 | // ** ПрочитатьВСоответствие - Булево - Если Истина, чтение объекта JSON будет выполнено в Соответствие.
23 | // Если Ложь, объекты будут считываться в объект типа Структура.
24 | // ** ФорматДатыJSON - ФорматДатыJSON - формат, в котором представлена дата в строке,
25 | // подлежащей преобразованию.
26 | // ** ИменаСвойствСоЗначениямиДата - Строка, Массив Из Строка - имена свойств JSON,
27 | // для которых нужно вызывать восстановление даты из строки.
28 | // * ПараметрыЗаписиJSON - ПараметрыЗаписиJSON - используемые при записи объекта JSON.
29 | // * Данные - Строка, ДвоичныеДанные - произвольные данные, которые необходимо отправить в запросе.
30 | // - Структура, Соответствие - поля формы, которые необходимо отправить в запрос:
31 | // ** Ключ - Строка - имя поля.
32 | // ** Значение - Строка - значение поля.
33 | // * Файлы - См. НовыйОтправляемыйФайл, Массив Из См. НовыйОтправляемыйФайл - файлы, к отправке
34 | // * МаксимальноеКоличествоПовторов - Число - количество повторных попыток соединения/отправки запроса.
35 | // Между попытками выполняется задержка, растущая по экспоненте.
36 | // Но если код состояния один из 413, 429, 503
37 | // и в ответе есть заголовок Retry-After,
38 | // то время задержки формируется из значения этого заголовка
39 | // Значение по умолчанию: 0 - повторы не выполняются.
40 | // * МаксимальноеВремяПовторов - Число - максимальное общее время (в секундах) отправки запроса с учетом повторов.
41 | // Значение по умолчанию: 600.
42 | // * КоэффициентЭкспоненциальнойЗадержки - Число - коэффициент изменения экспоненциальной задержки.
43 | // 1 формирует последовательность задержек: 1, 2, 4, 8 и т.д.
44 | // 2 формируется последовательность задержек: 2, 4, 8, 16 и т.д.
45 | // ...
46 | // Значение по умолчанию: 1.
47 | // * ПовторятьДляКодовСостояний - Неопределено - повторы будут выполняться для кодов состояний >= 500.
48 | // - Массив - повторы будут выполняться для конкретных кодов состояний.
49 | // Значение по умолчанию: Неопределено.
50 | //
--------------------------------------------------------------------------------
/src/jmh/java/com/github/_1c_syntax/bsl/parser/JMXBSLParserTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import org.antlr.v4.runtime.CharStream;
25 | import org.antlr.v4.runtime.CharStreams;
26 | import org.antlr.v4.runtime.Lexer;
27 | import org.antlr.v4.runtime.Parser;
28 | import org.apache.commons.io.IOUtils;
29 | import org.openjdk.jmh.annotations.Benchmark;
30 | import org.openjdk.jmh.annotations.BenchmarkMode;
31 | import org.openjdk.jmh.annotations.Measurement;
32 | import org.openjdk.jmh.annotations.Mode;
33 | import org.openjdk.jmh.annotations.Param;
34 | import org.openjdk.jmh.annotations.Scope;
35 | import org.openjdk.jmh.annotations.State;
36 | import org.openjdk.jmh.annotations.Warmup;
37 | import org.openjdk.jmh.util.ClassUtils;
38 |
39 | import java.io.IOException;
40 | import java.io.InputStream;
41 | import java.lang.reflect.InvocationTargetException;
42 | import java.nio.charset.StandardCharsets;
43 |
44 | @BenchmarkMode(Mode.SampleTime)
45 | @Warmup(iterations = 2) // число итераций для прогрева нашей функции
46 | @Measurement(iterations = 2, batchSize = 2)
47 | @State(Scope.Thread)
48 | public class JMXBSLParserTest {
49 |
50 | @Param({
51 | "BSLLexer"
52 | // , "BSLLexerOld"
53 | })
54 | public String lexerClassName;
55 | @Param({
56 | "BSLParser"
57 | //, "BSLParserOld"
58 | })
59 | public String parserClassName;
60 | @Param({"file"})
61 | public String parserRootASTMethodName;
62 |
63 | private String content;
64 |
65 | public JMXBSLParserTest() {
66 | final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
67 | try (InputStream inputStream = classLoader.getResourceAsStream("Module.bsl")) {
68 | assert inputStream != null;
69 | content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | }
73 | }
74 |
75 | @Benchmark
76 | public void parserTest()
77 | throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
78 | var parserClass = (Class) ClassUtils.loadClass(
79 | "com.github._1c_syntax.bsl.parser." + parserClassName);
80 | var parserRootASTMethod = parserClass.getMethod(parserRootASTMethodName);
81 | var lexerClass = (Class) ClassUtils.loadClass(
82 | "com.github._1c_syntax.bsl.parser." + lexerClassName);
83 | var lexer = (Lexer) lexerClass.getConstructor(CharStream.class)
84 | .newInstance(CharStreams.fromString(""));
85 |
86 | var tokenizer = new Tokenizer<>(content, lexer, parserClass) {
87 |
88 | @Override
89 | protected BSLParserRuleContext rootAST() {
90 | try {
91 | return (BSLParserRuleContext) parserRootASTMethod.invoke(parser);
92 | } catch (IllegalAccessException | InvocationTargetException e) {
93 | throw new RuntimeException("Error: ", e);
94 | }
95 | }
96 | };
97 | tokenizer.getAst();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/test/resources/methodDescription/example6.bsl:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////
2 | // Copyright (c) 2020, ООО 1С-Софт
3 | // Все права защищены. Эта программа и сопроводительные материалы предоставляются
4 | // в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
5 | // Текст лицензии доступен по ссылке:
6 | // https://creativecommons.org/licenses/by/4.0/legalcode
7 | ///////////////////////////////////////////////////////////////////////////////////////////////////////
8 | // Проверяет, запрещено ли изменение данных при интерактивном редактировании пользователем
9 | // или при программной загрузке данных из узла плана обмена УзелПроверкиЗапретаЗагрузки.
10 | //
11 | // Параметры:
12 | // ДанныеИлиПолноеИмя - СправочникОбъект
13 | // - ДокументОбъект
14 | // - ПланВидовХарактеристикОбъект
15 | // - ПланСчетовОбъект
16 | // - ПланВидовРасчетаОбъект
17 | // - БизнесПроцессОбъект
18 | // - ЗадачаОбъект
19 | // - ПланОбменаОбъект
20 | // - РегистрСведенийНаборЗаписей
21 | // - РегистрНакопленияНаборЗаписей
22 | // - РегистрБухгалтерииНаборЗаписей
23 | // - РегистрРасчетаНаборЗаписей - проверяемый элемент данных или набор записей.
24 | // - Строка - полное имя объекта метаданных, данные которого следует проверить в базе данных.
25 | // Например: "Документ.ПриходнаяНакладная".
26 | // В этом случае следует указать в параметре ИдентификаторДанных,
27 | // какие именно данные требуется прочитать из базы и проверить.
28 | //
29 | // ИдентификаторДанных - СправочникСсылка
30 | // - ДокументСсылка
31 | // - ПланВидовХарактеристикСсылка
32 | // - ПланСчетовСсылка
33 | // - ПланВидовРасчетаСсылка
34 | // - БизнесПроцессСсылка
35 | // - ЗадачаСсылка
36 | // - ПланОбменаСсылка
37 | // - Отбор - ссылка на элемент данных или отбор набора записей, который нужно проверить.
38 | // При этом значение для проверки будет получено из базы данных.
39 | // - Неопределено - если не требуется получать значение для проверки из базы данных,
40 | // а нужно проверить только данные самого объекта в ДанныеИлиПолноеИмя.
41 | //
42 | // ОписаниеОшибки - Null - (значение по умолчанию) - сведения о запретах не требуются.
43 | // - Строка - (возвращаемое значение) - вернуть текстовое описание найденных запретов.
44 | // - Структура - (возвращаемое значение) - вернуть структурное описание найденных запретов,
45 | // подробнее см. функцию ДатыЗапретаИзменения.НайденЗапретИзмененияДанных.
46 | //
47 | // УзелПроверкиЗапретаЗагрузки - Неопределено
48 | // - ПланыОбменаСсылка - если Неопределено, то проверить запрет
49 | // изменения данных; иначе - загрузку данных из указанного узла плана обмена.
50 | //
51 | // Возвращаемое значение:
52 | // Булево - Истина, если изменение данных запрещено.
53 | //
54 | // Варианты вызова:
55 | // ИзменениеЗапрещено(СправочникОбъект...) - проверить данные в переданном объекте (наборе записей).
56 | // ИзменениеЗапрещено(Строка, СправочникСсылка...) - проверить данные, полученные из базы данных
57 | // по полному имени объекта метаданных и ссылке (отбору набора записей).
58 | // ИзменениеЗапрещено(СправочникОбъект..., СправочникСсылка...) - проверить одновременно
59 | // данные в переданном объекте и данные в базе (т.е. "до" и "после" записи в базу, если проверка выполняется
60 | // перед записью объекта).
61 | //
--------------------------------------------------------------------------------
/src/jmh/java/com/github/_1c_syntax/bsl/parser/JMXBSLLexerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import org.antlr.v4.runtime.CharStream;
25 | import org.antlr.v4.runtime.CharStreams;
26 | import org.antlr.v4.runtime.Lexer;
27 | import org.antlr.v4.runtime.Parser;
28 | import org.antlr.v4.runtime.UnicodeCharStream;
29 | import org.apache.commons.io.IOUtils;
30 | import org.openjdk.jmh.annotations.Benchmark;
31 | import org.openjdk.jmh.annotations.BenchmarkMode;
32 | import org.openjdk.jmh.annotations.Measurement;
33 | import org.openjdk.jmh.annotations.Mode;
34 | import org.openjdk.jmh.annotations.Param;
35 | import org.openjdk.jmh.annotations.Scope;
36 | import org.openjdk.jmh.annotations.State;
37 | import org.openjdk.jmh.annotations.Warmup;
38 | import org.openjdk.jmh.util.ClassUtils;
39 |
40 | import java.io.IOException;
41 | import java.io.InputStream;
42 | import java.lang.reflect.InvocationTargetException;
43 | import java.nio.charset.StandardCharsets;
44 |
45 | @BenchmarkMode(Mode.SampleTime)
46 | @Warmup(iterations = 2) // число итераций для прогрева нашей функции
47 | @Measurement(iterations = 2, batchSize = 2)
48 | @State(Scope.Thread)
49 | public class JMXBSLLexerTest {
50 |
51 | @Param({
52 | "BSLLexer"
53 | //, "BSLLexerOld"
54 | })
55 | public String lexerClassName;
56 | @Param({
57 | "BSLParser"
58 | //, "BSLParserOld"
59 | })
60 | public String parserClassName;
61 | @Param({"file"})
62 | public String parserRootASTMethodName;
63 |
64 | private String content;
65 |
66 | public JMXBSLLexerTest() {
67 | final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
68 | try (InputStream inputStream = classLoader.getResourceAsStream("Module.bsl")) {
69 | assert inputStream != null;
70 | content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
71 | } catch (IOException e) {
72 | e.printStackTrace();
73 | }
74 | }
75 |
76 | @Benchmark
77 | public void lexerTest()
78 | throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
79 | var parserClass = (Class) ClassUtils.loadClass(
80 | "com.github._1c_syntax.bsl.parser." + parserClassName);
81 | var parserRootASTMethod = parserClass.getMethod(parserRootASTMethodName);
82 | var lexerClass = (Class) ClassUtils.loadClass(
83 | "com.github._1c_syntax.bsl.parser." + lexerClassName);
84 | var lexer = (Lexer) lexerClass.getConstructor(CharStream.class)
85 | .newInstance(CharStreams.fromString(""));
86 |
87 | var tokenizer = new Tokenizer<>(content, lexer, parserClass) {
88 |
89 | @Override
90 | protected BSLParserRuleContext rootAST() {
91 | try {
92 | return (BSLParserRuleContext) parserRootASTMethod.invoke(parser);
93 | } catch (IllegalAccessException | InvocationTargetException e) {
94 | throw new RuntimeException("Error: ", e);
95 | }
96 | }
97 | };
98 | tokenizer.getTokens();
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/antlr/BSLMethodDescriptionLexer.g4:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright © 2018-2022
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | /**
23 | * @author Maximov Valery
24 | */
25 | lexer grammar BSLMethodDescriptionLexer;
26 |
27 | // KEYWORDS
28 | PARAMETERS_KEYWORD: (P A R A M E T E R S | RU_P RU_A RU_R RU_A RU_M RU_E RU_T RU_R RU_Y) ':';
29 | RETURNS_KEYWORD: (R E T U R N S | (RU_V RU_O RU_Z RU_V RU_R RU_A RU_SCH RU_A RU_E RU_M RU_O RU_E ' ' RU_Z RU_N RU_A RU_CH RU_E RU_N RU_I RU_E)) ':';
30 | EXAMPLE_KEYWORD: (E X A M P L E S? | RU_P RU_R RU_I RU_M RU_E RU_R RU_Y?) ':';
31 | CALL_OPTIONS_KEYWORD: (C A L L ' ' O P T I O N S | RU_V RU_A RU_R RU_I RU_A RU_N RU_T RU_Y ' ' RU_V RU_Y RU_Z RU_O RU_V RU_A) ':';
32 | DEPRECATE_KEYWORD: (D E P R E C A T E | RU_U RU_S RU_T RU_A RU_R RU_E RU_L RU_A) '.'?;
33 | SEE_KEYWORD: (S E E | RU_S RU_M '.');
34 | OF_KEYWORD: (O F | C O N T A I N S | RU_I RU_Z);
35 |
36 | // COMMON
37 | EOL : '\r'? '\n';
38 | SPACE : [ \t]+;
39 | STAR : '*'+;
40 | DASH : [-–];
41 | COLON : ':';
42 | COMMA : ',';
43 | // OTHER
44 | COMMENT : '//';
45 | WORD : LETTER (LETTER | DIGIT)*;
46 | DOTSWORD: LETTER (LETTER | DIGIT)* ('.' LETTER (LETTER | DIGIT)*)+;
47 | LPAREN : '(';
48 | RPAREN : ')';
49 |
50 | ANYSYMBOL: .;
51 |
52 | // LETTERS
53 | fragment RU_A: 'А' | 'а';
54 | fragment RU_B: 'Б' | 'б';
55 | fragment RU_V: 'В' | 'в';
56 | fragment RU_G: 'Г' | 'г';
57 | fragment RU_D: 'Д' | 'д';
58 | fragment RU_YO: 'Ё' | 'ё';
59 | fragment RU_E: 'Е' | 'е';
60 | fragment RU_ZH: 'Ж' | 'ж';
61 | fragment RU_Z: 'З' | 'з';
62 | fragment RU_I: 'И' | 'и';
63 | fragment RU_J: 'Й' | 'й';
64 | fragment RU_K: 'К' | 'к';
65 | fragment RU_L: 'Л' | 'л';
66 | fragment RU_M: 'М' | 'м';
67 | fragment RU_N: 'Н' | 'н';
68 | fragment RU_O: 'О' | 'о';
69 | fragment RU_P: 'П' | 'п';
70 | fragment RU_R: 'Р' | 'р';
71 | fragment RU_S: 'С' | 'с';
72 | fragment RU_T: 'Т' | 'т';
73 | fragment RU_U: 'У' | 'у';
74 | fragment RU_F: 'Ф' | 'ф';
75 | fragment RU_H: 'Х' | 'х';
76 | fragment RU_C: 'Ц' | 'ц';
77 | fragment RU_CH: 'Ч' | 'ч';
78 | fragment RU_SH: 'Ш' | 'ш';
79 | fragment RU_SCH: 'Щ' | 'щ';
80 | fragment RU_SOLID_SIGN: 'Ъ' | 'ъ';
81 | fragment RU_Y: 'Ы' | 'ы';
82 | fragment RU_SOFT_SIGN: 'Ь' | 'ь';
83 | fragment RU_EH: 'Э' | 'э';
84 | fragment RU_YU: 'Ю' | 'ю';
85 | fragment RU_YA: 'Я' | 'я';
86 | fragment A: 'A' | 'a';
87 | fragment B: 'B' | 'b';
88 | fragment C: 'C' | 'c';
89 | fragment D: 'D' | 'd';
90 | fragment I: 'I' | 'i';
91 | fragment J: 'J' | 'j';
92 | fragment E: 'E' | 'e';
93 | fragment F: 'F' | 'f';
94 | fragment G: 'G' | 'g';
95 | fragment U: 'U' | 'u';
96 | fragment K: 'K' | 'k';
97 | fragment L: 'L' | 'l';
98 | fragment M: 'M' | 'm';
99 | fragment N: 'N' | 'n';
100 | fragment O: 'O' | 'o';
101 | fragment P: 'P' | 'p';
102 | fragment Q: 'Q' | 'q';
103 | fragment R: 'R' | 'r';
104 | fragment S: 'S' | 's';
105 | fragment T: 'T' | 't';
106 | fragment V: 'V' | 'v';
107 | fragment H: 'H' | 'h';
108 | fragment W: 'W' | 'w';
109 | fragment X: 'X' | 'x';
110 | fragment Y: 'Y' | 'y';
111 |
112 | // LITERALS
113 | fragment DIGIT: [0-9];
114 | fragment LETTER: [\p{Letter}] | '_';
115 |
--------------------------------------------------------------------------------
/.github/workflows/gh-pages.yml:
--------------------------------------------------------------------------------
1 | name: GitHub Pages
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - develop
8 | paths:
9 | - 'docs/**'
10 | - 'src/main/java/**'
11 | - 'src/main/antlr/**'
12 | - 'mkdocs.yml'
13 | - 'mkdocs.en.yml'
14 | - '.github/workflows/gh-pages.yml'
15 |
16 | jobs:
17 | build-deploy:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - uses: actions/checkout@v6
21 | with:
22 | fetch-depth: 0
23 |
24 | - name: Setup JDK
25 | uses: actions/setup-java@v5
26 | with:
27 | java-version: 17
28 | distribution: 'adopt'
29 |
30 | - name: Build javadoc
31 | run: ./gradlew --no-daemon javadoc
32 |
33 | - name: Set up Python
34 | uses: actions/setup-python@v6
35 | with:
36 | python-version: '3.12'
37 | architecture: 'x64'
38 |
39 | - name: Install dependencies
40 | run: |
41 | pip install --upgrade pip
42 | pip install mkdocs mkdocs-material pygments-bsl
43 |
44 | - name: Dowload latest GitHub Pages
45 | run: |
46 | wget https://github.com/${{ github.repository }}/archive/gh-pages.zip || true
47 | unzip gh-pages.zip || true
48 | mkdir tmp-bench
49 |
50 | - name: Save latest Develop
51 | if: github.ref == 'refs/heads/master'
52 | run: |
53 | mkdir public
54 | mkdir public/dev
55 | cp -R ${GITHUB_REPOSITORY#*/}-gh-pages/dev/. public/dev || true
56 |
57 | - name: Save latest Master
58 | if: github.ref == 'refs/heads/develop'
59 | run: |
60 | mkdir public
61 | cp -R ${GITHUB_REPOSITORY#*/}-gh-pages/. public || true
62 | rm -rf public/dev || true
63 | mkdir public/dev
64 |
65 | - name: Patch Develop
66 | if: github.ref == 'refs/heads/develop'
67 | run: |
68 | sed -i "s%BSLParser%BSL Parser Dev%g" mkdocs.yml
69 | sed -i "s%BSLParser%BSL Parser Dev%g" mkdocs.en.yml
70 | sed -i "s%https://1c-syntax.github.io/bsl-parser%https://1c-syntax.github.io/bsl-parser/dev%g" mkdocs.yml
71 | sed -i "s%https://1c-syntax.github.io/bsl-parser%https://1c-syntax.github.io/bsl-parser/dev%g" mkdocs.en.yml
72 | sed -i "s%link: /bsl-parser/%link: /bsl-parser/dev/%g" mkdocs.yml
73 | sed -i "s%link: /bsl-parser/%link: /bsl-parser/dev/%g" mkdocs.en.yml
74 |
75 | - name: Build Russian
76 | run: |
77 | mkdir temp
78 | cp mkdocs.yml temp
79 | cp -R docs/ru/. temp/docs
80 | mkdir temp/docs/assets
81 | cp -R docs/assets/. temp/docs/assets
82 | rm -rf temp/docs/en
83 | cd temp
84 | mkdocs build
85 |
86 | - name: Copy javadoc
87 | run: |
88 | cp -R build/docs/javadoc temp/site/javadoc
89 | echo "" > temp/site/.nojekyll
90 |
91 | - name: Public Russian Master
92 | if: github.ref == 'refs/heads/master'
93 | run: |
94 | cp -R temp/site/. public
95 |
96 | - name: Public Russian Develop
97 | if: github.ref == 'refs/heads/develop'
98 | run: |
99 | cp -R temp/site/. public/dev
100 |
101 | - name: Clean temp
102 | run: rm -rf temp
103 |
104 | - name: Build English
105 | run: |
106 | mkdir temp
107 | cp mkdocs.en.yml temp/mkdocs.yml
108 | mkdir temp/docs
109 | cp -R docs/en/. temp/docs
110 | mkdir temp/docs/assets
111 | cp -R docs/assets/. temp/docs/assets
112 | cd temp
113 | mkdocs build
114 |
115 | - name: Public English Master
116 | if: github.ref == 'refs/heads/master'
117 | run: |
118 | mkdir public/en
119 | cp -R temp/site/. public/en
120 |
121 | - name: Public English Develop
122 | if: github.ref == 'refs/heads/develop'
123 | run: |
124 | mkdir public/dev/en
125 | cp -R temp/site/. public/dev/en
126 |
127 | - name: Deploy
128 | uses: peaceiris/actions-gh-pages@v4.0.0
129 | with:
130 | deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
131 | publish_branch: gh-pages
132 | publish_dir: ./public
133 |
--------------------------------------------------------------------------------
/src/test/resources/methodDescription/example1.bsl:
--------------------------------------------------------------------------------
1 | // Запустить выполнение процедуры в фоновом задании, если это возможно.
2 | //
3 | // При выполнении любого из следующих условий запуск выполняется не в фоне, а сразу в основном потоке:
4 | // * если вызов выполняется в файловой базе во внешнем соединении (в этом режиме фоновые задания не поддерживаются);
5 | // * если приложение запущено в режиме отладки (параметр /C РежимОтладки) - для упрощения отладки конфигурации;
6 | // * если в файловой ИБ имеются активные фоновые задания - для снижения времени ожидания пользователя;
7 | // * если выполняется процедура модуля внешней обработки или внешнего отчета.
8 | //
9 | // Не следует использовать эту функцию, если необходимо безусловно запускать фоновое задание.
10 | // Может применяться совместно с функцией ДлительныеОперацииКлиент.ОжидатьЗавершение.
11 | //
12 | // Вызываемая процедура может быть с произвольным числом параметров, но не более 7.
13 | // Значения передаваемых параметров процедуры, а также возвращаемое значение должны быть сериализуемыми.
14 | // Параметры процедуры не должны быть возвращаемыми.
15 | //
16 | // Параметры:
17 | //
18 | // ПараметрыВыполнения - см. ДлительныеОперации.ПараметрыВыполненияПроцедуры
19 | //
20 | // ИмяПроцедуры - Строка - имя экспортной процедуры общего модуля, модуля менеджера объекта
21 | // или модуля обработки, которую необходимо выполнить в фоне.
22 | // Например, "МойОбщийМодуль.МояПроцедура", "Отчеты.ЗагруженныеДанные.Сформировать"
23 | // или "Обработки.ЗагрузкаДанных.МодульОбъекта.Загрузить".
24 | //
25 | // Параметр1 - Произвольный - произвольные параметры вызова процедуры. Количество параметров может быть от 0 до 7.
26 | // Параметр2 - Произвольный
27 | // Параметр3 - Произвольный
28 | // Параметр4 - Произвольный
29 | // Параметр5 - Произвольный
30 | // Параметр6 - Произвольный
31 | // Параметр7 - Произвольный
32 | //
33 | // Возвращаемое значение:
34 | // Структура - параметры выполнения задания:
35 | // * Статус - Строка - "Выполняется", если задание еще не завершилось;
36 | // "Выполнено", если задание было успешно выполнено;
37 | // "Ошибка", если задание завершено с ошибкой;
38 | // "Отменено", если задание отменено пользователем или администратором.
39 | // * ИдентификаторЗадания - УникальныйИдентификатор - если Статус = "Выполняется", то содержит
40 | // идентификатор запущенного фонового задания.
41 | // * КраткоеПредставлениеОшибки - Строка - краткая информация об исключении, если Статус = "Ошибка".
42 | // * ПодробноеПредставлениеОшибки - Строка - подробная информация об исключении, если Статус = "Ошибка".
43 | // * Сообщения - ФиксированныйМассив - если Статус <> "Выполняется", то массив объектов СообщениеПользователю,
44 | // которые были сформированы в фоновом задании.
45 | //
46 | // Пример:
47 | // В общем виде процесс запуска и обработки результата длительной операции в модуле формы выглядит следующим образом:
48 | //
49 | // 1) Процедура, которая будет исполняться в фоне, располагается в модуле менеджера объекта или в серверном общем модуле:
50 | // Процедура ВыполнитьРасчет(Знач МойПараметр1, Знач МойПараметр2) Экспорт
51 | // ...
52 | // КонецПроцедуры
53 | //
54 | // 2) Запуск операции на сервере и подключение обработчика ожидания (при необходимости):
55 | // &НаКлиенте
56 | // Процедура ВыполнитьРасчет()
57 | // ДлительнаяОперация = НачатьВыполнениеНаСервере();
58 | // ОповещениеОЗавершении = Новый ОписаниеОповещения("ОбработатьРезультат", ЭтотОбъект);
59 | // ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
60 | // ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
61 | // КонецПроцедуры
62 | //
63 | // &НаСервере
64 | // Функция НачатьВыполнениеНаСервере()
65 | // Возврат ДлительныеОперации.ВыполнитьПроцедуру(, "Обработки.МояОбработка.ВыполнитьРасчет",
66 | // МойПараметр1, МойПараметр2);
67 | // КонецФункции
68 | //
69 | // 3) Обработка результата длительной операции:
70 | // &НаКлиенте
71 | // Процедура ОбработатьРезультат(Результат, ДополнительныеПараметры) Экспорт
72 | // Если Результат = Неопределено Тогда
73 | // Возврат;
74 | // КонецЕсли;
75 | // ПриЗавершенииРасчета();
76 | // КонецПроцедуры
--------------------------------------------------------------------------------
/src/main/java/com/github/_1c_syntax/bsl/parser/description/VariableDescription.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description;
23 |
24 | import com.github._1c_syntax.bsl.parser.BSLMethodDescriptionTokenizer;
25 | import com.github._1c_syntax.bsl.parser.description.support.DescriptionReader;
26 | import com.github._1c_syntax.bsl.parser.description.support.SimpleRange;
27 | import org.antlr.v4.runtime.Token;
28 |
29 | import javax.annotation.Nullable;
30 | import java.util.List;
31 | import java.util.Optional;
32 | import java.util.stream.Collectors;
33 |
34 | import static java.util.Objects.requireNonNull;
35 |
36 | /**
37 | * Класс-описание переменной.
38 | */
39 | public final class VariableDescription implements SourceDefinedSymbolDescription {
40 |
41 | /**
42 | * Содержит полное описание переменной (весь текст)
43 | */
44 | private final String description;
45 |
46 | /**
47 | * Содержит часть строки после ключевого слова, в которой должно быть
48 | * описание причины устаревания переменной либо альтернативы
49 | */
50 | private final String deprecationInfo;
51 |
52 | /**
53 | * Признак устаревания переменной
54 | */
55 | private final boolean deprecated;
56 |
57 | /**
58 | * Описание назначения переменной
59 | */
60 | private final String purposeDescription;
61 |
62 | /**
63 | * Если описание содержит только ссылку, то здесь будет ее значение
64 | *
65 | * TODO Временное решение, надо будет продумать кошерное решение
66 | */
67 | private final String link;
68 |
69 | /**
70 | * Диапазон, в котором располагается описание.
71 | */
72 | private final SimpleRange range;
73 |
74 | /**
75 | * Описание "висячего" комментария
76 | */
77 | private final VariableDescription trailingDescription;
78 |
79 | VariableDescription(List comments) {
80 | this(comments, null);
81 | }
82 |
83 | VariableDescription(List comments, @Nullable Token trailingComment) {
84 | description = comments.stream()
85 | .map(Token::getText)
86 | .collect(Collectors.joining("\n"));
87 |
88 | var tokenizer = new BSLMethodDescriptionTokenizer(description);
89 | var ast = requireNonNull(tokenizer.getAst());
90 |
91 | range = SimpleRange.create(comments);
92 | purposeDescription = DescriptionReader.readPurposeDescription(ast);
93 | link = DescriptionReader.readLink(ast);
94 | deprecated = ast.deprecate() != null;
95 | deprecationInfo = DescriptionReader.readDeprecationInfo(ast);
96 | if (trailingComment == null) {
97 | trailingDescription = null;
98 | } else {
99 | trailingDescription = new VariableDescription(List.of(trailingComment));
100 | }
101 | }
102 |
103 | @Override
104 | public String getDescription() {
105 | return description;
106 | }
107 |
108 | @Override
109 | public String getDeprecationInfo() {
110 | return deprecationInfo;
111 | }
112 |
113 | @Override
114 | public boolean isDeprecated() {
115 | return deprecated;
116 | }
117 |
118 | @Override
119 | public String getPurposeDescription() {
120 | return purposeDescription;
121 | }
122 |
123 | @Override
124 | public String getLink() {
125 | return link;
126 | }
127 |
128 | @Override
129 | public SimpleRange getSimpleRange() {
130 | return range;
131 | }
132 |
133 | public Optional getTrailingDescription() {
134 | return Optional.ofNullable(trailingDescription);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/antlr/BSLMethodDescriptionParser.g4:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright © 2018-2022
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | /**
23 | * @author Maximov Valery
24 | */
25 | parser grammar BSLMethodDescriptionParser;
26 |
27 | options {
28 | tokenVocab = BSLMethodDescriptionLexer;
29 | }
30 |
31 | // структура описания
32 | methodDescription:
33 | (
34 | (deprecate? descriptionBlock? parameters? callOptions? returnsValues? examples?)
35 | | (deprecate? descriptionBlock? parameters? examples? returnsValues? callOptions?)
36 | | (deprecate? descriptionBlock? parameters? callOptions? examples? returnsValues?)
37 | | (deprecate? descriptionBlock? parameters? examples? callOptions? returnsValues?)
38 | | (descriptionBlock? parameters? callOptions? returnsValues? examples? deprecate?)
39 | | (descriptionBlock? parameters? examples? returnsValues? callOptions? deprecate?)
40 | | (descriptionBlock? parameters? callOptions? examples? returnsValues? deprecate?)
41 | | (descriptionBlock? parameters? examples? callOptions? returnsValues? deprecate?)
42 | ) EOF;
43 |
44 | // deprecate
45 | deprecate: startPart DEPRECATE_KEYWORD (SPACE deprecateDescription)? EOL?;
46 | deprecateDescription: ~(SPACE | EOL) ~EOL*;
47 |
48 | // description
49 | descriptionBlock: (hyperlinkBlock | description) EOL?;
50 | description: descriptionString+;
51 | descriptionString:
52 | (startPart ~(PARAMETERS_KEYWORD | RETURNS_KEYWORD | EXAMPLE_KEYWORD | CALL_OPTIONS_KEYWORD | DEPRECATE_KEYWORD | EOL | SPACE) ~EOL* EOL?)
53 | | (startPart EOL)
54 | ;
55 |
56 | // examples
57 | examples: startPart EXAMPLE_KEYWORD (EOL examplesString*)?;
58 | examplesString:
59 | (startPart ~(CALL_OPTIONS_KEYWORD | RETURNS_KEYWORD | EOL | SPACE) ~EOL* EOL?)
60 | | (startPart EOL?)
61 | ;
62 |
63 | // callOptions
64 | callOptions: startPart CALL_OPTIONS_KEYWORD (EOL callOptionsString*)?;
65 | callOptionsString:
66 | (startPart ~(RETURNS_KEYWORD | EXAMPLE_KEYWORD | EOL | SPACE) ~EOL* EOL?)
67 | | (startPart EOL?)
68 | ;
69 |
70 | // parameters
71 | parameters: startPart PARAMETERS_KEYWORD SPACE? (EOL (hyperlinkBlock | parameterString+)?)? EOL?;
72 | parameterString:
73 | parameter
74 | | (startPart typesBlock)
75 | | subParameter
76 | | (startPart typeDescription)
77 | | (startPart EOL?)
78 | ;
79 | parameter: startPart parameterName typesBlock;
80 | subParameter: startPart STAR SPACE? parameterName typesBlock;
81 | parameterName: WORD;
82 |
83 | // returnsValues
84 | returnsValues: startPart RETURNS_KEYWORD SPACE? (EOL (hyperlinkBlock | returnsValuesString+)?)? EOL?;
85 | returnsValuesString:
86 | returnsValue
87 | | (startPart typesBlock)
88 | | subParameter
89 | | (startPart typeDescription)
90 | | (startPart EOL?)
91 | ;
92 |
93 | returnsValue: startPart type ((spitter typeDescription?) | EOL);
94 |
95 | typesBlock: spitter type ((spitter typeDescription?) | EOL);
96 |
97 | typeDescription:
98 | SPACE? ~(RETURNS_KEYWORD | EXAMPLE_KEYWORD | CALL_OPTIONS_KEYWORD | EOL | SPACE | STAR) ~EOL* EOL;
99 |
100 | type:
101 | hyperlinkType
102 | | listTypes
103 | | (simpleType COLON?)
104 | | complexType
105 | ;
106 | simpleType: (WORD | DOTSWORD);
107 | listTypes: (simpleType | complexType | hyperlinkType) (COMMA SPACE? (simpleType | complexType | hyperlinkType))+;
108 |
109 | complexType:
110 | collection=(WORD | DOTSWORD) SPACE OF_KEYWORD SPACE type;
111 | hyperlinkType:
112 | SEE_KEYWORD SPACE link=(WORD | DOTSWORD) (LPAREN linkParams=~(EOL)* RPAREN)?;
113 |
114 | spitter: SPACE? DASH SPACE?;
115 |
116 | hyperlinkBlock: (startPart EOL)* startPart hyperlinkType SPACE? (EOL startPart)*;
117 | startPart: SPACE? COMMENT SPACE?;
--------------------------------------------------------------------------------
/src/main/java/com/github/_1c_syntax/bsl/parser/description/MethodDescription.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description;
23 |
24 | import com.github._1c_syntax.bsl.parser.BSLMethodDescriptionTokenizer;
25 | import com.github._1c_syntax.bsl.parser.description.support.DescriptionReader;
26 | import com.github._1c_syntax.bsl.parser.description.support.ParameterDescription;
27 | import com.github._1c_syntax.bsl.parser.description.support.SimpleRange;
28 | import com.github._1c_syntax.bsl.parser.description.support.TypeDescription;
29 | import org.antlr.v4.runtime.Token;
30 |
31 | import java.util.List;
32 | import java.util.stream.Collectors;
33 |
34 | import static java.util.Objects.requireNonNull;
35 |
36 | /**
37 | * Класс-описание метода (процедуры или функции).
38 | */
39 | public final class MethodDescription implements SourceDefinedSymbolDescription {
40 | /**
41 | * Содержит полное описание метода (весь текст).
42 | */
43 | private final String description;
44 | /**
45 | * Содержит часть строки после ключевого слова, в которой должно быть
46 | * описание причины устаревания метода либо альтернативы.
47 | */
48 | private final String deprecationInfo;
49 | /**
50 | * Признак устаревания метода.
51 | */
52 | private final boolean deprecated;
53 | /**
54 | * Описание назначения метода.
55 | */
56 | private final String purposeDescription;
57 | /**
58 | * Примеры использования метода.
59 | */
60 | private final List examples;
61 | /**
62 | * Варианты вызова метода.
63 | */
64 | private final List callOptions;
65 | /**
66 | * Параметры метода с типами и описанием.
67 | */
68 | private final List parameters;
69 | /**
70 | * Возвращаемые значения (типы).
71 | */
72 | private final List returnedValue;
73 | /**
74 | * Если описание содержит только ссылку, то здесь будет ее значение.
75 | *
76 | * TODO Временное решение, надо будет продумать в следующем релизе
77 | */
78 | private final String link;
79 | /**
80 | * Диапазон, в котором располагается описание.
81 | */
82 | private final SimpleRange range;
83 |
84 | MethodDescription(List comments) {
85 | description = comments.stream()
86 | .map(Token::getText)
87 | .collect(Collectors.joining("\n"));
88 |
89 | var tokenizer = new BSLMethodDescriptionTokenizer(description);
90 | var ast = requireNonNull(tokenizer.getAst());
91 |
92 | purposeDescription = DescriptionReader.readPurposeDescription(ast);
93 | link = DescriptionReader.readLink(ast);
94 | deprecated = ast.deprecate() != null;
95 | deprecationInfo = DescriptionReader.readDeprecationInfo(ast);
96 | callOptions = DescriptionReader.readCallOptions(ast);
97 | examples = DescriptionReader.readExamples(ast);
98 | parameters = DescriptionReader.readParameters(ast);
99 | returnedValue = DescriptionReader.readReturnedValue(ast);
100 | range = SimpleRange.create(comments);
101 | }
102 |
103 | @Override
104 | public String getDescription() {
105 | return description;
106 | }
107 |
108 | @Override
109 | public String getDeprecationInfo() {
110 | return deprecationInfo;
111 | }
112 |
113 | @Override
114 | public boolean isDeprecated() {
115 | return deprecated;
116 | }
117 |
118 | @Override
119 | public String getPurposeDescription() {
120 | return purposeDescription;
121 | }
122 |
123 | @Override
124 | public String getLink() {
125 | return link;
126 | }
127 |
128 | @Override
129 | public SimpleRange getSimpleRange() {
130 | return range;
131 | }
132 |
133 | public List getExamples() {
134 | return examples;
135 | }
136 |
137 | public List getCallOptions() {
138 | return callOptions;
139 | }
140 |
141 | public List getParameters() {
142 | return parameters;
143 | }
144 |
145 | public List getReturnedValue() {
146 | return returnedValue;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/main/java/com/github/_1c_syntax/bsl/parser/description/support/SimpleRange.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser.description.support;
23 |
24 | import org.antlr.v4.runtime.Token;
25 |
26 | import java.util.List;
27 |
28 | /**
29 | * Класс для хранения области символов
30 | */
31 | public final class SimpleRange {
32 |
33 | /**
34 | * Номер первой строки области
35 | */
36 | private final int startLine;
37 |
38 | /**
39 | * Номер первого символа области
40 | */
41 | private final int startCharacter;
42 |
43 | /**
44 | * Номер последней строки области
45 | */
46 | private final int endLine;
47 |
48 | /**
49 | * Номер последнего символа области
50 | */
51 | private final int endCharacter;
52 |
53 | public SimpleRange(int startLine, int startCharacter, int endLine, int endCharacter) {
54 | this.startLine = startLine;
55 | this.startCharacter = startCharacter;
56 | this.endLine = endLine;
57 | this.endCharacter = endCharacter;
58 | }
59 |
60 | /**
61 | * Проверяет вхождение второй области в первую
62 | *
63 | * @param bigger Первая область
64 | * @param smaller Вторая область
65 | * @return Признак вхождения второй в первую
66 | */
67 | public static boolean containsRange(SimpleRange bigger, SimpleRange smaller) {
68 | if (bigger.getStartLine() > smaller.getStartLine()
69 | || bigger.getEndLine() < smaller.getEndLine()) {
70 | return false;
71 | }
72 |
73 | if (bigger.getStartLine() == smaller.getStartLine()
74 | && bigger.getStartCharacter() > smaller.getStartCharacter()) {
75 | return false;
76 | }
77 |
78 | return bigger.getEndLine() != smaller.getEndLine()
79 | || bigger.getEndCharacter() >= smaller.getEndCharacter();
80 | }
81 |
82 | /**
83 | * Создает новую область по токенам углов области
84 | *
85 | * @param startToken Токен левого верхнего угла
86 | * @param endToken Токен правого нижнего узла
87 | * @return Созданная область
88 | */
89 | public static SimpleRange create(Token startToken, Token endToken) {
90 | int startLine = startToken.getLine() - 1;
91 | int startChar = startToken.getCharPositionInLine();
92 | int endLine = endToken.getLine() - 1;
93 | int endChar;
94 | if (endToken.getType() == Token.EOF) {
95 | endChar = endToken.getCharPositionInLine();
96 | } else {
97 | endChar = endToken.getCharPositionInLine() + endToken.getText().length();
98 | }
99 |
100 | return new SimpleRange(startLine, startChar, endLine, endChar);
101 | }
102 |
103 | /**
104 | * Создает область по списку токенов
105 | *
106 | * @param tokens Список токенов области
107 | * @return Созданная область
108 | */
109 | public static SimpleRange create(List tokens) {
110 | if (tokens.isEmpty()) {
111 | return new SimpleRange(0, 0, 0, 0);
112 | }
113 | var firstElement = tokens.get(0);
114 | var lastElement = tokens.get(tokens.size() - 1);
115 |
116 | return create(firstElement, lastElement);
117 | }
118 |
119 | public int getStartLine() {
120 | return startLine;
121 | }
122 |
123 | public int getStartCharacter() {
124 | return startCharacter;
125 | }
126 |
127 | public int getEndLine() {
128 | return endLine;
129 | }
130 |
131 | public int getEndCharacter() {
132 | return endCharacter;
133 | }
134 |
135 | public String toString() {
136 | return ("SimpleRange(startLine=" + startLine
137 | + ", startCharacter=" + startCharacter
138 | + ", endLine=" + endLine
139 | + ", endCharacter=" + endCharacter + ")").intern();
140 | }
141 |
142 | public boolean equals(final Object other) {
143 | if (other == this) {
144 | return true;
145 | } else if (!(other instanceof SimpleRange otherRange)) {
146 | return false;
147 | } else {
148 | return (startLine == otherRange.getStartLine()
149 | && startCharacter == otherRange.getStartCharacter()
150 | && endLine == otherRange.getEndLine()
151 | && endCharacter == otherRange.getEndCharacter());
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLParserMatchesTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import com.github._1c_syntax.bsl.parser.testing.TestParser;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.params.ParameterizedTest;
27 | import org.junit.jupiter.params.provider.ValueSource;
28 |
29 | class SDBLParserMatchesTest {
30 |
31 | private TestParser testParser;
32 |
33 | @BeforeEach
34 | void before() {
35 | testParser = new TestParser<>(SDBLParser.class, SDBLLexer.class);
36 | }
37 |
38 | @ParameterizedTest
39 | @ValueSource(strings =
40 | {
41 | "ВЫБРАТь 1",
42 | "Select Fld from table",
43 | "Drop table",
44 | """
45 | Выбрать * из Справочник.Пользователи;
46 | Выбрать * поместиТЬ ВТ Из &Таблица где поле = 1;
47 | Уничтожить ТЧ;
48 | """
49 | }
50 | )
51 | void testQueryPackage(String inputString) {
52 | testParser.assertThat(inputString).matches(testParser.parser().queryPackage());
53 | }
54 |
55 | @ParameterizedTest
56 | @ValueSource(strings =
57 | {
58 | "", ";", "Какой-то текст", "Запрос = Новый Запрос()"
59 | }
60 | )
61 | void testNoQueryPackage(String inputString) {
62 | testParser.assertThat(inputString).noMatches(testParser.parser().queryPackage());
63 | }
64 |
65 | @ParameterizedTest
66 | @ValueSource(strings =
67 | {
68 | "ВЫБРАТь 1",
69 | "Select Fld from table",
70 | "drop table",
71 | """
72 | Выбрать * из Справочник.Пользователи;
73 | Выбрать * поместиТЬ ВТ Из &Таблица где поле = 1;
74 | Уничтожить ТЧ;
75 | """
76 | }
77 | )
78 | void testQueries(String inputString) {
79 | testParser.assertThat(inputString).matches(testParser.parser().queries());
80 | }
81 |
82 | @ParameterizedTest
83 | @ValueSource(strings =
84 | {
85 | "ВЫБРАТь",
86 | "Уничтожить;",
87 | """
88 | УничтожитьТЧ;
89 | Уничтожить;
90 | """
91 | }
92 | )
93 | void testNoQueries(String inputString) {
94 | testParser.assertThat(inputString).noMatches(testParser.parser().queries());
95 | }
96 |
97 | @ParameterizedTest
98 | @ValueSource(strings =
99 | {
100 | "drop table",
101 | """
102 | Уничтожить ТЧ;
103 | Уничтожить ТЧ2;
104 | """
105 | }
106 | )
107 | void testDropTableQuery(String inputString) {
108 | testParser.assertThat(inputString).matches(testParser.parser().dropTableQuery());
109 | }
110 |
111 | @ParameterizedTest
112 | @ValueSource(strings =
113 | {
114 | "drops table",
115 | """
116 | Выбрать 1;
117 | Уничтожить ТЧ2;
118 | """,
119 | ""
120 | }
121 | )
122 | void testNoDropTableQuery(String inputString) {
123 | testParser.assertThat(inputString).noMatches(testParser.parser().dropTableQuery());
124 | }
125 |
126 | @ParameterizedTest
127 | @ValueSource(strings =
128 | {
129 | "выбрать поле из таблица",
130 | "выбрать поле из таблица объединить выбрать поле2 из таблица2 упорядочить поле",
131 | "выбрать первые 1 поле из таблица объединить выбрать поле2 из таблица2 упорядочить поле сгруппировать по поле",
132 | "выбрать * из таблица, таблица2 сгруппировать по поле1 итоги по поле2",
133 | }
134 | )
135 | void testSelectQuery(String inputString) {
136 | testParser.assertThat(inputString).matches(testParser.parser().selectQuery());
137 | }
138 |
139 | @ParameterizedTest
140 | @ValueSource(strings =
141 | {
142 | "выбрать поле из таблица",
143 | "выбрать поле из таблица объединить выбрать поле2 из таблица2 упорядочить поле",
144 | "выбрать первые 1 поле из таблица объединить выбрать поле2 из таблица2 упорядочить поле сгруппировать по поле",
145 | "выбрать * из таблица сгруппировать по поле1 итоги сумма(1) по поле2",
146 | }
147 | )
148 | void testSubquery(String inputString) {
149 | testParser.assertThat(inputString).matches(testParser.parser().subquery());
150 | }
151 |
152 | @ParameterizedTest
153 | @ValueSource(strings =
154 | {
155 | "Объединить выбрать 1", "объединить все выбрать 2", "объединить все выбрать 2 упорядочить по поле"
156 | }
157 | )
158 | void testUnion(String inputString) {
159 | testParser.assertThat(inputString).matches(testParser.parser().union());
160 | }
161 |
162 | @ParameterizedTest
163 | @ValueSource(strings =
164 | {
165 | "выбрать 1", "выбрать первые 1 2", "выбрать 1 как поле поместить вт",
166 | "выбрать 1 как поле поместить .вт", "выбрать 1 как поле поместить вт#1#", "выбрать 1 как поле поместить ##",
167 | "выбрать различные поле из таблица", "выбрать различные Таблица.поле как поле из таблица",
168 | "выбрать различные Сумма(Sin(поле)) из таблица индексировать по поле",
169 | "выбрать поле, поле1, таблица.поле3 как как из таблица сгруппировать по поле для изменения"
170 | }
171 | )
172 | void testQuery(String inputString) {
173 | testParser.assertThat(inputString).matches(testParser.parser().query());
174 | }
175 |
176 | @ParameterizedTest
177 | @ValueSource(strings =
178 | {
179 | "первые 0",
180 | "первые 10 разрешенные различные",
181 | "различные первые 10 разрешенные ",
182 | "разрешенные различные первые 10 "
183 | }
184 | )
185 | void testLimitations(String inputString) {
186 | testParser.assertThat(inputString).matches(testParser.parser().limitations());
187 | }
188 |
189 | @ParameterizedTest
190 | @ValueSource(strings =
191 | {
192 | "0", "\"текст\"", "NULL, Поле.Поле.Поле", "Поле.Поле.Поле КАК Поле", "*, \"\" as fld",
193 | "Поле", "ПустаяТаблица(), Sin(f), f"
194 | }
195 | )
196 | void testSelectedFields(String inputString) {
197 | testParser.assertThat(inputString).matches(testParser.parser().selectedFields());
198 | }
199 |
200 | @ParameterizedTest
201 | @ValueSource(strings =
202 | {
203 | "0", "\"текст\"", "NULL как Поле", "Поле.Поле.Поле КАК Поле", "Поле.*", "\"\" as fld",
204 | "Поле", "Sin(f) as f"
205 | }
206 | )
207 | void testSelectedField(String inputString) {
208 | testParser.assertThat(inputString).matches(testParser.parser().selectedField());
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/BSLMethodDescriptionParserMatchesTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import com.github._1c_syntax.bsl.parser.testing.TestParser;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.api.Test;
27 | import org.junit.jupiter.params.ParameterizedTest;
28 | import org.junit.jupiter.params.provider.ValueSource;
29 |
30 | class BSLMethodDescriptionParserMatchesTest {
31 |
32 | private TestParser testParser;
33 |
34 | @BeforeEach
35 | void before() {
36 | testParser = new TestParser<>(BSLMethodDescriptionParser.class, BSLMethodDescriptionLexer.class);
37 | }
38 |
39 | @ParameterizedTest
40 | @ValueSource(strings =
41 | {
42 | "",
43 | "//Устарела но не\n//\n//\t//34567890-dfghjkl_)(*&^%$#@ Совсем \n//" +
44 | "//||Описание метода\n// \n//" +
45 | "//Параметры//",
46 | "//Устарела.", "//Параметры:", "//Варианты вызова:", "//Пример:", "//Возвращаемое значение:"
47 | }
48 | )
49 | void testMethodDescription(String inputString) {
50 | testParser.assertThat(inputString).matches(testParser.parser().methodDescription());
51 | }
52 |
53 | @Test
54 | void testDeprecate() {
55 | testParser.assertThat("").noMatches(testParser.parser().deprecate());
56 | testParser.assertThat("//Устарела").matches(testParser.parser().deprecate());
57 |
58 | testParser.assertThat("//Описание\nУстарела").noMatches(testParser.parser().deprecate());
59 | testParser.assertThat("//Описание\nУстарела.").noMatches(testParser.parser().deprecate());
60 |
61 | testParser.assertThat("// Устарела.")
62 | .matches(testParser.parser().deprecate())
63 | .noMatches(testParser.parser().deprecateDescription());
64 | testParser.assertThat("//Устарела.")
65 | .matches(testParser.parser().deprecate())
66 | .noMatches(testParser.parser().deprecateDescription());
67 | testParser.assertThat("//Устарела.\n")
68 | .matches(testParser.parser().deprecate())
69 | .noMatches(testParser.parser().deprecateDescription());
70 |
71 | testParser.assertThat("//Устарела. \nИспользовать другой метод")
72 | .matches(testParser.parser().deprecate())
73 | .containsRule(BSLMethodDescriptionParser.RULE_deprecateDescription, 0);
74 | testParser.assertThat("//Устарела. \n//Использовать другой метод")
75 | .matches(testParser.parser().deprecate())
76 | .containsRule(BSLMethodDescriptionParser.RULE_deprecateDescription, 0);
77 |
78 | testParser.assertThat("//Устарела. Использовать другой метод")
79 | .matches(testParser.parser().deprecate())
80 | .containsRule(BSLMethodDescriptionParser.RULE_deprecateDescription, 1);
81 |
82 | testParser.assertThat("//Устарела.Использовать другой метод")
83 | .matches(testParser.parser().methodDescription())
84 | .containsRule(BSLMethodDescriptionParser.RULE_deprecate, 0);
85 | }
86 |
87 | @ParameterizedTest
88 | @ValueSource(strings =
89 | {
90 | "//Устарела.", "//Устарела.\n//Параметры:", "//Устарела.\n//Call options:", "//returns:", "//example:"
91 | }
92 | )
93 | void testNoDescription(String inputString) {
94 | testParser.assertThat(inputString).containsRule(BSLMethodDescriptionParser.RULE_description, 0);
95 | }
96 |
97 | @Test
98 | void testDescription() {
99 | testParser.assertThat("//Устарела.\n//Описание\n//\n//ногостчрочное")
100 | .containsRule(BSLMethodDescriptionParser.RULE_description, 1);
101 | testParser.assertThat("//Описание \n// многострочное:")
102 | .containsRule(BSLMethodDescriptionParser.RULE_description, 1);
103 | }
104 |
105 | @Test
106 | void testNoParameters() {
107 | testParser.assertThat("//Параметры").noMatches(testParser.parser().parameters());
108 | }
109 |
110 | @ParameterizedTest
111 | @ValueSource(strings =
112 | {
113 | "//Параметры:\n//Параметр1\n//\n//Параметр2\n",
114 | "//Параметры:\n//Параметр1\n//\n//Параметр2\n//Пример:",
115 | "//Параметры:\n//Параметр1\n//\n//Параметр2\n//Варианты вызова:",
116 | "//Параметры:\n//Параметр1\n//\n//Параметр2\n//Возвращаемое значение:",
117 | "//Параметры:\n//Параметр1 - Тип Описание\n//\n//Параметр2\n//Возвращаемое значение:"
118 | }
119 | )
120 | void testParameters(String inputString) {
121 | testParser.assertThat(inputString)
122 | .matches(testParser.parser().parameters())
123 | .containsRule(BSLMethodDescriptionParser.RULE_parameterString, 3);
124 | }
125 |
126 | @Test
127 | void testNoCallOptions() {
128 | testParser.assertThat("//Варианты вызова").noMatches(testParser.parser().callOptions());
129 | }
130 |
131 | @ParameterizedTest
132 | @ValueSource(strings =
133 | {
134 | "//Call options:\n//Var 1\n//\n//Var 2 bla ba()",
135 | "//Call options:\n//Var 1\n//\n//Var 2 bla ba()\n//Example:",
136 | "//Call options:\n//Var 1\n//\n//Var 2 bla ba()\n//Возвращаемое значение:"
137 | }
138 | )
139 | void testCallOptions(String inputString) {
140 | testParser.assertThat(inputString)
141 | .matches(testParser.parser().callOptions())
142 | .containsRule(BSLMethodDescriptionParser.RULE_callOptionsString, 3);
143 | }
144 |
145 | @Test
146 | void testReturns() {
147 | testParser.assertThat("//returns").noMatches(testParser.parser().returnsValues());
148 | testParser.assertThat("//returns:\n//boolean - description\n")
149 | .matches(testParser.parser().returnsValues())
150 | .containsRule(BSLMethodDescriptionParser.RULE_returnsValuesString, 1);
151 | testParser.assertThat("//returns:\n// - ref - description\n// - boolean - description\n//Example:")
152 | .matches(testParser.parser().returnsValues())
153 | .containsRule(BSLMethodDescriptionParser.RULE_returnsValuesString, 2);
154 | }
155 |
156 | @Test
157 | void testExample() {
158 | testParser.assertThat("//Пример").noMatches(testParser.parser().examples());
159 | testParser.assertThat("//Пример:\n//Пример - описаниепримера")
160 | .matches(testParser.parser().examples())
161 | .containsRule(BSLMethodDescriptionParser.RULE_examplesString, 1);
162 | testParser.assertThat("//Пример:\n//Пример:\n//Пример: - описаниепримера")
163 | .matches(testParser.parser().examples())
164 | .containsRule(BSLMethodDescriptionParser.RULE_examplesString, 2);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/COPYING.LESSER.md:
--------------------------------------------------------------------------------
1 | GNU Lesser General Public License
2 | =================================
3 |
4 | _Version 3, 29 June 2007_
5 | _Copyright © 2007 Free Software Foundation, Inc. <>_
6 |
7 | Everyone is permitted to copy and distribute verbatim copies
8 | of this license document, but changing it is not allowed.
9 |
10 |
11 | This version of the GNU Lesser General Public License incorporates
12 | the terms and conditions of version 3 of the GNU General Public
13 | License, supplemented by the additional permissions listed below.
14 |
15 | ### 0. Additional Definitions
16 |
17 | As used herein, “this License” refers to version 3 of the GNU Lesser
18 | General Public License, and the “GNU GPL” refers to version 3 of the GNU
19 | General Public License.
20 |
21 | “The Library” refers to a covered work governed by this License,
22 | other than an Application or a Combined Work as defined below.
23 |
24 | An “Application” is any work that makes use of an interface provided
25 | by the Library, but which is not otherwise based on the Library.
26 | Defining a subclass of a class defined by the Library is deemed a mode
27 | of using an interface provided by the Library.
28 |
29 | A “Combined Work” is a work produced by combining or linking an
30 | Application with the Library. The particular version of the Library
31 | with which the Combined Work was made is also called the “Linked
32 | Version”.
33 |
34 | The “Minimal Corresponding Source” for a Combined Work means the
35 | Corresponding Source for the Combined Work, excluding any source code
36 | for portions of the Combined Work that, considered in isolation, are
37 | based on the Application, and not on the Linked Version.
38 |
39 | The “Corresponding Application Code” for a Combined Work means the
40 | object code and/or source code for the Application, including any data
41 | and utility programs needed for reproducing the Combined Work from the
42 | Application, but excluding the System Libraries of the Combined Work.
43 |
44 | ### 1. Exception to Section 3 of the GNU GPL
45 |
46 | You may convey a covered work under sections 3 and 4 of this License
47 | without being bound by section 3 of the GNU GPL.
48 |
49 | ### 2. Conveying Modified Versions
50 |
51 | If you modify a copy of the Library, and, in your modifications, a
52 | facility refers to a function or data to be supplied by an Application
53 | that uses the facility (other than as an argument passed when the
54 | facility is invoked), then you may convey a copy of the modified
55 | version:
56 |
57 | * **a)** under this License, provided that you make a good faith effort to
58 | ensure that, in the event an Application does not supply the
59 | function or data, the facility still operates, and performs
60 | whatever part of its purpose remains meaningful, or
61 |
62 | * **b)** under the GNU GPL, with none of the additional permissions of
63 | this License applicable to that copy.
64 |
65 | ### 3. Object Code Incorporating Material from Library Header Files
66 |
67 | The object code form of an Application may incorporate material from
68 | a header file that is part of the Library. You may convey such object
69 | code under terms of your choice, provided that, if the incorporated
70 | material is not limited to numerical parameters, data structure
71 | layouts and accessors, or small macros, inline functions and templates
72 | (ten or fewer lines in length), you do both of the following:
73 |
74 | * **a)** Give prominent notice with each copy of the object code that the
75 | Library is used in it and that the Library and its use are
76 | covered by this License.
77 | * **b)** Accompany the object code with a copy of the GNU GPL and this license
78 | document.
79 |
80 | ### 4. Combined Works
81 |
82 | You may convey a Combined Work under terms of your choice that,
83 | taken together, effectively do not restrict modification of the
84 | portions of the Library contained in the Combined Work and reverse
85 | engineering for debugging such modifications, if you also do each of
86 | the following:
87 |
88 | * **a)** Give prominent notice with each copy of the Combined Work that
89 | the Library is used in it and that the Library and its use are
90 | covered by this License.
91 |
92 | * **b)** Accompany the Combined Work with a copy of the GNU GPL and this license
93 | document.
94 |
95 | * **c)** For a Combined Work that displays copyright notices during
96 | execution, include the copyright notice for the Library among
97 | these notices, as well as a reference directing the user to the
98 | copies of the GNU GPL and this license document.
99 |
100 | * **d)** Do one of the following:
101 | - **0)** Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 | - **1)** Use a suitable shared library mechanism for linking with the
109 | Library. A suitable mechanism is one that **(a)** uses at run time
110 | a copy of the Library already present on the user's computer
111 | system, and **(b)** will operate properly with a modified version
112 | of the Library that is interface-compatible with the Linked
113 | Version.
114 |
115 | * **e)** Provide Installation Information, but only if you would otherwise
116 | be required to provide such information under section 6 of the
117 | GNU GPL, and only to the extent that such information is
118 | necessary to install and execute a modified version of the
119 | Combined Work produced by recombining or relinking the
120 | Application with a modified version of the Linked Version. (If
121 | you use option **4d0**, the Installation Information must accompany
122 | the Minimal Corresponding Source and Corresponding Application
123 | Code. If you use option **4d1**, you must provide the Installation
124 | Information in the manner specified by section 6 of the GNU GPL
125 | for conveying Corresponding Source.)
126 |
127 | ### 5. Combined Libraries
128 |
129 | You may place library facilities that are a work based on the
130 | Library side by side in a single library together with other library
131 | facilities that are not Applications and are not covered by this
132 | License, and convey such a combined library under terms of your
133 | choice, if you do both of the following:
134 |
135 | * **a)** Accompany the combined library with a copy of the same work based
136 | on the Library, uncombined with any other library facilities,
137 | conveyed under the terms of this License.
138 | * **b)** Give prominent notice with the combined library that part of it
139 | is a work based on the Library, and explaining where to find the
140 | accompanying uncombined form of the same work.
141 |
142 | ### 6. Revised Versions of the GNU Lesser General Public License
143 |
144 | The Free Software Foundation may publish revised and/or new versions
145 | of the GNU Lesser General Public License from time to time. Such new
146 | versions will be similar in spirit to the present version, but may
147 | differ in detail to address new problems or concerns.
148 |
149 | Each version is given a distinguishing version number. If the
150 | Library as you received it specifies that a certain numbered version
151 | of the GNU Lesser General Public License “or any later version”
152 | applies to it, you have the option of following the terms and
153 | conditions either of that published version or of any later version
154 | published by the Free Software Foundation. If the Library as you
155 | received it does not specify a version number of the GNU Lesser
156 | General Public License, you may choose any version of the GNU Lesser
157 | General Public License ever published by the Free Software Foundation.
158 |
159 | If the Library as you received it specifies that a proxy can decide
160 | whether future versions of the GNU Lesser General Public License shall
161 | apply, that proxy's public statement of acceptance of any version is
162 | permanent authorization for you to choose that version for the
163 | Library.
164 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/BSLMethodDescriptionLexerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import com.github._1c_syntax.bsl.parser.testing.TestLexer;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.api.Test;
27 |
28 | class BSLMethodDescriptionLexerTest {
29 |
30 | private TestLexer testLexer;
31 |
32 | @BeforeEach
33 | void before() {
34 | testLexer = new TestLexer<>(BSLMethodDescriptionLexer.class);
35 | }
36 |
37 | @Test
38 | void testWhitespaces() {
39 | var inputString = "// А";
40 | testLexer.assertThat(BSLMethodDescriptionLexer.DEFAULT_MODE, inputString)
41 | .containsExactly(BSLMethodDescriptionLexer.COMMENT,
42 | BSLMethodDescriptionLexer.SPACE,
43 | BSLMethodDescriptionLexer.WORD,
44 | BSLMethodDescriptionLexer.EOF);
45 | }
46 |
47 | @Test
48 | void testBOM() {
49 | testLexer.assertThat('\uFEFF' + "Процедура").containsAll(BSLMethodDescriptionLexer.WORD);
50 | }
51 |
52 | @Test
53 | void testHyperlink() {
54 | testLexer.assertThat("СМ").isEqualTo("СМСМ").containsAll(BSLMethodDescriptionLexer.WORD);
55 | testLexer.assertThat("SEE").isEqualTo("СМ.").containsAll(BSLMethodDescriptionLexer.SEE_KEYWORD);
56 |
57 | testLexer.assertThat("СМ. ОбщийМодуль")
58 | .isEqualTo("SEE ОбщийМодуль")
59 | .isEqualTo("SEE ОбщийМодуль")
60 | .containsAll(
61 | BSLMethodDescriptionLexer.SEE_KEYWORD,
62 | BSLMethodDescriptionLexer.SPACE,
63 | BSLMethodDescriptionLexer.WORD);
64 |
65 | testLexer.assertThat("SSEE ОбщийМодуль")
66 | .containsAll(BSLMethodDescriptionLexer.WORD, BSLMethodDescriptionLexer.SPACE, BSLMethodDescriptionLexer.WORD);
67 |
68 | testLexer.assertThat("СМ. ОбщийМодуль.Метод").isEqualTo("SEE ОбщийМодуль.Метод")
69 | .containsAll(
70 | BSLMethodDescriptionLexer.SEE_KEYWORD,
71 | BSLMethodDescriptionLexer.SPACE,
72 | BSLMethodDescriptionLexer.DOTSWORD);
73 |
74 | testLexer.assertThat("SEE ОбщийМодуль.Метод()").containsAll(
75 | BSLMethodDescriptionLexer.SEE_KEYWORD,
76 | BSLMethodDescriptionLexer.SPACE,
77 | BSLMethodDescriptionLexer.DOTSWORD,
78 | BSLMethodDescriptionLexer.LPAREN,
79 | BSLMethodDescriptionLexer.RPAREN);
80 |
81 | testLexer.assertThat("СМ. ОбщийМодуль.Метод(Параметра, Значение)").containsAll(
82 | BSLMethodDescriptionLexer.SEE_KEYWORD,
83 | BSLMethodDescriptionLexer.SPACE,
84 | BSLMethodDescriptionLexer.DOTSWORD,
85 | BSLMethodDescriptionLexer.LPAREN,
86 | BSLMethodDescriptionLexer.WORD,
87 | BSLMethodDescriptionLexer.COMMA,
88 | BSLMethodDescriptionLexer.SPACE,
89 | BSLMethodDescriptionLexer.WORD,
90 | BSLMethodDescriptionLexer.RPAREN);
91 |
92 | testLexer.assertThat("SEE ОбщийМодуль.Метод() WORD").containsAll(
93 | BSLMethodDescriptionLexer.SEE_KEYWORD,
94 | BSLMethodDescriptionLexer.SPACE,
95 | BSLMethodDescriptionLexer.DOTSWORD,
96 | BSLMethodDescriptionLexer.LPAREN,
97 | BSLMethodDescriptionLexer.RPAREN,
98 | BSLMethodDescriptionLexer.SPACE,
99 | BSLMethodDescriptionLexer.WORD);
100 |
101 | testLexer.assertThat("SEE. ОбщийМодуль.Метод() WORD").containsAll(
102 | BSLMethodDescriptionLexer.SEE_KEYWORD,
103 | BSLMethodDescriptionLexer.ANYSYMBOL,
104 | BSLMethodDescriptionLexer.SPACE,
105 | BSLMethodDescriptionLexer.DOTSWORD,
106 | BSLMethodDescriptionLexer.LPAREN,
107 | BSLMethodDescriptionLexer.RPAREN,
108 | BSLMethodDescriptionLexer.SPACE,
109 | BSLMethodDescriptionLexer.WORD);
110 |
111 | testLexer.assertThat("СМ. ОбщийМодуль.Метод() WORD").containsAll(
112 | BSLMethodDescriptionLexer.SEE_KEYWORD,
113 | BSLMethodDescriptionLexer.SPACE,
114 | BSLMethodDescriptionLexer.DOTSWORD,
115 | BSLMethodDescriptionLexer.LPAREN,
116 | BSLMethodDescriptionLexer.RPAREN,
117 | BSLMethodDescriptionLexer.SPACE,
118 | BSLMethodDescriptionLexer.WORD);
119 | }
120 |
121 | @Test
122 | void testParameters() {
123 | testLexer.assertThat("Параметры").isEqualTo("Parameters").containsAll(BSLMethodDescriptionLexer.WORD);
124 | testLexer.assertThat("NoParameters:")
125 | .containsAll(BSLMethodDescriptionLexer.WORD, BSLMethodDescriptionLexer.COLON);
126 | testLexer.assertThat("Параметры:").isEqualTo("Parameters:")
127 | .containsAll(BSLMethodDescriptionLexer.PARAMETERS_KEYWORD);
128 | testLexer.assertThat("Параметры :")
129 | .containsAll(BSLMethodDescriptionLexer.WORD, BSLMethodDescriptionLexer.SPACE, BSLMethodDescriptionLexer.COLON);
130 | }
131 |
132 | @Test
133 | void testReturns() {
134 | testLexer.assertThat("Возвращаемое значение").containsAll(
135 | BSLMethodDescriptionLexer.WORD,
136 | BSLMethodDescriptionLexer.SPACE,
137 | BSLMethodDescriptionLexer.WORD);
138 | testLexer.assertThat("RETURNS", BSLMethodDescriptionLexer.WORD);
139 | testLexer.assertThat("Возвращаемое значение:")
140 | .isEqualTo("НеВозвращаемое значение:")
141 | .containsAll(
142 | BSLMethodDescriptionLexer.WORD,
143 | BSLMethodDescriptionLexer.SPACE,
144 | BSLMethodDescriptionLexer.WORD,
145 | BSLMethodDescriptionLexer.COLON);
146 | testLexer.assertThat("RETURNS :").containsAll(
147 | BSLMethodDescriptionLexer.WORD,
148 | BSLMethodDescriptionLexer.SPACE,
149 | BSLMethodDescriptionLexer.COLON);
150 | testLexer.assertThat("Возвращаемое значение:").isEqualTo("RETURNS:")
151 | .containsAll(BSLMethodDescriptionLexer.RETURNS_KEYWORD);
152 | testLexer.assertThat("НЕRETURNS:")
153 | .containsAll(BSLMethodDescriptionLexer.WORD, BSLMethodDescriptionLexer.COLON);
154 | }
155 |
156 | @Test
157 | void testExample() {
158 | testLexer.assertThat("Пример")
159 | .isEqualTo("ПримерЫ")
160 | .isEqualTo("Example")
161 | .isEqualTo("Examples")
162 | .containsAll(BSLMethodDescriptionLexer.WORD);
163 |
164 | testLexer.assertThat("Примеры:")
165 | .isEqualTo("Examples:")
166 | .isEqualTo("Пример:")
167 | .isEqualTo("Example:")
168 | .containsAll(BSLMethodDescriptionLexer.EXAMPLE_KEYWORD);
169 |
170 | testLexer.assertThat("Пример :").containsAll(
171 | BSLMethodDescriptionLexer.WORD,
172 | BSLMethodDescriptionLexer.SPACE,
173 | BSLMethodDescriptionLexer.COLON);
174 |
175 | testLexer.assertThat("NoExample:").containsAll(
176 | BSLMethodDescriptionLexer.WORD,
177 | BSLMethodDescriptionLexer.COLON);
178 | }
179 |
180 | @Test
181 | void testCallOptions() {
182 | testLexer.assertThat("Варианты вызова")
183 | .isEqualTo("Call options")
184 | .containsAll(BSLMethodDescriptionLexer.WORD, BSLMethodDescriptionLexer.SPACE, BSLMethodDescriptionLexer.WORD);
185 |
186 | testLexer.assertThat("Варианты вызова:")
187 | .containsAll(
188 | BSLMethodDescriptionLexer.WORD,
189 | BSLMethodDescriptionLexer.SPACE,
190 | BSLMethodDescriptionLexer.WORD,
191 | BSLMethodDescriptionLexer.COLON);
192 |
193 | testLexer.assertThat("Call options :")
194 | .containsAll(
195 | BSLMethodDescriptionLexer.WORD,
196 | BSLMethodDescriptionLexer.SPACE,
197 | BSLMethodDescriptionLexer.WORD,
198 | BSLMethodDescriptionLexer.SPACE,
199 | BSLMethodDescriptionLexer.COLON);
200 |
201 | testLexer.assertThat("Варианты вызова:").isEqualTo("Call options:")
202 | .containsAll(BSLMethodDescriptionLexer.CALL_OPTIONS_KEYWORD);
203 |
204 | testLexer.assertThat("Вариант вызова:").isEqualTo("Call option:")
205 | .containsAll(
206 | BSLMethodDescriptionLexer.WORD,
207 | BSLMethodDescriptionLexer.SPACE,
208 | BSLMethodDescriptionLexer.WORD,
209 | BSLMethodDescriptionLexer.COLON);
210 | }
211 |
212 | @Test
213 | void testDeprecate() {
214 | testLexer.assertThat("Устарела")
215 | .isEqualTo("Deprecate")
216 | .isEqualTo("Устарела.")
217 | .isEqualTo("Deprecate.")
218 | .containsAll(BSLMethodDescriptionLexer.DEPRECATE_KEYWORD);
219 |
220 | testLexer.assertThat("Depricate", BSLMethodDescriptionLexer.WORD);
221 |
222 | testLexer.assertThat("Устарела .").containsAll(
223 | BSLMethodDescriptionLexer.DEPRECATE_KEYWORD,
224 | BSLMethodDescriptionLexer.SPACE,
225 | BSLMethodDescriptionLexer.ANYSYMBOL);
226 |
227 | testLexer.assertThat("Deprecate:").containsAll(
228 | BSLMethodDescriptionLexer.DEPRECATE_KEYWORD,
229 | BSLMethodDescriptionLexer.COLON);
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH="\\\"\\\""
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | if ! command -v java >/dev/null 2>&1
137 | then
138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
139 |
140 | Please set the JAVA_HOME variable in your environment to match the
141 | location of your Java installation."
142 | fi
143 | fi
144 |
145 | # Increase the maximum file descriptors if we can.
146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
147 | case $MAX_FD in #(
148 | max*)
149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
150 | # shellcheck disable=SC2039,SC3045
151 | MAX_FD=$( ulimit -H -n ) ||
152 | warn "Could not query maximum file descriptor limit"
153 | esac
154 | case $MAX_FD in #(
155 | '' | soft) :;; #(
156 | *)
157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
158 | # shellcheck disable=SC2039,SC3045
159 | ulimit -n "$MAX_FD" ||
160 | warn "Could not set maximum file descriptor limit to $MAX_FD"
161 | esac
162 | fi
163 |
164 | # Collect all arguments for the java command, stacking in reverse order:
165 | # * args from the command line
166 | # * the main class name
167 | # * -classpath
168 | # * -D...appname settings
169 | # * --module-path (only if needed)
170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
171 |
172 | # For Cygwin or MSYS, switch paths to Windows format before running java
173 | if "$cygwin" || "$msys" ; then
174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
176 |
177 | JAVACMD=$( cygpath --unix "$JAVACMD" )
178 |
179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
180 | for arg do
181 | if
182 | case $arg in #(
183 | -*) false ;; # don't mess with options #(
184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
185 | [ -e "$t" ] ;; #(
186 | *) false ;;
187 | esac
188 | then
189 | arg=$( cygpath --path --ignore --mixed "$arg" )
190 | fi
191 | # Roll the args list around exactly as many times as the number of
192 | # args, so each arg winds up back in the position where it started, but
193 | # possibly modified.
194 | #
195 | # NB: a `for` loop captures its iteration list before it begins, so
196 | # changing the positional parameters here affects neither the number of
197 | # iterations, nor the values presented in `arg`.
198 | shift # remove old arg
199 | set -- "$@" "$arg" # push replacement arg
200 | done
201 | fi
202 |
203 |
204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
206 |
207 | # Collect all arguments for the java command:
208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
209 | # and any embedded shellness will be escaped.
210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
211 | # treated as '${Hostname}' itself on the command line.
212 |
213 | set -- \
214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
215 | -classpath "$CLASSPATH" \
216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
217 | "$@"
218 |
219 | # Stop when "xargs" is not available.
220 | if ! command -v xargs >/dev/null 2>&1
221 | then
222 | die "xargs is not available"
223 | fi
224 |
225 | # Use "xargs" to parse quoted args.
226 | #
227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
228 | #
229 | # In Bash we could simply go:
230 | #
231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
232 | # set -- "${ARGS[@]}" "$@"
233 | #
234 | # but POSIX shell has neither arrays nor command substitution, so instead we
235 | # post-process each arg (as a line of input to sed) to backslash-escape any
236 | # character that might be a shell metacharacter, then use eval to reverse
237 | # that process (while maintaining the separation between arguments), and wrap
238 | # the whole thing up as a single "set" statement.
239 | #
240 | # This will of course break if any of these variables contains a newline or
241 | # an unmatched quote.
242 | #
243 |
244 | eval "set -- $(
245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
246 | xargs -n1 |
247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
248 | tr '\n' ' '
249 | )" '"$@"'
250 |
251 | exec "$JAVACMD" "$@"
252 |
--------------------------------------------------------------------------------
/src/main/antlr/BSLParser.g4:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright © 2018-2022
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | parser grammar BSLParser;
23 |
24 | options {
25 | tokenVocab = BSLLexer;
26 | incremental = true;
27 | }
28 |
29 | // ROOT
30 | file: shebang? moduleAnnotations? preprocessor* moduleVars? preprocessor* (fileCodeBlockBeforeSub subs)? fileCodeBlock EOF;
31 |
32 | // moduleAnnotations
33 | preproc_native : HASH PREPROC_NATIVE;
34 | usedLib : (PREPROC_STRING | PREPROC_IDENTIFIER);
35 | use : HASH PREPROC_USE_KEYWORD usedLib;
36 |
37 | moduleAnnotations
38 | :
39 | (preproc_native use*)
40 | | (use+ preproc_native? use*)
41 | ;
42 |
43 | // preprocessor
44 | shebang : HASH PREPROC_EXCLAMATION_MARK (PREPROC_ANY | PREPROC_IDENTIFIER)*;
45 |
46 | regionStart : PREPROC_REGION regionName;
47 | regionEnd : PREPROC_END_REGION;
48 | regionName : PREPROC_IDENTIFIER;
49 |
50 | preproc_if : PREPROC_IF_KEYWORD preproc_expression PREPROC_THEN_KEYWORD;
51 | preproc_elsif : PREPROC_ELSIF_KEYWORD preproc_expression PREPROC_THEN_KEYWORD;
52 | preproc_else : PREPROC_ELSE_KEYWORD;
53 | preproc_endif : PREPROC_ENDIF_KEYWORD;
54 |
55 | preproc_expression
56 | : ( PREPROC_NOT_KEYWORD? (PREPROC_LPAREN preproc_expression PREPROC_RPAREN ) )
57 | | preproc_logicalExpression
58 | ;
59 | preproc_logicalOperand
60 | : (PREPROC_LPAREN PREPROC_NOT_KEYWORD? preproc_logicalOperand PREPROC_RPAREN)
61 | | (PREPROC_NOT_KEYWORD? preproc_symbol)
62 | | (PREPROC_LPAREN preproc_logicalExpression PREPROC_RPAREN)
63 | ;
64 | preproc_logicalExpression
65 | : preproc_logicalOperand (preproc_boolOperation preproc_logicalOperand)*
66 | ;
67 | preproc_symbol
68 | : PREPROC_CLIENT_SYMBOL
69 | | PREPROC_ATCLIENT_SYMBOL
70 | | PREPROC_SERVER_SYMBOL
71 | | PREPROC_ATSERVER_SYMBOL
72 | | PREPROC_MOBILEAPPCLIENT_SYMBOL
73 | | PREPROC_MOBILEAPPSERVER_SYMBOL
74 | | PREPROC_MOBILECLIENT_SYMBOL
75 | | PREPROC_THICKCLIENTORDINARYAPPLICATION_SYMBOL
76 | | PREPROC_THICKCLIENTMANAGEDAPPLICATION_SYMBOL
77 | | PREPROC_EXTERNALCONNECTION_SYMBOL
78 | | PREPROC_THINCLIENT_SYMBOL
79 | | PREPROC_WEBCLIENT_SYMBOL
80 | | PREPROC_MOBILE_STANDALONE_SERVER
81 | | PREPROC_LINUX
82 | | PREPROC_WINDOWS
83 | | PREPROC_MACOS
84 | | preproc_unknownSymbol
85 | ;
86 | preproc_unknownSymbol
87 | : PREPROC_IDENTIFIER
88 | ;
89 | preproc_boolOperation
90 | : PREPROC_OR_KEYWORD
91 | | PREPROC_AND_KEYWORD
92 | ;
93 |
94 | preprocessor
95 | : HASH
96 | (regionStart
97 | | regionEnd
98 | | preproc_if
99 | | preproc_elsif
100 | | preproc_else
101 | | preproc_endif
102 | )
103 | ;
104 |
105 | // compiler directives
106 | compilerDirectiveSymbol
107 | : ANNOTATION_ATSERVERNOCONTEXT_SYMBOL
108 | | ANNOTATION_ATCLIENTATSERVERNOCONTEXT_SYMBOL
109 | | ANNOTATION_ATCLIENTATSERVER_SYMBOL
110 | | ANNOTATION_ATCLIENT_SYMBOL
111 | | ANNOTATION_ATSERVER_SYMBOL
112 | ;
113 |
114 | compilerDirective
115 | : AMPERSAND compilerDirectiveSymbol
116 | ;
117 |
118 | // annotations
119 | annotationName
120 | : ANNOTATION_CUSTOM_SYMBOL
121 | | ANNOTATION_BEFORE_SYMBOL
122 | | ANNOTATION_AFTER_SYMBOL
123 | | ANNOTATION_AROUND_SYMBOL
124 | | ANNOTATION_CHANGEANDVALIDATE_SYMBOL
125 | ;
126 | annotationParamName
127 | : IDENTIFIER
128 | ;
129 | annotation
130 | : AMPERSAND annotationName annotationParams?
131 | ;
132 | annotationParams
133 | : LPAREN
134 | (
135 | annotationParam
136 | (COMMA annotationParam)*
137 | )?
138 | RPAREN
139 | ;
140 | annotationParam
141 | : (annotationParamName (ASSIGN annotationParamValue)?)
142 | | annotationParamValue
143 | ;
144 | annotationParamValue
145 | : constValue
146 | | annotation
147 | ;
148 |
149 | // vars
150 | var_name : IDENTIFIER;
151 |
152 | moduleVars : moduleVar+;
153 | moduleVar : (preprocessor | compilerDirective | annotation)* VAR_KEYWORD moduleVarsList SEMICOLON?;
154 | moduleVarsList : moduleVarDeclaration (COMMA moduleVarDeclaration)*;
155 | moduleVarDeclaration: var_name EXPORT_KEYWORD?;
156 |
157 | subVars : subVar+;
158 | subVar : (preprocessor | compilerDirective | annotation)* VAR_KEYWORD subVarsList SEMICOLON?;
159 | subVarsList : subVarDeclaration (COMMA subVarDeclaration)*;
160 | subVarDeclaration: var_name;
161 |
162 | // subs
163 | subName : IDENTIFIER;
164 |
165 | subs : sub+;
166 | sub : procedure | function;
167 | procedure : procDeclaration subCodeBlock ENDPROCEDURE_KEYWORD;
168 | function : funcDeclaration subCodeBlock ENDFUNCTION_KEYWORD;
169 | procDeclaration : (preprocessor | compilerDirective | annotation)* ASYNC_KEYWORD? PROCEDURE_KEYWORD subName LPAREN paramList? RPAREN EXPORT_KEYWORD?;
170 | funcDeclaration : (preprocessor | compilerDirective | annotation)* ASYNC_KEYWORD? FUNCTION_KEYWORD subName LPAREN paramList? RPAREN EXPORT_KEYWORD?;
171 | subCodeBlock : subVars? codeBlock;
172 |
173 | // statements
174 | continueStatement : CONTINUE_KEYWORD;
175 | breakStatement : BREAK_KEYWORD;
176 | raiseStatement : RAISE_KEYWORD (doCall | expression)?;
177 | ifStatement
178 | : ifBranch elsifBranch* elseBranch? ENDIF_KEYWORD
179 | ;
180 | ifBranch
181 | : IF_KEYWORD expression THEN_KEYWORD codeBlock
182 | ;
183 | elsifBranch
184 | : ELSIF_KEYWORD expression THEN_KEYWORD codeBlock
185 | ;
186 | elseBranch
187 | : ELSE_KEYWORD codeBlock
188 | ;
189 | whileStatement : WHILE_KEYWORD expression DO_KEYWORD codeBlock ENDDO_KEYWORD;
190 | forStatement : FOR_KEYWORD IDENTIFIER ASSIGN expression TO_KEYWORD expression DO_KEYWORD codeBlock ENDDO_KEYWORD;
191 | forEachStatement : FOR_KEYWORD EACH_KEYWORD IDENTIFIER IN_KEYWORD expression DO_KEYWORD codeBlock ENDDO_KEYWORD;
192 | tryStatement : TRY_KEYWORD tryCodeBlock EXCEPT_KEYWORD exceptCodeBlock ENDTRY_KEYWORD;
193 | returnStatement : RETURN_KEYWORD expression?;
194 | executeStatement : EXECUTE_KEYWORD (doCall | callParamList);
195 | callStatement : ((IDENTIFIER | globalMethodCall) modifier* accessCall) | globalMethodCall;
196 | waitStatement : waitExpression;
197 |
198 | labelName : IDENTIFIER;
199 | label : TILDA labelName COLON;
200 | gotoStatement : GOTO_KEYWORD TILDA labelName;
201 |
202 | tryCodeBlock : codeBlock;
203 | exceptCodeBlock : codeBlock;
204 |
205 | event
206 | : expression
207 | ;
208 |
209 | handler
210 | : expression
211 | ;
212 | addHandlerStatement
213 | : ADDHANDLER_KEYWORD event COMMA handler
214 | ;
215 | removeHandlerStatement
216 | : REMOVEHANDLER_KEYWORD event COMMA handler
217 | ;
218 |
219 | ternaryOperator : QUESTION LPAREN expression COMMA expression COMMA expression RPAREN;
220 | waitExpression : AWAIT_KEYWORD expression;
221 |
222 | // main
223 | fileCodeBlockBeforeSub
224 | : codeBlock
225 | ;
226 | fileCodeBlock
227 | : codeBlock
228 | ;
229 | codeBlock : (statement | preprocessor)*;
230 | numeric : FLOAT | DECIMAL;
231 | paramList : param (COMMA param)*;
232 | param : (annotation)* VAL_KEYWORD? IDENTIFIER (ASSIGN defaultValue)?;
233 | defaultValue : constValue;
234 | constValue : (MINUS | PLUS)? numeric | string | TRUE | FALSE | UNDEFINED | NULL | DATETIME;
235 | multilineString : STRINGSTART (STRINGPART | BAR | preprocessor)* STRINGTAIL;
236 | string : (STRING | multilineString)+;
237 | statement
238 | : (
239 | (
240 | ( label (callStatement | waitStatement | compoundStatement | assignment | preprocessor)?)
241 | |
242 | (callStatement | waitStatement | compoundStatement | assignment| preprocessor)
243 | )
244 | SEMICOLON?
245 | )
246 | | SEMICOLON
247 | ;
248 | assignment : lValue preprocessor* ASSIGN expression;
249 | callParamList : callParam (COMMA callParam)*;
250 | callParam : expression?;
251 | expression : preprocessor* member (preprocessor* operation preprocessor* member preprocessor*)*;
252 | operation : PLUS | MINUS | MUL | QUOTIENT | MODULO | boolOperation | compareOperation;
253 | compareOperation : LESS | LESS_OR_EQUAL | GREATER | GREATER_OR_EQUAL | ASSIGN | NOT_EQUAL;
254 | boolOperation : OR_KEYWORD | AND_KEYWORD;
255 | unaryModifier : NOT_KEYWORD | MINUS | PLUS;
256 | member
257 | : unaryModifier?
258 | (
259 | constValue
260 | | complexIdentifier
261 | | (( LPAREN expression RPAREN ) modifier*)
262 | | (IDENTIFIER | globalMethodCall)
263 | | waitExpression
264 | );
265 | newExpression : NEW_KEYWORD typeName doCall? | NEW_KEYWORD doCall;
266 | typeName : IDENTIFIER;
267 | methodCall : methodName doCall;
268 | globalMethodCall : methodName doCall;
269 | methodName : IDENTIFIER;
270 | complexIdentifier: (IDENTIFIER | newExpression | ternaryOperator | globalMethodCall) modifier*;
271 | modifier : accessProperty | accessIndex | accessCall;
272 | acceptor : modifier* (accessProperty | accessIndex);
273 | lValue : (IDENTIFIER | globalMethodCall) acceptor?;
274 | accessCall : DOT methodCall;
275 | accessIndex : LBRACK expression RBRACK;
276 | accessProperty : DOT IDENTIFIER;
277 | doCall : LPAREN callParamList RPAREN;
278 |
279 | compoundStatement
280 | : ifStatement
281 | | whileStatement
282 | | forStatement
283 | | forEachStatement
284 | | tryStatement
285 | | returnStatement
286 | | continueStatement
287 | | breakStatement
288 | | raiseStatement
289 | | executeStatement
290 | | gotoStatement
291 | | addHandlerStatement
292 | | removeHandlerStatement
293 | ;
294 |
--------------------------------------------------------------------------------
/src/main/antlr/BSLLexer.g4:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright © 2018-2022
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | lexer grammar BSLLexer;
23 |
24 | channels {
25 | // для хранения удаленного блока
26 | PREPROC_DELETE_CHANNEL
27 | }
28 |
29 | options { caseInsensitive=true; }
30 |
31 | // commons
32 | fragment DIGIT: [0-9];
33 | LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);
34 | WHITE_SPACE: [ \t\f\r\n]+ -> channel(HIDDEN);
35 |
36 | // separators
37 | DOT: '.' -> pushMode(DOT_MODE);
38 | LBRACK: '[';
39 | RBRACK: ']';
40 | LPAREN: '(';
41 | RPAREN: ')';
42 | COLON: ':';
43 | SEMICOLON: ';';
44 | COMMA: ',';
45 | ASSIGN: '=';
46 | PLUS: '+';
47 | MINUS: '-';
48 | LESS_OR_EQUAL: '<=';
49 | NOT_EQUAL: '<>';
50 | LESS: '<';
51 | GREATER_OR_EQUAL: '>=';
52 | GREATER: '>';
53 | MUL: '*';
54 | QUOTIENT: '/';
55 | MODULO: '%';
56 | QUESTION: '?';
57 | AMPERSAND: '&' -> pushMode(ANNOTATION_MODE);
58 | PREPROC_DELETE
59 | : '#' [ \t]* ('УДАЛЕНИЕ' | 'DELETE')
60 | -> pushMode(PREPROC_DELETE_MODE), channel(PREPROC_DELETE_CHANNEL)
61 | ;
62 | PREPROC_INSERT
63 | : '#' [ \t]* ('ВСТАВКА' | 'INSERT')
64 | -> channel(HIDDEN)
65 | ;
66 | PREPROC_ENDINSERT
67 | : '#' [ \t]* ('КОНЕЦВСТАВКИ' | 'ENDINSERT')
68 | -> channel(HIDDEN)
69 | ;
70 | HASH: '#' -> pushMode(PREPROCESSOR_MODE);
71 |
72 | fragment SQUOTE: '\'';
73 | BAR: '|';
74 | TILDA: '~' -> pushMode(LABEL_MODE);
75 |
76 | // literals
77 | TRUE: 'ИСТИНА' | 'TRUE';
78 | FALSE: 'ЛОЖЬ' | 'FALSE';
79 | UNDEFINED: 'НЕОПРЕДЕЛЕНО' | 'UNDEFINED';
80 | NULL: 'NULL';
81 | DECIMAL: DIGIT+;
82 | DATETIME: SQUOTE(~['\n\r])*SQUOTE?; // TODO: Честная регулярка
83 |
84 | FLOAT : DIGIT+ '.' DIGIT*;
85 | STRING: '"' (~[\r\n"] | '""')* '"';
86 | STRINGSTART: '"' (~["\n\r]| '""')*;
87 | STRINGTAIL: BAR (~["\n\r] | '""')* '"';
88 | STRINGPART: BAR (~[\r\n"] | '""')*;
89 |
90 | // keywords
91 | PROCEDURE_KEYWORD: 'ПРОЦЕДУРА' | 'PROCEDURE';
92 | FUNCTION_KEYWORD: 'ФУНКЦИЯ' | 'FUNCTION';
93 | ENDPROCEDURE_KEYWORD: 'КОНЕЦПРОЦЕДУРЫ' | 'ENDPROCEDURE';
94 | ENDFUNCTION_KEYWORD: 'КОНЕЦФУНКЦИИ' | 'ENDFUNCTION';
95 | EXPORT_KEYWORD: 'ЭКСПОРТ' | 'EXPORT';
96 | VAL_KEYWORD: 'ЗНАЧ' | 'VAL';
97 | ENDIF_KEYWORD: 'КОНЕЦЕСЛИ' | 'ENDIF';
98 | ENDDO_KEYWORD: 'КОНЕЦЦИКЛА' | 'ENDDO';
99 | IF_KEYWORD: 'ЕСЛИ' | 'IF';
100 | ELSIF_KEYWORD: 'ИНАЧЕЕСЛИ' | 'ELSIF';
101 | ELSE_KEYWORD: 'ИНАЧЕ' | 'ELSE';
102 | THEN_KEYWORD: 'ТОГДА' | 'THEN';
103 | WHILE_KEYWORD: 'ПОКА' | 'WHILE';
104 | DO_KEYWORD: 'ЦИКЛ' | 'DO';
105 | FOR_KEYWORD: 'ДЛЯ' | 'FOR';
106 | TO_KEYWORD: 'ПО' | 'TO';
107 | EACH_KEYWORD: 'КАЖДОГО' | 'EACH';
108 | IN_KEYWORD: 'ИЗ' | 'IN';
109 | TRY_KEYWORD: 'ПОПЫТКА' | 'TRY';
110 | EXCEPT_KEYWORD: 'ИСКЛЮЧЕНИЕ' | 'EXCEPT';
111 | ENDTRY_KEYWORD: 'КОНЕЦПОПЫТКИ' | 'ENDTRY';
112 | RETURN_KEYWORD: 'ВОЗВРАТ' | 'RETURN';
113 | CONTINUE_KEYWORD: 'ПРОДОЛЖИТЬ' | 'CONTINUE';
114 | RAISE_KEYWORD: 'ВЫЗВАТЬИСКЛЮЧЕНИЕ' | 'RAISE';
115 | VAR_KEYWORD: 'ПЕРЕМ' | 'VAR';
116 | NOT_KEYWORD: 'НЕ' | 'NOT';
117 | OR_KEYWORD: 'ИЛИ' | 'OR';
118 | AND_KEYWORD: 'И' | 'AND';
119 | NEW_KEYWORD: 'НОВЫЙ' | 'NEW';
120 | GOTO_KEYWORD: 'ПЕРЕЙТИ' | 'GOTO';
121 | BREAK_KEYWORD: 'ПРЕРВАТЬ' | 'BREAK';
122 | EXECUTE_KEYWORD: 'ВЫПОЛНИТЬ' | 'EXECUTE';
123 | ADDHANDLER_KEYWORD: 'ДОБАВИТЬОБРАБОТЧИК' | 'ADDHANDLER';
124 | REMOVEHANDLER_KEYWORD: 'УДАЛИТЬОБРАБОТЧИК' | 'REMOVEHANDLER';
125 | ASYNC_KEYWORD: ('АСИНХ' | 'ASYNC') -> pushMode(ASYNC_MODE);
126 |
127 | fragment LETTER: [\p{Letter}] | '_';
128 | IDENTIFIER : LETTER (LETTER | DIGIT)*;
129 |
130 | UNKNOWN: . -> channel(HIDDEN);
131 |
132 | mode PREPROCESSOR_MODE;
133 |
134 | PREPROC_EXCLAMATION_MARK: '!';
135 | PREPROC_LPAREN: LPAREN;
136 | PREPROC_RPAREN: RPAREN;
137 |
138 | PREPROC_STRING: '"' (~["\n\r])* '"';
139 | PREPROC_NATIVE: 'NATIVE';
140 | PREPROC_USE_KEYWORD: ('ИСПОЛЬЗОВАТЬ' | 'USE') -> pushMode(USE_MODE);
141 | PREPROC_REGION: ('ОБЛАСТЬ' | 'REGION') -> pushMode(REGION_MODE);
142 | PREPROC_END_REGION: 'КОНЕЦОБЛАСТИ' | 'ENDREGION';
143 | PREPROC_NOT_KEYWORD: NOT_KEYWORD;
144 | PREPROC_OR_KEYWORD: OR_KEYWORD;
145 | PREPROC_AND_KEYWORD: AND_KEYWORD;
146 | PREPROC_IF_KEYWORD: IF_KEYWORD;
147 | PREPROC_THEN_KEYWORD: THEN_KEYWORD;
148 | PREPROC_ELSIF_KEYWORD: ELSIF_KEYWORD;
149 | PREPROC_ENDIF_KEYWORD: ENDIF_KEYWORD;
150 | PREPROC_ELSE_KEYWORD: ELSE_KEYWORD;
151 |
152 | PREPROC_MOBILEAPPCLIENT_SYMBOL: 'МОБИЛЬНОЕПРИЛОЖЕНИЕКЛИЕНТ' | 'MOBILEAPPCLIENT';
153 | PREPROC_MOBILEAPPSERVER_SYMBOL: 'МОБИЛЬНОЕПРИЛОЖЕНИЕСЕРВЕР' | 'MOBILEAPPSERVER';
154 | PREPROC_MOBILECLIENT_SYMBOL: 'МОБИЛЬНЫЙКЛИЕНТ' | 'MOBILECLIENT';
155 | PREPROC_THICKCLIENTORDINARYAPPLICATION_SYMBOL: 'ТОЛСТЫЙКЛИЕНТОБЫЧНОЕПРИЛОЖЕНИЕ' | 'THICKCLIENTORDINARYAPPLICATION';
156 | PREPROC_THICKCLIENTMANAGEDAPPLICATION_SYMBOL: 'ТОЛСТЫЙКЛИЕНТУПРАВЛЯЕМОЕПРИЛОЖЕНИЕ' | 'THICKCLIENTMANAGEDAPPLICATION';
157 | PREPROC_EXTERNALCONNECTION_SYMBOL: 'ВНЕШНЕЕСОЕДИНЕНИЕ' | 'EXTERNALCONNECTION';
158 | PREPROC_THINCLIENT_SYMBOL: 'ТОНКИЙКЛИЕНТ' | 'THINCLIENT';
159 | PREPROC_WEBCLIENT_SYMBOL: 'ВЕБКЛИЕНТ' | 'WEBCLIENT';
160 | PREPROC_ATCLIENT_SYMBOL: 'НАКЛИЕНТЕ' | 'ATCLIENT';
161 | PREPROC_CLIENT_SYMBOL: 'КЛИЕНТ' | 'CLIENT';
162 | PREPROC_ATSERVER_SYMBOL: 'НАСЕРВЕРЕ' | 'ATSERVER';
163 | PREPROC_SERVER_SYMBOL: 'СЕРВЕР' | 'SERVER';
164 | PREPROC_MOBILE_STANDALONE_SERVER: 'МОБИЛЬНЫЙАВТОНОМНЫЙСЕРВЕР' | 'MOBILESTANDALONESERVER';
165 |
166 | PREPROC_LINUX : 'LINUX';
167 | PREPROC_WINDOWS : 'WINDOWS';
168 | PREPROC_MACOS : 'MACOS';
169 |
170 | PREPROC_IDENTIFIER : IDENTIFIER;
171 |
172 | PREPROC_WHITE_SPACE: [ \t\f]+ -> channel(HIDDEN), type(WHITE_SPACE);
173 | PREPROC_LINE_COMMENT: LINE_COMMENT -> channel(HIDDEN), type(LINE_COMMENT);
174 | PREPROC_NEWLINE: '\r'?'\n' -> popMode, channel(HIDDEN);
175 |
176 | PREPROC_ANY: ~[\r\n];
177 |
178 | mode ANNOTATION_MODE;
179 | ANNOTATION_ATSERVERNOCONTEXT_SYMBOL: ('НАСЕРВЕРЕБЕЗКОНТЕКСТА' | 'ATSERVERNOCONTEXT') -> popMode;
180 | ANNOTATION_ATCLIENTATSERVERNOCONTEXT_SYMBOL: ('НАКЛИЕНТЕНАСЕРВЕРЕБЕЗКОНТЕКСТА' | 'ATCLIENTATSERVERNOCONTEXT') -> popMode;
181 | ANNOTATION_ATCLIENTATSERVER_SYMBOL: ('НАКЛИЕНТЕНАСЕРВЕРЕ' | 'ATCLIENTATSERVER') -> popMode;
182 | ANNOTATION_ATCLIENT_SYMBOL: ('НАКЛИЕНТЕ' | 'ATCLIENT') -> popMode;
183 | ANNOTATION_ATSERVER_SYMBOL: ('НАСЕРВЕРЕ' | 'ATSERVER') -> popMode;
184 | ANNOTATION_BEFORE_SYMBOL: ('ПЕРЕД' | 'BEFORE') -> popMode;
185 | ANNOTATION_AFTER_SYMBOL: ('ПОСЛЕ' | 'AFTER') -> popMode;
186 | ANNOTATION_AROUND_SYMBOL: ('ВМЕСТО' | 'AROUND') -> popMode;
187 | ANNOTATION_CHANGEANDVALIDATE_SYMBOL: ('ИЗМЕНЕНИЕИКОНТРОЛЬ' | 'CHANGEANDVALIDATE') -> popMode;
188 | ANNOTATION_CUSTOM_SYMBOL: IDENTIFIER -> popMode;
189 | ANNOTATION_WHITE_SPACE: WHITE_SPACE -> channel(HIDDEN), type(WHITE_SPACE);
190 | ANNOTATION_UNKNOWN: UNKNOWN -> channel(HIDDEN);
191 |
192 | mode LABEL_MODE;
193 | LABEL_IDENTIFIER : IDENTIFIER -> type(IDENTIFIER), popMode;
194 |
195 | mode REGION_MODE;
196 | REGION_WHITE_SPACE: PREPROC_WHITE_SPACE -> channel(HIDDEN), type(WHITE_SPACE);
197 | REGION_IDENTIFIER : IDENTIFIER -> type(PREPROC_IDENTIFIER), popMode;
198 |
199 | mode USE_MODE;
200 | fragment USE_LETTER: LETTER | '-';
201 | USE_WHITE_SPACE: PREPROC_WHITE_SPACE -> channel(HIDDEN), type(WHITE_SPACE);
202 | USE_STRING : PREPROC_STRING -> type(PREPROC_STRING), popMode;
203 | USE_IDENTIFIER : ( USE_LETTER | DIGIT )+ -> type(PREPROC_IDENTIFIER), popMode;
204 |
205 | mode DOT_MODE;
206 | DOT_WHITE_SPACE: PREPROC_WHITE_SPACE -> channel(HIDDEN), type(WHITE_SPACE);
207 | DOT_IDENTIFIER : IDENTIFIER -> type(IDENTIFIER), popMode;
208 |
209 | mode PREPROC_DELETE_MODE;
210 | PREPROC_ENDDELETE
211 | : '#' [ \t]* ('КОНЕЦУДАЛЕНИЯ' | 'ENDDELETE')
212 | -> popMode, channel(PREPROC_DELETE_CHANNEL);
213 | PREPROC_DELETE_WHITE_SPACE: PREPROC_WHITE_SPACE -> channel(HIDDEN), type(WHITE_SPACE);
214 | PREPROC_DELETE_LINE_COMMENT: LINE_COMMENT -> channel(HIDDEN), type(LINE_COMMENT);
215 | PREPROC_DELETE_NEWLINE: PREPROC_NEWLINE -> channel(HIDDEN), type(PREPROC_NEWLINE);
216 | PREPROC_DELETE_ANY: . -> channel(PREPROC_DELETE_CHANNEL);
217 |
218 | mode ASYNC_MODE;
219 | Async_LINE_COMMENT: LINE_COMMENT -> type(LINE_COMMENT), channel(HIDDEN);
220 | Async_WHITE_SPACE: WHITE_SPACE -> type(WHITE_SPACE), channel(HIDDEN);
221 |
222 | // separators
223 | Async_DOT: DOT -> type(DOT), pushMode(DOT_MODE);
224 | Async_LBRACK: LBRACK -> type(LBRACK);
225 | Async_RBRACK: RBRACK -> type(RBRACK);
226 | Async_LPAREN: LPAREN -> type(LPAREN);
227 | Async_RPAREN: RPAREN -> type(RPAREN);
228 | Async_COLON: COLON -> type(COLON);
229 | Async_SEMICOLON: SEMICOLON -> type(SEMICOLON);
230 | Async_COMMA: COMMA -> type(COMMA);
231 | Async_ASSIGN: ASSIGN -> type(ASSIGN);
232 | Async_PLUS: PLUS -> type(PLUS);
233 | Async_MINUS: MINUS -> type(MINUS);
234 | Async_LESS_OR_EQUAL: LESS_OR_EQUAL -> type(LESS_OR_EQUAL);
235 | Async_NOT_EQUAL: NOT_EQUAL -> type(NOT_EQUAL);
236 | Async_LESS: LESS -> type(LESS);
237 | Async_GREATER_OR_EQUAL: GREATER_OR_EQUAL -> type(GREATER_OR_EQUAL);
238 | Async_GREATER: GREATER -> type(GREATER);
239 | Async_MUL: MUL -> type(MUL);
240 | Async_QUOTIENT: QUOTIENT -> type(QUOTIENT);
241 | Async_MODULO: MODULO -> type(MODULO);
242 | Async_QUESTION: QUESTION -> type(QUESTION);
243 | Async_AMPERSAND: AMPERSAND -> type(AMPERSAND), pushMode(ANNOTATION_MODE);
244 | Async_PREPROC_DELETE: PREPROC_DELETE ->
245 | type(PREPROC_DELETE),
246 | pushMode(PREPROC_DELETE_MODE),
247 | channel(PREPROC_DELETE_CHANNEL);
248 | Async_PREPROC_INSERT: PREPROC_INSERT -> type(PREPROC_INSERT), channel(HIDDEN);
249 | Async_PREPROC_ENDINSERT: PREPROC_ENDINSERT -> type(PREPROC_ENDINSERT), channel(HIDDEN);
250 |
251 | Async_HASH: HASH -> type(HASH), pushMode(PREPROCESSOR_MODE);
252 | Async_BAR: BAR -> type(BAR);
253 | Async_TILDA: TILDA -> type(TILDA), pushMode(LABEL_MODE);
254 |
255 | // literals
256 | Async_TRUE: TRUE -> type(TRUE);
257 | Async_FALSE: FALSE -> type(FALSE);
258 | Async_UNDEFINED: UNDEFINED -> type(UNDEFINED);
259 | Async_NULL: NULL -> type(NULL);
260 | Async_DECIMAL: DECIMAL -> type(DECIMAL);
261 | Async_DATETIME: DATETIME -> type(DATETIME);
262 | Async_FLOAT: FLOAT -> type(FLOAT);
263 | Async_STRING: STRING -> type(STRING);
264 | Async_STRINGSTART: STRINGSTART -> type(STRINGSTART);
265 | Async_STRINGTAIL: STRINGTAIL -> type(STRINGTAIL);
266 | Async_STRINGPART: STRINGPART -> type(STRINGPART);
267 |
268 | // keywords
269 | Async_PROCEDURE_KEYWORD: PROCEDURE_KEYWORD -> type(PROCEDURE_KEYWORD);
270 | Async_FUNCTION_KEYWORD: FUNCTION_KEYWORD -> type(FUNCTION_KEYWORD);
271 | Async_ENDPROCEDURE_KEYWORD: ENDPROCEDURE_KEYWORD -> type(ENDPROCEDURE_KEYWORD), popMode;
272 | Async_ENDFUNCTION_KEYWORD: ENDFUNCTION_KEYWORD -> type(ENDFUNCTION_KEYWORD), popMode;
273 | Async_EXPORT_KEYWORD: EXPORT_KEYWORD -> type(EXPORT_KEYWORD);
274 | Async_VAL_KEYWORD: VAL_KEYWORD -> type(VAL_KEYWORD);
275 | Async_ENDIF_KEYWORD: ENDIF_KEYWORD -> type(ENDIF_KEYWORD);
276 | Async_ENDDO_KEYWORD: ENDDO_KEYWORD -> type(ENDDO_KEYWORD);
277 | Async_IF_KEYWORD: IF_KEYWORD -> type(IF_KEYWORD);
278 | Async_ELSIF_KEYWORD: ELSIF_KEYWORD -> type(ELSIF_KEYWORD);
279 | Async_ELSE_KEYWORD: ELSE_KEYWORD -> type(ELSE_KEYWORD);
280 | Async_THEN_KEYWORD: THEN_KEYWORD -> type(THEN_KEYWORD);
281 | Async_WHILE_KEYWORD: WHILE_KEYWORD -> type(WHILE_KEYWORD);
282 | Async_DO_KEYWORD: DO_KEYWORD -> type(DO_KEYWORD);
283 | Async_FOR_KEYWORD: FOR_KEYWORD -> type(FOR_KEYWORD);
284 | Async_TO_KEYWORD: TO_KEYWORD -> type(TO_KEYWORD);
285 | Async_EACH_KEYWORD: EACH_KEYWORD -> type(EACH_KEYWORD);
286 | Async_IN_KEYWORD: IN_KEYWORD -> type(IN_KEYWORD);
287 | Async_TRY_KEYWORD: TRY_KEYWORD -> type(TRY_KEYWORD);
288 | Async_EXCEPT_KEYWORD: EXCEPT_KEYWORD -> type(EXCEPT_KEYWORD);
289 | Async_ENDTRY_KEYWORD: ENDTRY_KEYWORD -> type(ENDTRY_KEYWORD);
290 | Async_RETURN_KEYWORD: RETURN_KEYWORD -> type(RETURN_KEYWORD);
291 | Async_CONTINUE_KEYWORD: CONTINUE_KEYWORD -> type(CONTINUE_KEYWORD);
292 | Async_RAISE_KEYWORD: RAISE_KEYWORD -> type(RAISE_KEYWORD);
293 | Async_VAR_KEYWORD: VAR_KEYWORD -> type(VAR_KEYWORD);
294 | Async_NOT_KEYWORD: NOT_KEYWORD -> type(NOT_KEYWORD);
295 | Async_OR_KEYWORD: OR_KEYWORD -> type(OR_KEYWORD);
296 | Async_AND_KEYWORD: AND_KEYWORD -> type(AND_KEYWORD);
297 | Async_NEW_KEYWORD: NEW_KEYWORD -> type(NEW_KEYWORD);
298 | Async_GOTO_KEYWORD: GOTO_KEYWORD -> type(GOTO_KEYWORD);
299 | Async_BREAK_KEYWORD: BREAK_KEYWORD -> type(BREAK_KEYWORD);
300 | Async_EXECUTE_KEYWORD: EXECUTE_KEYWORD -> type(EXECUTE_KEYWORD);
301 | Async_ADDHANDLER_KEYWORD: ADDHANDLER_KEYWORD -> type(ADDHANDLER_KEYWORD);
302 | Async_REMOVEHANDLER_KEYWORD: REMOVEHANDLER_KEYWORD -> type(REMOVEHANDLER_KEYWORD);
303 |
304 | AWAIT_KEYWORD: 'ЖДАТЬ' | 'AWAIT';
305 |
306 | // всегда в конце мода
307 | Async_IDENTIFIER: IDENTIFIER -> type(IDENTIFIER);
308 | Async_UNKNOWN: UNKNOWN -> type(UNKNOWN);
309 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLParserCheckSourceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import com.github._1c_syntax.bsl.parser.testing.TestParser;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.api.Test;
27 |
28 | class SDBLParserCheckSourceTest {
29 |
30 | private TestParser testParser;
31 |
32 | @BeforeEach
33 | void before() {
34 | testParser = new TestParser<>(SDBLParser.class, SDBLLexer.class);
35 | }
36 |
37 | @Test
38 | void testDrop() {
39 | testParser.assertThatFile("sdbl/drop.sdbl")
40 | .containsRule(SDBLParser.RULE_queries, 3)
41 | .containsRule(SDBLParser.RULE_dropTableQuery, 3)
42 | .containsRule(SDBLParser.RULE_selectQuery, 0)
43 | .containsRule(SDBLParser.RULE_identifier, 3);
44 | }
45 |
46 | @Test
47 | void testSelect01() {
48 | testParser.assertThatFile("sdbl/select01.sdbl")
49 | .containsRule(SDBLParser.RULE_queries, 1)
50 | .containsRule(SDBLParser.RULE_dropTableQuery, 0)
51 | .containsRule(SDBLParser.RULE_selectQuery, 1)
52 | .containsRule(SDBLParser.RULE_identifier, 68)
53 | .containsRule(SDBLParser.RULE_subquery, 1)
54 | .containsRule(SDBLParser.RULE_union, 0)
55 | .containsRule(SDBLParser.RULE_query, 1)
56 | .containsRule(SDBLParser.RULE_limitations, 0)
57 | .containsRule(SDBLParser.RULE_top, 0)
58 | .containsRule(SDBLParser.RULE_selectedFields, 1)
59 | .containsRule(SDBLParser.RULE_selectedField, 1)
60 | .containsRule(SDBLParser.RULE_columnField, 0)
61 | .containsRule(SDBLParser.RULE_emptyTableField, 0)
62 | .containsRule(SDBLParser.RULE_emptyTableColumns, 0)
63 | .containsRule(SDBLParser.RULE_inlineTableField, 0)
64 | .containsRule(SDBLParser.RULE_recordAutoNumberFunction, 0)
65 | .containsRule(SDBLParser.RULE_groupByItem, 0)
66 | .containsRule(SDBLParser.RULE_indexingItem, 0)
67 | .containsRule(SDBLParser.RULE_orderBy, 0)
68 | .containsRule(SDBLParser.RULE_ordersByExpession, 0)
69 | .containsRule(SDBLParser.RULE_totalBy, 0)
70 | .containsRule(SDBLParser.RULE_totalsGroup, 0)
71 | .containsRule(SDBLParser.RULE_periodic, 0)
72 | .containsRule(SDBLParser.RULE_column, 30)
73 | .containsRule(SDBLParser.RULE_expression, 103)
74 | .containsRule(SDBLParser.RULE_primitiveExpression, 49)
75 | .containsRule(SDBLParser.RULE_caseExpression, 0)
76 | .containsRule(SDBLParser.RULE_caseBranch, 0)
77 | .containsRule(SDBLParser.RULE_bracketExpression, 0)
78 | .containsRule(SDBLParser.RULE_unaryExpression, 24)
79 | .containsRule(SDBLParser.RULE_functionCall, 0)
80 | .containsRule(SDBLParser.RULE_builtInFunctions, 0)
81 | .containsRule(SDBLParser.RULE_aggregateFunctions, 0)
82 | .containsRule(SDBLParser.RULE_valueFunction, 0)
83 | .containsRule(SDBLParser.RULE_castFunction, 0)
84 | .containsRule(SDBLParser.RULE_logicalExpression, 5)
85 | .containsRule(SDBLParser.RULE_predicate, 29)
86 | .containsRule(SDBLParser.RULE_expressionList, 0)
87 | .containsRule(SDBLParser.RULE_dataSources, 1)
88 | .containsRule(SDBLParser.RULE_dataSource, 3)
89 | .containsRule(SDBLParser.RULE_table, 2)
90 | .containsRule(SDBLParser.RULE_virtualTable, 1)
91 | .containsRule(SDBLParser.RULE_parameterTable, 0)
92 | .containsRule(SDBLParser.RULE_joinPart, 2)
93 | .containsRule(SDBLParser.RULE_alias, 4)
94 | .containsRule(SDBLParser.RULE_datePart, 0)
95 | .containsRule(SDBLParser.RULE_multiString, 0)
96 | .containsRule(SDBLParser.RULE_sign, 24)
97 | .containsRule(SDBLParser.RULE_parameter, 48)
98 | .containsRule(SDBLParser.RULE_mdo, 1)
99 | .containsRule(SDBLParser.RULE_likePredicate, 0)
100 | .containsRule(SDBLParser.RULE_comparePredicate, 3)
101 | .containsRule(SDBLParser.RULE_betweenPredicate, 24)
102 | .containsRule(SDBLParser.RULE_inPredicate, 0)
103 | .containsRule(SDBLParser.RULE_refsPredicate, 0);
104 | }
105 |
106 | @Test
107 | void testSelect02() {
108 | testParser.assertThatFile("sdbl/select02.sdbl")
109 | .containsRule(SDBLParser.RULE_queries, 1)
110 | .containsRule(SDBLParser.RULE_dropTableQuery, 0)
111 | .containsRule(SDBLParser.RULE_selectQuery, 1)
112 | .containsRule(SDBLParser.RULE_identifier, 15)
113 | .containsRule(SDBLParser.RULE_subquery, 2)
114 | .containsRule(SDBLParser.RULE_union, 0)
115 | .containsRule(SDBLParser.RULE_query, 2)
116 | .containsRule(SDBLParser.RULE_limitations, 0)
117 | .containsRule(SDBLParser.RULE_top, 0)
118 | .containsRule(SDBLParser.RULE_selectedFields, 2)
119 | .containsRule(SDBLParser.RULE_selectedField, 3)
120 | .containsRule(SDBLParser.RULE_columnField, 0)
121 | .containsRule(SDBLParser.RULE_emptyTableField, 0)
122 | .containsRule(SDBLParser.RULE_emptyTableColumns, 0)
123 | .containsRule(SDBLParser.RULE_inlineTableField, 0)
124 | .containsRule(SDBLParser.RULE_recordAutoNumberFunction, 0)
125 | .containsRule(SDBLParser.RULE_groupByItem, 0)
126 | .containsRule(SDBLParser.RULE_indexingItem, 0)
127 | .containsRule(SDBLParser.RULE_orderBy, 0)
128 | .containsRule(SDBLParser.RULE_ordersByExpession, 0)
129 | .containsRule(SDBLParser.RULE_totalBy, 0)
130 | .containsRule(SDBLParser.RULE_totalsGroup, 0)
131 | .containsRule(SDBLParser.RULE_periodic, 0)
132 | .containsRule(SDBLParser.RULE_column, 9)
133 | .containsRule(SDBLParser.RULE_expression, 13)
134 | .containsRule(SDBLParser.RULE_primitiveExpression, 3)
135 | .containsRule(SDBLParser.RULE_caseExpression, 0)
136 | .containsRule(SDBLParser.RULE_caseBranch, 0)
137 | .containsRule(SDBLParser.RULE_bracketExpression, 0)
138 | .containsRule(SDBLParser.RULE_unaryExpression, 0)
139 | .containsRule(SDBLParser.RULE_functionCall, 1)
140 | .containsRule(SDBLParser.RULE_builtInFunctions, 0)
141 | .containsRule(SDBLParser.RULE_aggregateFunctions, 1)
142 | .containsRule(SDBLParser.RULE_valueFunction, 0)
143 | .containsRule(SDBLParser.RULE_castFunction, 0)
144 | .containsRule(SDBLParser.RULE_logicalExpression, 14)
145 | .containsRule(SDBLParser.RULE_predicate, 14)
146 | .containsRule(SDBLParser.RULE_expressionList, 3)
147 | .containsRule(SDBLParser.RULE_dataSources, 2)
148 | .containsRule(SDBLParser.RULE_dataSource, 2)
149 | .containsRule(SDBLParser.RULE_table, 1)
150 | .containsRule(SDBLParser.RULE_virtualTable, 1)
151 | .containsRule(SDBLParser.RULE_parameterTable, 0)
152 | .containsRule(SDBLParser.RULE_joinPart, 0)
153 | .containsRule(SDBLParser.RULE_alias, 1)
154 | .containsRule(SDBLParser.RULE_datePart, 0)
155 | .containsRule(SDBLParser.RULE_multiString, 0)
156 | .containsRule(SDBLParser.RULE_sign, 0)
157 | .containsRule(SDBLParser.RULE_parameter, 3)
158 | .containsRule(SDBLParser.RULE_mdo, 2)
159 | .containsRule(SDBLParser.RULE_likePredicate, 0)
160 | .containsRule(SDBLParser.RULE_comparePredicate, 1)
161 | .containsRule(SDBLParser.RULE_betweenPredicate, 0)
162 | .containsRule(SDBLParser.RULE_inPredicate, 2)
163 | .containsRule(SDBLParser.RULE_refsPredicate, 0);
164 | }
165 |
166 | @Test
167 | void testSelect03() {
168 | testParser.assertThatFile("sdbl/select03.sdbl")
169 | .containsRule(SDBLParser.RULE_queries, 1)
170 | .containsRule(SDBLParser.RULE_dropTableQuery, 0)
171 | .containsRule(SDBLParser.RULE_selectQuery, 1)
172 | .containsRule(SDBLParser.RULE_identifier, 12)
173 | .containsRule(SDBLParser.RULE_subquery, 1)
174 | .containsRule(SDBLParser.RULE_union, 0)
175 | .containsRule(SDBLParser.RULE_query, 1)
176 | .containsRule(SDBLParser.RULE_limitations, 0)
177 | .containsRule(SDBLParser.RULE_top, 0)
178 | .containsRule(SDBLParser.RULE_selectedFields, 1)
179 | .containsRule(SDBLParser.RULE_selectedField, 4)
180 | .containsRule(SDBLParser.RULE_columnField, 0)
181 | .containsRule(SDBLParser.RULE_emptyTableField, 0)
182 | .containsRule(SDBLParser.RULE_emptyTableColumns, 0)
183 | .containsRule(SDBLParser.RULE_inlineTableField, 0)
184 | .containsRule(SDBLParser.RULE_recordAutoNumberFunction, 0)
185 | .containsRule(SDBLParser.RULE_groupByItem, 0)
186 | .containsRule(SDBLParser.RULE_indexingItem, 0)
187 | .containsRule(SDBLParser.RULE_orderBy, 0)
188 | .containsRule(SDBLParser.RULE_ordersByExpession, 0)
189 | .containsRule(SDBLParser.RULE_totalBy, 0)
190 | .containsRule(SDBLParser.RULE_totalsGroup, 0)
191 | .containsRule(SDBLParser.RULE_periodic, 0)
192 | .containsRule(SDBLParser.RULE_column, 4)
193 | .containsRule(SDBLParser.RULE_expression, 5)
194 | .containsRule(SDBLParser.RULE_primitiveExpression, 0)
195 | .containsRule(SDBLParser.RULE_caseExpression, 0)
196 | .containsRule(SDBLParser.RULE_caseBranch, 0)
197 | .containsRule(SDBLParser.RULE_bracketExpression, 0)
198 | .containsRule(SDBLParser.RULE_unaryExpression, 0)
199 | .containsRule(SDBLParser.RULE_functionCall, 1)
200 | .containsRule(SDBLParser.RULE_builtInFunctions, 1)
201 | .containsRule(SDBLParser.RULE_aggregateFunctions, 0)
202 | .containsRule(SDBLParser.RULE_valueFunction, 0)
203 | .containsRule(SDBLParser.RULE_castFunction, 0)
204 | .containsRule(SDBLParser.RULE_logicalExpression, 4)
205 | .containsRule(SDBLParser.RULE_predicate, 4)
206 | .containsRule(SDBLParser.RULE_expressionList, 0)
207 | .containsRule(SDBLParser.RULE_dataSources, 1)
208 | .containsRule(SDBLParser.RULE_dataSource, 1)
209 | .containsRule(SDBLParser.RULE_table, 1)
210 | .containsRule(SDBLParser.RULE_virtualTable, 0)
211 | .containsRule(SDBLParser.RULE_parameterTable, 0)
212 | .containsRule(SDBLParser.RULE_joinPart, 0)
213 | .containsRule(SDBLParser.RULE_alias, 2)
214 | .containsRule(SDBLParser.RULE_datePart, 0)
215 | .containsRule(SDBLParser.RULE_multiString, 0)
216 | .containsRule(SDBLParser.RULE_sign, 0)
217 | .containsRule(SDBLParser.RULE_parameter, 0)
218 | .containsRule(SDBLParser.RULE_mdo, 1)
219 | .containsRule(SDBLParser.RULE_likePredicate, 0)
220 | .containsRule(SDBLParser.RULE_comparePredicate, 0)
221 | .containsRule(SDBLParser.RULE_betweenPredicate, 0)
222 | .containsRule(SDBLParser.RULE_inPredicate, 0)
223 | .containsRule(SDBLParser.RULE_refsPredicate, 0);
224 | }
225 |
226 | @Test
227 | void testSelect04() {
228 | testParser.assertThatFile("sdbl/select04.sdbl")
229 | .containsRule(SDBLParser.RULE_queries, 1)
230 | .containsRule(SDBLParser.RULE_dropTableQuery, 0)
231 | .containsRule(SDBLParser.RULE_selectQuery, 1)
232 | .containsRule(SDBLParser.RULE_identifier, 16)
233 | .containsRule(SDBLParser.RULE_subquery, 2)
234 | .containsRule(SDBLParser.RULE_union, 0)
235 | .containsRule(SDBLParser.RULE_query, 2)
236 | .containsRule(SDBLParser.RULE_limitations, 1)
237 | .containsRule(SDBLParser.RULE_top, 1)
238 | .containsRule(SDBLParser.RULE_selectedFields, 2)
239 | .containsRule(SDBLParser.RULE_selectedField, 2)
240 | .containsRule(SDBLParser.RULE_columnField, 0)
241 | .containsRule(SDBLParser.RULE_emptyTableField, 0)
242 | .containsRule(SDBLParser.RULE_emptyTableColumns, 0)
243 | .containsRule(SDBLParser.RULE_inlineTableField, 0)
244 | .containsRule(SDBLParser.RULE_recordAutoNumberFunction, 0)
245 | .containsRule(SDBLParser.RULE_groupByItem, 0)
246 | .containsRule(SDBLParser.RULE_indexingItem, 0)
247 | .containsRule(SDBLParser.RULE_orderBy, 1)
248 | .containsRule(SDBLParser.RULE_ordersByExpession, 1)
249 | .containsRule(SDBLParser.RULE_totalBy, 0)
250 | .containsRule(SDBLParser.RULE_totalsGroup, 0)
251 | .containsRule(SDBLParser.RULE_periodic, 0)
252 | .containsRule(SDBLParser.RULE_column, 5)
253 | .containsRule(SDBLParser.RULE_expression, 5)
254 | .containsRule(SDBLParser.RULE_primitiveExpression, 0)
255 | .containsRule(SDBLParser.RULE_caseExpression, 0)
256 | .containsRule(SDBLParser.RULE_caseBranch, 0)
257 | .containsRule(SDBLParser.RULE_bracketExpression, 0)
258 | .containsRule(SDBLParser.RULE_unaryExpression, 0)
259 | .containsRule(SDBLParser.RULE_functionCall, 0)
260 | .containsRule(SDBLParser.RULE_builtInFunctions, 0)
261 | .containsRule(SDBLParser.RULE_aggregateFunctions, 0)
262 | .containsRule(SDBLParser.RULE_valueFunction, 0)
263 | .containsRule(SDBLParser.RULE_castFunction, 0)
264 | .containsRule(SDBLParser.RULE_logicalExpression, 4)
265 | .containsRule(SDBLParser.RULE_predicate, 4)
266 | .containsRule(SDBLParser.RULE_expressionList, 0)
267 | .containsRule(SDBLParser.RULE_dataSources, 2)
268 | .containsRule(SDBLParser.RULE_dataSource, 2)
269 | .containsRule(SDBLParser.RULE_table, 2)
270 | .containsRule(SDBLParser.RULE_virtualTable, 0)
271 | .containsRule(SDBLParser.RULE_parameterTable, 0)
272 | .containsRule(SDBLParser.RULE_joinPart, 0)
273 | .containsRule(SDBLParser.RULE_alias, 4)
274 | .containsRule(SDBLParser.RULE_datePart, 0)
275 | .containsRule(SDBLParser.RULE_multiString, 0)
276 | .containsRule(SDBLParser.RULE_sign, 0)
277 | .containsRule(SDBLParser.RULE_parameter, 0)
278 | .containsRule(SDBLParser.RULE_mdo, 2)
279 | .containsRule(SDBLParser.RULE_likePredicate, 0)
280 | .containsRule(SDBLParser.RULE_comparePredicate, 0)
281 | .containsRule(SDBLParser.RULE_betweenPredicate, 0)
282 | .containsRule(SDBLParser.RULE_inPredicate, 1)
283 | .containsRule(SDBLParser.RULE_refsPredicate, 0);
284 | }
285 |
286 | @Test
287 | void testSelect05() {
288 | testParser.assertThatFile("sdbl/select05.sdbl")
289 | .containsRule(SDBLParser.RULE_queries, 1)
290 | .containsRule(SDBLParser.RULE_selectedField, 4)
291 | .containsRule(SDBLParser.RULE_builtInFunctions, 4);
292 | }
293 |
294 | @Test
295 | void testSelect06() {
296 | testParser.assertThatFile("sdbl/select06.sdbl")
297 | .containsRule(SDBLParser.RULE_queries, 4)
298 | .containsRule(SDBLParser.RULE_dataSource, 4);
299 | }
300 |
301 | @Test
302 | void testSelect07() {
303 | testParser.assertThatFile("sdbl/select07.sdbl")
304 | .containsRule(SDBLParser.RULE_queries, 1)
305 | .containsRule(SDBLParser.RULE_dataSource, 1);
306 | }
307 |
308 | @Test
309 | void testSelect08() {
310 | testParser.assertThatFile("sdbl/select08.sdbl")
311 | .containsRule(SDBLParser.RULE_queries, 1)
312 | .containsRule(SDBLParser.RULE_dataSource, 1)
313 | .containsRule(SDBLParser.RULE_builtInFunctions, 35);
314 | }
315 | }
316 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLLexerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import com.github._1c_syntax.bsl.parser.testing.TestLexer;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.api.Test;
27 |
28 | class SDBLLexerTest {
29 | private TestLexer testLexer;
30 |
31 | @BeforeEach
32 | void before() {
33 | testLexer = new TestLexer<>(SDBLLexer.class);
34 | }
35 |
36 | @Test
37 | void testWhitespaces() {
38 | var inputString = " А";
39 | testLexer.assertThat(SDBLLexer.DEFAULT_MODE, inputString)
40 | .containsExactly(SDBLLexer.WHITE_SPACE, SDBLLexer.IDENTIFIER, SDBLLexer.EOF);
41 | }
42 |
43 | @Test
44 | void testKeyWords() {
45 | testLexer.assertThat("ИСТиНА").isEqualTo("TRuE").containsAll(SDBLLexer.TRUE);
46 | testLexer.assertThat("ЛоЖЬ").isEqualTo("FaLSE").containsAll(SDBLLexer.FALSE);
47 | testLexer.assertThat("НеопределенО").isEqualTo("UNDEFINeD").containsAll(SDBLLexer.UNDEFINED);
48 | testLexer.assertThat("NUlL").containsAll(SDBLLexer.NULL);
49 |
50 | testLexer.assertThat("Автоупорядочивание").isEqualTo("AUTOORDEr").containsAll(SDBLLexer.AUTOORDER);
51 | testLexer.assertThat("Булево").isEqualTo("Boolean").containsAll(SDBLLexer.BOOLEAN);
52 | testLexer.assertThat("В").isEqualTo("IN").containsAll(SDBLLexer.IN);
53 | testLexer.assertThat("ВОЗр").isEqualTo("aSC").containsAll(SDBLLexer.ASC);
54 | testLexer.assertThat("ВыБОР").isEqualTo("CAsE").containsAll(SDBLLexer.CASE);
55 | testLexer.assertThat("ВЫБРАТь").isEqualTo("SELECt").containsAll(SDBLLexer.SELECT);
56 | testLexer.assertThat("ВЫРАзИТЬ").isEqualTo("CAST").containsAll(SDBLLexer.CAST);
57 | testLexer.assertThat("ГДЕ").isEqualTo("WHERE").containsAll(SDBLLexer.WHERE);
58 | testLexer.assertThat("ГОД").isEqualTo("YEAR").containsAll(SDBLLexer.YEAR);
59 | testLexer.assertThat("ДАТА").isEqualTo("DATE").containsAll(SDBLLexer.DATE);
60 | testLexer.assertThat("ДАТАВРЕМЯ").isEqualTo("DATETIME").containsAll(SDBLLexer.DATETIME);
61 | testLexer.assertThat("ДЕКАДА").isEqualTo("TENDAYS").containsAll(SDBLLexer.TENDAYS);
62 | testLexer.assertThat("ДЕНЬ").isEqualTo("DAY").containsAll(SDBLLexer.DAY);
63 | testLexer.assertThat("ДЕНЬГОДА").isEqualTo("DAYOFYEAR").containsAll(SDBLLexer.DAYOFYEAR);
64 | testLexer.assertThat("ДЕНЬНЕДЕЛИ").isEqualTo("WEEKDAY").containsAll(SDBLLexer.WEEKDAY);
65 | testLexer.assertThat("ДЛЯ ИЗМЕНЕНИЯ")
66 | .isEqualTo("FOR UPDATE").containsAll(SDBLLexer.FOR, SDBLLexer.UPDATE);
67 | testLexer.assertThat("FOR UPDATE OF").containsAll(SDBLLexer.FOR, SDBLLexer.UPDATE, SDBLLexer.OF);
68 | testLexer.assertThat("ДОБАВИТЬКДАТЕ").isEqualTo("DATEADD").containsAll(SDBLLexer.DATEADD);
69 | testLexer.assertThat("ЕСТЬ").isEqualTo("IS").containsAll(SDBLLexer.IS);
70 | testLexer.assertThat("ЕСТЬNULL").isEqualTo("ISNULL").containsAll(SDBLLexer.ISNULL);
71 | testLexer.assertThat("Значение").isEqualTo("VALUE").containsAll(SDBLLexer.VALUE);
72 | testLexer.assertThat("И").isEqualTo("AND").containsAll(SDBLLexer.AND);
73 | testLexer.assertThat("HIERARCHY").containsAll(SDBLLexer.HIERARCHY);
74 | testLexer.assertThat("ИЕРАРХИЯ").containsAll(SDBLLexer.HIERARCHY);
75 | testLexer.assertThat("ИЗ").isEqualTo("FROM").containsAll(SDBLLexer.FROM);
76 | testLexer.assertThat("ИЛИ").isEqualTo("Or").containsAll(SDBLLexer.OR);
77 | testLexer.assertThat("ИМЕЮЩИЕ").isEqualTo("HAVING").containsAll(SDBLLexer.HAVING);
78 | testLexer.assertThat("ИНАЧЕ").isEqualTo("ELSE").containsAll(SDBLLexer.ELSE);
79 | testLexer.assertThat("ИНДЕКСИРОВАТЬ BY")
80 | .isEqualTo("INDEX BY").containsAll(SDBLLexer.INDEX, SDBLLexer.BY_EN);
81 | testLexer.assertThat("ИТОГИ").isEqualTo("TOTALS").containsAll(SDBLLexer.TOTALS);
82 | testLexer.assertThat("КАК").isEqualTo("AS").containsAll(SDBLLexer.AS);
83 | testLexer.assertThat("КВАРТАЛ").isEqualTo("QUARTER").containsAll(SDBLLexer.QUARTER);
84 | testLexer.assertThat("КОГДА").isEqualTo("WHEN").containsAll(SDBLLexer.WHEN);
85 | testLexer.assertThat("КОЛИЧЕСТВО").isEqualTo("COUNT").containsAll(SDBLLexer.COUNT);
86 | testLexer.assertThat("КОНЕЦПЕРИОДА").isEqualTo("ENDOFPERIOD").containsAll(SDBLLexer.ENDOFPERIOD);
87 | testLexer.assertThat("КОНЕЦ").isEqualTo("END").containsAll(SDBLLexer.END);
88 | testLexer.assertThat("МАКСИМУМ").isEqualTo("MAX").containsAll(SDBLLexer.MAX);
89 | testLexer.assertThat("МЕЖДУ").isEqualTo("BETWEEN").containsAll(SDBLLexer.BETWEEN);
90 | testLexer.assertThat("МЕСЯЦ").isEqualTo("MONTH").containsAll(SDBLLexer.MONTH);
91 | testLexer.assertThat("МИНИМУМ").isEqualTo("MIN").containsAll(SDBLLexer.MIN);
92 | testLexer.assertThat("МИНУТА").isEqualTo("MINUTE").containsAll(SDBLLexer.MINUTE);
93 | testLexer.assertThat("НАЧАЛОПЕРИОДА").isEqualTo("BEGINOFPERIOD").containsAll(SDBLLexer.BEGINOFPERIOD);
94 | testLexer.assertThat("НЕ").isEqualTo("Not").containsAll(SDBLLexer.NOT);
95 | testLexer.assertThat("НЕДЕЛЯ").isEqualTo("WEEK").containsAll(SDBLLexer.WEEK);
96 | testLexer.assertThat("ОБЩИЕ").isEqualTo("OVERALL").containsAll(SDBLLexer.OVERALL);
97 | testLexer.assertThat("ОБЪЕДИНИТЬ").isEqualTo("UNION").containsAll(SDBLLexer.UNION);
98 | testLexer.assertThat("ПЕРВЫЕ").isEqualTo("TOP").containsAll(SDBLLexer.TOP);
99 | testLexer.assertThat("ПЕРИОДАМИ").isEqualTo("PERIODS").containsAll(SDBLLexer.PERIODS);
100 | testLexer.assertThat("ПОДОБНО").isEqualTo("LIKE").containsAll(SDBLLexer.LIKE);
101 | testLexer.assertThat("ПОЛУГОДИЕ").isEqualTo("HALFYEAR").containsAll(SDBLLexer.HALFYEAR);
102 | testLexer.assertThat("ПОМЕСТИТЬ").isEqualTo("INTO").containsAll(SDBLLexer.INTO);
103 | testLexer.assertThat("ПРАВОЕ JOIN")
104 | .isEqualTo("RIGHT JOIN").containsAll(SDBLLexer.RIGHT, SDBLLexer.JOIN);
105 | testLexer.assertThat("ПРЕДСТАВЛЕНИЕ").isEqualTo("PRESENTATION").containsAll(SDBLLexer.PRESENTATION);
106 | testLexer.assertThat("ПУСТАЯТАБЛИЦА").isEqualTo("EMPTYTABLE").containsAll(SDBLLexer.EMPTYTABLE);
107 | testLexer.assertThat("РАЗЛИЧНЫЕ").isEqualTo("DISTINCT").containsAll(SDBLLexer.DISTINCT);
108 | testLexer.assertThat("РАЗРЕШЕННЫЕ").isEqualTo("ALLOWED").containsAll(SDBLLexer.ALLOWED);
109 | testLexer.assertThat("Сгруппировать По").containsAll(SDBLLexer.GROUP, SDBLLexer.PO_RU);
110 | testLexer.assertThat("GROUP BY").containsAll(SDBLLexer.GROUP, SDBLLexer.BY_EN);
111 | testLexer.assertThat("СЕКУНДА").isEqualTo("SECOND").containsAll(SDBLLexer.SECOND);
112 | testLexer.assertThat("СОЕДИНЕНИЕ ПО").containsAll(SDBLLexer.JOIN, SDBLLexer.PO_RU);
113 | testLexer.assertThat("JOIN ON").containsAll(SDBLLexer.JOIN, SDBLLexer.ON_EN);
114 | testLexer.assertThat("СПЕЦСИМВОЛ").isEqualTo("ESCAPE").containsAll(SDBLLexer.ESCAPE);
115 | testLexer.assertThat("ПОДСТРОКА").isEqualTo("SUBSTRING").containsAll(SDBLLexer.SUBSTRING);
116 | testLexer.assertThat("СРЕДНЕЕ").isEqualTo("AVG").containsAll(SDBLLexer.AVG);
117 | testLexer.assertThat("ССЫЛКА").isEqualTo("REFS").containsAll(SDBLLexer.REFS);
118 | testLexer.assertThat("СТРОКА").isEqualTo("STRING").containsAll(SDBLLexer.STRING);
119 | testLexer.assertThat("СУММА").isEqualTo("SUM").containsAll(SDBLLexer.SUM);
120 | testLexer.assertThat("ТИП").isEqualTo("TYPE").containsAll(SDBLLexer.TYPE);
121 | testLexer.assertThat("ТИПЗНАЧЕНИЯ").isEqualTo("VALUETYPE").containsAll(SDBLLexer.VALUETYPE);
122 | testLexer.assertThat("ТОГДА").isEqualTo("THEN").containsAll(SDBLLexer.THEN);
123 | testLexer.assertThat("ТОЛЬКО").isEqualTo("ONLY").containsAll(SDBLLexer.ONLY);
124 | testLexer.assertThat("УБЫВ").isEqualTo("DESC").containsAll(SDBLLexer.DESC);
125 | testLexer.assertThat("УПОРЯДОЧИТЬ ПО")
126 | .isEqualTo("ORDER ПО").containsAll(SDBLLexer.ORDER, SDBLLexer.PO_RU);
127 | testLexer.assertThat("ЧАС").isEqualTo("HOUR").containsAll(SDBLLexer.HOUR);
128 | testLexer.assertThat("ЧИСЛО").isEqualTo("NUMBER").containsAll(SDBLLexer.NUMBER);
129 | testLexer.assertThat("УНИЧТОЖИТЬ").isEqualTo("DROP").containsAll(SDBLLexer.DROP);
130 |
131 | testLexer.assertThat("РазностьДат").isEqualTo("DateDiff").containsAll(SDBLLexer.DATEDIFF);
132 | testLexer.assertThat("автономерзаписи")
133 | .isEqualTo("RECORDAUTONUMBER").containsAll(SDBLLexer.RECORDAUTONUMBER);
134 |
135 | }
136 |
137 | @Test
138 | void testKeyWordsP2() {
139 | testLexer.assertThat("ЦЕЛ").isEqualTo("int").containsAll(SDBLLexer.INT);
140 | testLexer.assertThat("ACOS").isEqualTo("ACOs").containsAll(SDBLLexer.ACOS);
141 | testLexer.assertThat("ASIN").isEqualTo("ASIn").containsAll(SDBLLexer.ASIN);
142 | testLexer.assertThat("ATAN").isEqualTo("ATaN").containsAll(SDBLLexer.ATAN);
143 | testLexer.assertThat("COS").isEqualTo("cOS").containsAll(SDBLLexer.COS);
144 | testLexer.assertThat("SIN").isEqualTo("SiN").containsAll(SDBLLexer.SIN);
145 | testLexer.assertThat("TAN").isEqualTo("TAn").containsAll(SDBLLexer.TAN);
146 | testLexer.assertThat("LOG").isEqualTo("LOg").containsAll(SDBLLexer.LOG);
147 | testLexer.assertThat("LOG10").isEqualTo("loG10").containsAll(SDBLLexer.LOG10);
148 | testLexer.assertThat("EXP").isEqualTo("EXp").containsAll(SDBLLexer.EXP);
149 | testLexer.assertThat("POW").isEqualTo("POw").containsAll(SDBLLexer.POW);
150 | testLexer.assertThat("SQRT").isEqualTo("SqRT").containsAll(SDBLLexer.SQRT);
151 | testLexer.assertThat("LOWER").isEqualTo("Нрег").containsAll(SDBLLexer.LOWER);
152 | testLexer.assertThat("STRINGLENGTH").isEqualTo("ДлинаСТроки").containsAll(SDBLLexer.STRINGLENGTH);
153 | testLexer.assertThat("TRIMALL").isEqualTo("Сокрлп").containsAll(SDBLLexer.TRIMALL);
154 | testLexer.assertThat("TRIML").isEqualTo("Сокрл").containsAll(SDBLLexer.TRIML);
155 | testLexer.assertThat("TRIMR").isEqualTo("СокрП").containsAll(SDBLLexer.TRIMR);
156 | testLexer.assertThat("UPPER").isEqualTo("вреГ").containsAll(SDBLLexer.UPPER);
157 | testLexer.assertThat("ROUND").isEqualTo("окр").containsAll(SDBLLexer.ROUND);
158 | testLexer.assertThat("STOREDDATASIZE")
159 | .isEqualTo("РазмерХранимыхДанных").containsAll(SDBLLexer.STOREDDATASIZE);
160 | testLexer.assertThat("UUID").isEqualTo("УникальныйиДентификатор").containsAll(SDBLLexer.UUID);
161 | testLexer.assertThat("STRFIND").isEqualTo("стрнайТи").containsAll(SDBLLexer.STRFIND);
162 | testLexer.assertThat("STRREPLACE").isEqualTo("стрЗАМЕнить").containsAll(SDBLLexer.STRREPLACE);
163 | }
164 |
165 | @Test
166 | void testStandardFields() {
167 | testLexer.assertThat("ТочкаМаршрута").isEqualTo("RoutePoint").containsAll(SDBLLexer.ROUTEPOINT_FIELD);
168 | }
169 |
170 | @Test
171 | void testMDOTypes() {
172 | testLexer.assertThat("БизнесПроцесс")
173 | .isEqualTo("BusinessProcess").containsAll(SDBLLexer.BUSINESS_PROCESS_TYPE);
174 | testLexer.assertThat("Справочник").isEqualTo("Catalog").containsAll(SDBLLexer.CATALOG_TYPE);
175 | testLexer.assertThat("ДОкумент").isEqualTo("Document").containsAll(SDBLLexer.DOCUMENT_TYPE);
176 | testLexer.assertThat("РегистрСведений")
177 | .isEqualTo("InformationRegister").containsAll(SDBLLexer.INFORMATION_REGISTER_TYPE);
178 | testLexer.assertThat("Константа").isEqualTo("Constant").containsAll(SDBLLexer.CONSTANT_TYPE);
179 | testLexer.assertThat("КритерийОтбора")
180 | .isEqualTo("FilterCriterion").containsAll(SDBLLexer.FILTER_CRITERION_TYPE);
181 | testLexer.assertThat("ПланОбмена").isEqualTo("ExchangePlan").containsAll(SDBLLexer.EXCHANGE_PLAN_TYPE);
182 | testLexer.assertThat("Последовательность").isEqualTo("SEQUENCE").containsAll(SDBLLexer.SEQUENCE_TYPE);
183 | testLexer.assertThat("ЖурналДокументов")
184 | .isEqualTo("DocumentJournal").containsAll(SDBLLexer.DOCUMENT_JOURNAL_TYPE);
185 | testLexer.assertThat("Перечисление").isEqualTo("Enum").containsAll(SDBLLexer.ENUM_TYPE);
186 | testLexer.assertThat("ПланВидовХарактеристик")
187 | .isEqualTo("ChartOfCharacteristicTypes").containsAll(SDBLLexer.CHART_OF_CHARACTERISTIC_TYPES_TYPE);
188 | testLexer.assertThat("ПланСчетов").isEqualTo("ChartOfAccounts").containsAll(SDBLLexer.CHART_OF_ACCOUNTS_TYPE);
189 | testLexer.assertThat("ПланВидоВРасчета")
190 | .isEqualTo("ChartOfCalculationTypes").containsAll(SDBLLexer.CHART_OF_CALCULATION_TYPES_TYPE);
191 | testLexer.assertThat("РегистрНакопления")
192 | .isEqualTo("AccumulationRegister").containsAll(SDBLLexer.ACCUMULATION_REGISTER_TYPE);
193 | testLexer.assertThat("РегистрБухгалтерии")
194 | .isEqualTo("AccountingRegister").containsAll(SDBLLexer.ACCOUNTING_REGISTER_TYPE);
195 | testLexer.assertThat("РегистрРасчета")
196 | .isEqualTo("CalculationRegister").containsAll(SDBLLexer.CALCULATION_REGISTER_TYPE);
197 | testLexer.assertThat("Задача").isEqualTo("Task").containsAll(SDBLLexer.TASK_TYPE);
198 | testLexer.assertThat("ВнешнийИсточникДанных")
199 | .isEqualTo("ExternalDataSource").containsAll(SDBLLexer.EXTERNAL_DATA_SOURCE_TYPE);
200 | }
201 |
202 | @Test
203 | void testMDOTT() {
204 | testLexer.assertThat(".СрезПоследних")
205 | .isEqualTo(".SLICELAST").containsAll(SDBLLexer.DOT, SDBLLexer.SLICELAST_VT);
206 | testLexer.assertThat(".СрезПервых")
207 | .isEqualTo(".SLICEFIRST").containsAll(SDBLLexer.DOT, SDBLLexer.SLICEFIRST_VT);
208 | testLexer.assertThat(".Границы")
209 | .isEqualTo(".BOUNDARIES").containsAll(SDBLLexer.DOT, SDBLLexer.BOUNDARIES_VT);
210 | testLexer.assertThat(".Обороты")
211 | .isEqualTo(".TURNOVERS").containsAll(SDBLLexer.DOT, SDBLLexer.TURNOVERS_VT);
212 | testLexer.assertThat(".Остатки")
213 | .isEqualTo(".BALANCE").containsAll(SDBLLexer.DOT, SDBLLexer.BALANCE_VT);
214 | testLexer.assertThat(".ОстаткиИОбороты")
215 | .isEqualTo(".BALANCEANDTURNOVERS").containsAll(SDBLLexer.DOT, SDBLLexer.BALANCE_AND_TURNOVERS_VT);
216 | testLexer.assertThat(".Субконто")
217 | .isEqualTo(".EXTDIMENSIONS").containsAll(SDBLLexer.DOT, SDBLLexer.EXT_DIMENSIONS_VT);
218 | testLexer.assertThat(".Движенияссубконто")
219 | .isEqualTo(".RECORDSWITHEXTDIMENSIONS").containsAll(SDBLLexer.DOT, SDBLLexer.RECORDS_WITH_EXT_DIMENSIONS_VT);
220 | testLexer.assertThat(".ОборотыДтКт")
221 | .isEqualTo(".DrCrTURNOVERS").containsAll(SDBLLexer.DOT, SDBLLexer.DR_CR_TURNOVERS_VT);
222 | testLexer.assertThat(".ФактическийПериодДействия")
223 | .isEqualTo(".ACTUALACTIONPERIOD").containsAll(SDBLLexer.DOT, SDBLLexer.ACTUAL_ACTION_PERIOD_VT);
224 | testLexer.assertThat(".ДанныеГрафика")
225 | .isEqualTo(".SCHEDULEDATA").containsAll(SDBLLexer.DOT, SDBLLexer.SCHEDULE_DATA_VT);
226 | testLexer.assertThat(".ЗадачиПоИсполнителю")
227 | .isEqualTo(".TASKBYPERFORMER").containsAll(SDBLLexer.DOT, SDBLLexer.TASK_BY_PERFORMER_VT);
228 | }
229 |
230 | @Test
231 | void testExternalTypes() {
232 | testLexer.assertThat("ВнешнийИсточникДанных.ВИД1.Таблица")
233 | .isEqualTo("ExternalDataSource.EDS1.Table")
234 | .containsAll(
235 | SDBLLexer.EXTERNAL_DATA_SOURCE_TYPE,
236 | SDBLLexer.DOT,
237 | SDBLLexer.IDENTIFIER,
238 | SDBLLexer.DOT,
239 | SDBLLexer.EDS_TABLE);
240 | testLexer.assertThat("ВнешнийИсточникДанных.ВИД1.Куб.Куб1.ТаблицаИзмерения")
241 | .isEqualTo("ExternalDataSource.EDS1.Cube.Cube1.DimensionTable")
242 | .containsAll(
243 | SDBLLexer.EXTERNAL_DATA_SOURCE_TYPE,
244 | SDBLLexer.DOT,
245 | SDBLLexer.IDENTIFIER,
246 | SDBLLexer.DOT,
247 | SDBLLexer.EDS_CUBE,
248 | SDBLLexer.DOT,
249 | SDBLLexer.IDENTIFIER,
250 | SDBLLexer.DOT,
251 | SDBLLexer.EDS_CUBE_DIMTABLE);
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/test/java/com/github/_1c_syntax/bsl/parser/BSLParserWithChildrenTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is a part of BSL Parser.
3 | *
4 | * Copyright (c) 2018-2025
5 | * Alexey Sosnoviy , Nikita Fedkin , Sergey Batanov
6 | *
7 | * SPDX-License-Identifier: LGPL-3.0-or-later
8 | *
9 | * BSL Parser is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 3.0 of the License, or (at your option) any later version.
13 | *
14 | * BSL Parser is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with BSL Parser.
21 | */
22 | package com.github._1c_syntax.bsl.parser;
23 |
24 | import com.github._1c_syntax.bsl.parser.testing.TestParser;
25 | import org.junit.jupiter.api.BeforeEach;
26 | import org.junit.jupiter.api.Test;
27 | import org.junit.jupiter.params.ParameterizedTest;
28 | import org.junit.jupiter.params.provider.ValueSource;
29 |
30 | import static org.assertj.core.api.Assertions.assertThat;
31 |
32 | class BSLParserWithChildrenTest {
33 |
34 | private TestParser testParser;
35 |
36 | @BeforeEach
37 | void before() {
38 | testParser = new TestParser<>(BSLParser.class, BSLLexer.class);
39 | }
40 |
41 | @Test
42 | void testPreproc_Expression() {
43 | var content = testParser.assertThat("#Если (Клиент Или (НЕ Клиент)) И НЕ Клиент Тогда\n" +
44 | "#ИначеЕсли ((((Не (ВебКлиент))) И ((НЕ МобильныйКлиент)))) Тогда\n" +
45 | "#КонецЕсли");
46 |
47 | var file = testParser.parser().file();
48 | content.matches(file);
49 |
50 | var preprocessors = file.preprocessor();
51 | assertThat(preprocessors).isNotNull().hasSize(3);
52 |
53 | var preproc_if = preprocessors.get(0);
54 | var preproc_elif = preprocessors.get(1);
55 | var preproc_endif = preprocessors.get(2);
56 | content.matches(preproc_if.preproc_if());
57 | content.matches(preproc_if.preproc_if().preproc_expression());
58 | content.matches(preproc_elif.preproc_elsif());
59 | content.matches(preproc_elif.preproc_elsif().preproc_expression());
60 | content.matches(preproc_endif.preproc_endif());
61 |
62 | // в выражении условия все есть логическое условие
63 | var preproc_exp = preproc_if.preproc_if().preproc_expression().preproc_logicalExpression();
64 | content.matches(preproc_exp);
65 | // логическое условие содержит два операнда
66 | assertThat(preproc_exp.preproc_logicalOperand()).isNotNull().hasSize(2);
67 |
68 | var preproc_exp_inside = preproc_exp.preproc_logicalOperand(0);
69 | assertThat(preproc_exp_inside).isNotNull();
70 | // первый операнд это тоже логическое условие
71 | content.matches(preproc_exp_inside.preproc_logicalExpression());
72 | }
73 |
74 | @Test
75 | void testDeletePreproc() {
76 | var content = testParser.assertThat("""
77 | &ИзменениеИКонтроль("ПроверитьЗавершитьДоговорВАрхиве")
78 | Функция ХФ164150_ПроверитьЗавершитьДоговорВАрхиве(ДоговорОбъект, ДопНастройки, ИмяРеквизитаДатаОкончания)
79 | \tТекущаяДата = НачалоДня(ТекущаяДатаСеанса());
80 | \t#Удаление
81 | \tЕсли СтароеУсловие
82 | \t#КонецУдаления
83 | \t#Вставка
84 | \tНовоеУсловие = Выражение;
85 | \tЕсли НовоеУсловие
86 | \t#КонецВставки
87 | \t\tИ ЧастьСтарогоУсловия Тогда
88 | \t\t Возврат Истина;
89 | \tКонецЕсли;
90 | \tВозврат Ложь;
91 | КонецФункции""");
92 |
93 | var file = testParser.parser().file();
94 | content.matches(file);
95 |
96 | var subs = file.subs();
97 | content.matches(subs);
98 |
99 | var listSubs = subs.sub();
100 | listSubs.forEach(content::matches);
101 |
102 | var func = listSubs.get(0);
103 | content.matches(func);
104 |
105 | assertThat(func.getText())
106 | .doesNotContain("#Удаление")
107 | .doesNotContain("#КонецУдаления")
108 | .doesNotContain("#ЕслиСтароеУсловие")
109 | .doesNotContain("#Вставка")
110 | .doesNotContain("#КонецВставки")
111 | .contains("ИЧастьСтарогоУсловияТогда")
112 | ;
113 | }
114 |
115 | @ParameterizedTest
116 | @ValueSource(strings =
117 | {
118 | """
119 | &ИзменениеИКонтроль("Тест")
120 | Асинх Функция Тест(Параметры)
121 | \tВозврат Ложь;
122 | КонецФункции""",
123 | """
124 | &НаКлиенте
125 | Асинх Процедура Тест(Параметры)
126 | \tВозврат;
127 | КонецПроцедуры"""
128 | }
129 | )
130 | void testAsync(String inputString) {
131 | var content = testParser.assertThat(inputString);
132 |
133 | var file = testParser.parser().file();
134 | content.matches(file);
135 |
136 | var subs = file.subs();
137 | content.matches(subs);
138 |
139 | var listSubs = subs.sub();
140 | listSubs.forEach(content::matches);
141 |
142 | var method = listSubs.get(0);
143 | content.matches(method);
144 |
145 | if (method.function() == null) {
146 | var procDeclare = method.procedure().procDeclaration();
147 | content.matches(procDeclare.ASYNC_KEYWORD());
148 | } else {
149 | var funcDeclare = method.function().funcDeclaration();
150 | content.matches(funcDeclare.ASYNC_KEYWORD());
151 | }
152 | }
153 |
154 | @Test
155 | void testWait() {
156 | var content = testParser.assertThat("""
157 | Асинх Процедура Test()
158 | Ждать КопироватьФайлыАсинх(ИсходныйКаталог, ЦелевойКаталог); //1 \s
159 | КопироватьФайлы(ИсходныйКаталог, ЦелевойКаталог); //1 \s
160 | Файлы = Ждать НайтиФайлыАсинх(ИсхКаталог, "*", Ложь); //2
161 | Сч = Ждать КопироватьФайлыАсинх(ИсходныйКаталог, ЦелевойКаталог); //1
162 | Об = КопироватьФайлАсинх(ИсхФайл, ЦелФайл);\s
163 | Ждать Об;
164 | если Ждать Об тогда\s
165 | возврат;
166 | конецесли;
167 | если Ждать мояФункция(а) тогда\s
168 | возврат;
169 | конецесли;
170 | EndProcedure""");
171 |
172 | var file = testParser.parser().file();
173 | content.matches(file);
174 |
175 | var subs = file.subs();
176 | content.matches(subs);
177 |
178 | var listSubs = subs.sub();
179 | listSubs.forEach(content::matches);
180 |
181 | var proc = listSubs.get(0);
182 | content.matches(proc);
183 |
184 | var subCodeblock = proc.procedure().subCodeBlock();
185 | content.matches(subCodeblock);
186 |
187 | var codeBlock = subCodeblock.codeBlock();
188 | content.matches(codeBlock);
189 |
190 | var statements = codeBlock.statement();
191 | statements.forEach(content::matches);
192 | assertThat(statements.stream().filter(statementContext -> statementContext.callStatement() != null))
193 | .hasSize(1);
194 | assertThat(statements.stream().filter(statementContext -> statementContext.waitStatement() != null))
195 | .hasSize(2);
196 | }
197 |
198 | @Test
199 | void testAnotherWait() {
200 | var content = testParser.assertThat("""
201 | Асинх Функция Test()
202 | Ждать 1; \s
203 | Ждать (Ждать 1);\s
204 | Существует = Ждать ФайлНаДиске.СуществуетАсинх();
205 | Возврат Ждать (Ждать 1) + Ждать (Ждать 2);\s
206 | КонецФункции""");
207 |
208 | var file = testParser.parser().file();
209 | content.matches(file);
210 |
211 | var codeBlockContext = file.subs().sub(0).function().subCodeBlock().codeBlock();
212 |
213 | content.matches(codeBlockContext.statement(0).waitStatement());
214 | content.matches(codeBlockContext.statement(1).waitStatement());
215 | content.matches(codeBlockContext.statement(2).assignment());
216 | content.matches(codeBlockContext.statement(3).compoundStatement().returnStatement().expression().member(0)
217 | .waitExpression());
218 | }
219 |
220 | @Test
221 | void testNoWait() {
222 | var content = testParser.assertThat("""
223 | Процедура Test(Парам1, Ждать, wAit)
224 | Ждать = КопироватьФайлыАсинх(ИсходныйКаталог, ЦелевойКаталог, Ждать, wait); //1 \s
225 | если Ждать тогда\s
226 | возврат;
227 | конецесли;
228 | если Ждать > мояФункция(а) тогда\s
229 | возврат;
230 | конецесли;
231 | EndProcedure""");
232 |
233 | var file = testParser.parser().file();
234 | content.matches(file);
235 |
236 | var subs = file.subs();
237 | content.matches(subs);
238 |
239 | var listSubs = subs.sub();
240 | listSubs.forEach(content::matches);
241 |
242 | var proc = listSubs.get(0);
243 | content.matches(proc);
244 |
245 | var param = proc.procedure().procDeclaration().paramList().param(1);
246 | content.matches(param);
247 |
248 | var subCodeblock = proc.procedure().subCodeBlock();
249 | content.matches(subCodeblock);
250 |
251 | var codeBlock = subCodeblock.codeBlock();
252 | content.matches(codeBlock);
253 |
254 | var statements = codeBlock.statement();
255 | statements.forEach(content::matches);
256 | }
257 |
258 | @Test
259 | void testAnnotateParams() {
260 | var content = testParser.assertThat("""
261 | Процедура САннотированнымиПараметрами(
262 | \t
263 | \t&АннотацияДляПараметра
264 | \tЗнач Парам1,
265 |
266 | \t&АннотацияДляПараметра
267 | \t&АннотацияДляПараметра1
268 | \t&АннотацияДляПараметра2(СПараметрами = 3, 4, 5)
269 | \tЗнач Парам2,
270 |
271 | \tПарам3,
272 | \tПарам4 = Неопределено
273 | ) Экспорт
274 |
275 | КонецПроцедуры""");
276 |
277 | var file = testParser.parser().file();
278 | content.matches(file);
279 | assertThat(file.subs()).isNotNull();
280 | assertThat(file.subs().sub()).isNotNull().hasSize(1);
281 |
282 | var sub = file.subs().sub(0);
283 | content.matches(sub.procedure());
284 | content.matches(sub.procedure().procDeclaration());
285 | assertThat(sub.procedure().procDeclaration().paramList()).isNotNull();
286 | assertThat(sub.procedure().procDeclaration().paramList().param()).isNotNull().hasSize(4);
287 |
288 | var param1 = sub.procedure().procDeclaration().paramList().param(0);
289 | assertThat(param1.annotation()).isNotNull().hasSize(1);
290 |
291 | var param2 = sub.procedure().procDeclaration().paramList().param(1);
292 | assertThat(param2.annotation()).isNotNull().hasSize(3);
293 |
294 | var annotation2 = param2.annotation().get(2);
295 | assertThat(annotation2.annotationParams()).isNotNull();
296 | assertThat(annotation2.annotationParams().annotationParam()).isNotNull().hasSize(3);
297 | }
298 |
299 | @Test
300 | void testNestedAnnotations() {
301 | var content = testParser.assertThat("""
302 | &ДляКаждого(
303 | Значение = &Тип("Строка"),
304 | &Тип("Число", &Длина(10))
305 | )
306 | Перем Параметр;""");
307 |
308 | var file = testParser.parser().file();
309 | content.matches(file);
310 | assertThat(file.moduleVars()).isNotNull();
311 | assertThat(file.moduleVars().moduleVar())
312 | .isNotNull()
313 | .hasSize(1);
314 |
315 | var moduleVar = file.moduleVars().moduleVar(0);
316 | assertThat(moduleVar.annotation())
317 | .isNotNull()
318 | .hasSize(1);
319 |
320 | var mainAnnotation = moduleVar.annotation().get(0);
321 | assertThat(mainAnnotation.annotationParams()).isNotNull();
322 | assertThat(mainAnnotation.annotationParams().annotationParam())
323 | .isNotNull()
324 | .hasSize(2);
325 |
326 | // First param: Значение = &Тип("Строка")
327 | var param1 = mainAnnotation.annotationParams().annotationParam(0);
328 | assertThat(param1.annotationParamName()).isNotNull();
329 | assertThat(param1.annotationParamValue()).isNotNull();
330 | assertThat(param1.annotationParamValue().annotation()).isNotNull();
331 |
332 | // Second param: &Тип("Число", &Длина(10))
333 | var param2 = mainAnnotation.annotationParams().annotationParam(1);
334 | assertThat(param2.annotationParamValue()).isNotNull();
335 | assertThat(param2.annotationParamValue().annotation()).isNotNull();
336 | var nestedAnnotation = param2.annotationParamValue().annotation();
337 | assertThat(nestedAnnotation.annotationParams()).isNotNull();
338 | assertThat(nestedAnnotation.annotationParams().annotationParam())
339 | .isNotNull()
340 | .hasSize(2);
341 |
342 | // Check that the second param of the nested annotation is also an annotation
343 | var nestedParam2 = nestedAnnotation.annotationParams().annotationParam(1);
344 | assertThat(nestedParam2.annotationParamValue()).isNotNull();
345 | assertThat(nestedParam2.annotationParamValue().annotation()).isNotNull();
346 | }
347 |
348 | @Test
349 | void testNestedAnnotationsInMethodDeclaration() {
350 | var content = testParser.assertThat("""
351 | &Аннотация(&Тип("Строка"))
352 | Процедура Метод()
353 | КонецПроцедуры""");
354 |
355 | var file = testParser.parser().file();
356 | content.matches(file);
357 | assertThat(file.subs()).isNotNull();
358 | assertThat(file.subs().sub())
359 | .isNotNull()
360 | .hasSize(1);
361 |
362 | var sub = file.subs().sub(0);
363 | var procDeclaration = sub.procedure().procDeclaration();
364 | assertThat(procDeclaration.annotation())
365 | .isNotNull()
366 | .hasSize(1);
367 |
368 | var annotation = procDeclaration.annotation().get(0);
369 | assertThat(annotation.annotationParams()).isNotNull();
370 | assertThat(annotation.annotationParams().annotationParam())
371 | .isNotNull()
372 | .hasSize(1);
373 |
374 | var param = annotation.annotationParams().annotationParam(0);
375 | assertThat(param.annotationParamValue()).isNotNull();
376 | assertThat(param.annotationParamValue().annotation()).isNotNull();
377 | }
378 |
379 | @Test
380 | void testNestedAnnotationsInMethodParameter() {
381 | var content = testParser.assertThat("""
382 | Процедура Метод(
383 | &Тип(&Строка())
384 | Парам1
385 | )
386 | КонецПроцедуры""");
387 |
388 | var file = testParser.parser().file();
389 | content.matches(file);
390 | assertThat(file.subs()).isNotNull();
391 | assertThat(file.subs().sub())
392 | .isNotNull()
393 | .hasSize(1);
394 |
395 | var sub = file.subs().sub(0);
396 | var procDeclaration = sub.procedure().procDeclaration();
397 | assertThat(procDeclaration.paramList()).isNotNull();
398 | assertThat(procDeclaration.paramList().param())
399 | .isNotNull()
400 | .hasSize(1);
401 |
402 | var param = procDeclaration.paramList().param(0);
403 | assertThat(param.annotation())
404 | .isNotNull()
405 | .hasSize(1);
406 |
407 | var annotation = param.annotation().get(0);
408 | assertThat(annotation.annotationParams()).isNotNull();
409 | assertThat(annotation.annotationParams().annotationParam())
410 | .isNotNull()
411 | .hasSize(1);
412 |
413 | var annotationParam = annotation.annotationParams().annotationParam(0);
414 | assertThat(annotationParam.annotationParamValue()).isNotNull();
415 | assertThat(annotationParam.annotationParamValue().annotation()).isNotNull();
416 | }
417 |
418 | @Test
419 | void testRaise() {
420 | var content = testParser.assertThat("ВызватьИсключение (\"Документ не может быть проведен\", " +
421 | "КатегорияОшибки.ОшибкаКонфигурации, " +
422 | "\"ERR.DOCS.0001\", " +
423 | "\"Клиенту запрещена отгрузка\");");
424 |
425 | var file = testParser.parser().file();
426 | content.matches(file);
427 | assertThat(file.fileCodeBlock()).isNotNull();
428 | assertThat(file.fileCodeBlock().codeBlock()).isNotNull();
429 | assertThat(file.fileCodeBlock().codeBlock().statement()).isNotNull().hasSize(1);
430 |
431 | var statement = file.fileCodeBlock().codeBlock().statement().get(0);
432 | assertThat(statement).isNotNull();
433 | assertThat(statement.compoundStatement()).isNotNull();
434 | assertThat(statement.compoundStatement().raiseStatement()).isNotNull();
435 |
436 | var raise = statement.compoundStatement().raiseStatement();
437 | assertThat(raise.expression()).isNull();
438 | assertThat(raise.doCall()).isNotNull();
439 | assertThat(raise.doCall().callParamList()).isNotNull();
440 | assertThat(raise.doCall().callParamList().callParam()).isNotNull().hasSize(4);
441 | }
442 | }
443 |
--------------------------------------------------------------------------------