├── .gitmodules ├── docs ├── javadoc │ └── .empty ├── en │ └── index.md ├── ru │ ├── examples.md │ ├── index.md │ └── systemRequirements.md ├── assets │ ├── images │ │ └── logo.png │ ├── javascripts │ │ └── tables.js │ └── stylesheets │ │ └── extra.css └── index.md ├── src ├── jmh │ ├── resources │ │ └── .gitkeep │ └── java │ │ └── com │ │ └── github │ │ └── _1c_syntax │ │ └── bsl │ │ └── parser │ │ ├── JMXBSLParserTest.java │ │ └── JMXBSLLexerTest.java ├── test │ ├── resources │ │ ├── sdbl │ │ │ ├── drop.sdbl │ │ │ ├── select07.sdbl │ │ │ ├── select03.sdbl │ │ │ ├── select02.sdbl │ │ │ ├── select04.sdbl │ │ │ ├── select05.sdbl │ │ │ ├── select06.sdbl │ │ │ ├── select08.sdbl │ │ │ └── select01.sdbl │ │ └── methodDescription │ │ │ ├── example4.bsl │ │ │ ├── example2.bsl │ │ │ ├── example3.bsl │ │ │ ├── example10.bsl │ │ │ ├── example9.bsl │ │ │ ├── example6.bsl │ │ │ └── example1.bsl │ └── java │ │ └── com │ │ └── github │ │ └── _1c_syntax │ │ └── bsl │ │ └── parser │ │ ├── BSLTokenizerTest.java │ │ ├── SDBLTokenizerTest.java │ │ ├── description │ │ └── support │ │ │ └── SimpleRangeTest.java │ │ ├── SDBLParserMatchesTest.java │ │ ├── BSLMethodDescriptionParserMatchesTest.java │ │ ├── BSLMethodDescriptionLexerTest.java │ │ ├── SDBLParserCheckSourceTest.java │ │ ├── SDBLLexerTest.java │ │ └── BSLParserWithChildrenTest.java └── main │ ├── java │ └── com │ │ └── github │ │ └── _1c_syntax │ │ └── bsl │ │ └── parser │ │ ├── description │ │ ├── package-info.java │ │ ├── support │ │ │ ├── package-info.java │ │ │ ├── ParameterDescription.java │ │ │ ├── TypeDescription.java │ │ │ └── SimpleRange.java │ │ ├── BSLDescriptionReader.java │ │ ├── SourceDefinedSymbolDescription.java │ │ ├── VariableDescription.java │ │ └── MethodDescription.java │ │ ├── BSLTokenizer.java │ │ ├── SDBLTokenizer.java │ │ └── BSLMethodDescriptionTokenizer.java │ └── antlr │ ├── BSLMethodDescriptionLexer.g4 │ ├── BSLMethodDescriptionParser.g4 │ ├── BSLParser.g4 │ └── BSLLexer.g4 ├── settings.gradle.kts ├── .gitattributes ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── encodings.xml ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── compiler.xml ├── checkstyle-idea.xml └── jarRepositories.xml ├── .github ├── workflows │ ├── javadoc.yml │ ├── update-gradle.yaml │ ├── qa.yml │ ├── check.yml │ ├── release.yml │ ├── publish-to-maven-central.yml │ └── gh-pages.yml └── dependabot.yml ├── license └── HEADER.txt ├── README.md ├── .gitignore ├── mkdocs.en.yml ├── mkdocs.yml ├── gradlew.bat ├── COPYING.LESSER.md └── gradlew /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/javadoc/.empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/jmh/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/en/index.md: -------------------------------------------------------------------------------- 1 | # BSL Parser 2 | 3 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "bsl-parser" 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.java eol=lf 2 | *.bsl eol=lf 3 | *.xml eol=lf 4 | -------------------------------------------------------------------------------- /docs/ru/examples.md: -------------------------------------------------------------------------------- 1 | # Примеры использования 2 | 3 | *В разработке* 4 | -------------------------------------------------------------------------------- /src/test/resources/sdbl/drop.sdbl: -------------------------------------------------------------------------------- 1 | Уничтожить ТЧ; 2 | Drop table; 3 | Drop Уничтожить -------------------------------------------------------------------------------- /src/test/resources/sdbl/select07.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ * 2 | ИЗ РегистрСведений.Таблица КАК Таблица 3 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.parallel=true 2 | org.gradle.jvmargs=-Xmx1024m -XX:MaxMetaspaceSize=512m 3 | -------------------------------------------------------------------------------- /docs/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1c-syntax/bsl-parser/HEAD/docs/assets/images/logo.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1c-syntax/bsl-parser/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # BSL Parser 2 | 3 | - [Документация на русском языке](ru/index.md) 4 | - [English documentation](en/index.md) 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/ru/index.md: -------------------------------------------------------------------------------- 1 | # BSL Parser 2 | 3 | *В разработке* 4 | 5 | ## Полезная информация 6 | 7 | - [Примеры использования](examples.md) 8 | - [Системные требования](systemRequirements.md) 9 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/assets/javascripts/tables.js: -------------------------------------------------------------------------------- 1 | app.document$.subscribe(function() { 2 | var tables = document.querySelectorAll("article table") 3 | tables.forEach(function(table) { 4 | new Tablesort(table) 5 | }) 6 | }) -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/test/resources/sdbl/select03.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ 2 | Изменения.ВидСогласования, 3 | Изменения.КоличествоЧасовСогласования, 4 | Изменения.КоличествоДнейСогласования, 5 | ТИПЗНАЧЕНИЯ(Изменения.ПустаяСсылка) КАК ТипСсылки 6 | ПОМЕСТИТЬ ВТСрокиСогласования 7 | ИЗ 8 | РегистрСведений.успСрокиСогласования КАК Изменения 9 | -------------------------------------------------------------------------------- /src/test/resources/methodDescription/example4.bsl: -------------------------------------------------------------------------------- 1 | // Описание функции. 2 | // Многострочное. 3 | // 4 | // Параметры: 5 | // П1 - Дата, Число - Описание даты/числа 6 | // П2 - Число - Описание числа 7 | // П3 - Строка - Описание строки 8 | // 9 | // Возвращаемое значение: 10 | // Строка - вернувшаяся строка 11 | // -------------------------------------------------------------------------------- /src/test/resources/methodDescription/example2.bsl: -------------------------------------------------------------------------------- 1 | // Инициализирует структуру параметров для взаимодействия с файловой системой. 2 | // 3 | // Параметры: 4 | // РежимДиалога - РежимДиалогаВыбораФайла - режим работы конструируемого диалога выбора файлов. 5 | // 6 | // Возвращаемое значение: 7 | // см. ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла 8 | // -------------------------------------------------------------------------------- /src/test/resources/sdbl/select02.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ 2 | Максимум(Регистр.Поле = &Пара) 3 | ИЗ 4 | РегистрНакопления.Регистр2.Остатки(Начало, Конец, (Измерение1, Измерение2) В ( 5 | ВЫБРАТЬ 6 | Справочник.Поле1, 7 | Справочник.Полек2 8 | Из Справочник.Справочник1 9 | ГДЕ 10 | (Код, Наименование) НЕ В (&Параметр1, &Параметр2))) КАК Регистр -------------------------------------------------------------------------------- /src/test/resources/sdbl/select04.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ 2 | Информация.Регистратор КАК Регистратор 3 | ИЗ 4 | РегистрСведений.Информация КАК Информация 5 | ГДЕ 6 | Информация.Регистратор В 7 | (ВЫБРАТЬ ПЕРВЫЕ 1 8 | Заявка.Ссылка КАК Ссылка 9 | ИЗ 10 | Документ.Заявка КАК Заявка 11 | ГДЕ 12 | Заявка.Проведен 13 | УПОРЯДОЧИТЬ ПО 14 | Заявка.Дата УБЫВ ) 15 | -------------------------------------------------------------------------------- /src/test/resources/sdbl/select05.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ 2 | ЕСТЬNULL(Справочник1.Реквизит2 = ЗНАЧЕНИЕ(Справочник.Справочник1.Пустаяссылка), ЛОЖЬ) КАК Поле1, 3 | ЕСТЬNULL(Справочник1.Реквизит2, ЛОЖЬ) КАК Поле2, 4 | ЕСТЬNULL(Справочник1.Реквизит2, Справочник1.Реквизит2) КАК Поле3, 5 | ЕСТЬNULL(Справочник1.Реквизит2, Справочник1.Реквизит2 = ЗНАЧЕНИЕ(Справочник.Справочник1.Пустаяссылка)) КАК Поле4 6 | ИЗ 7 | Справочник.Справочник1 КАК Справочник1 -------------------------------------------------------------------------------- /.github/workflows/javadoc.yml: -------------------------------------------------------------------------------- 1 | name: javadoc 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v6 10 | with: 11 | fetch-depth: 0 12 | - name: Set up JDK 13 | uses: actions/setup-java@v5 14 | with: 15 | java-version: 17 16 | distribution: 'adopt' 17 | - name: Check javadoc build 18 | run: ./gradlew javadoc --stacktrace 19 | -------------------------------------------------------------------------------- /src/test/resources/sdbl/select06.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ 2 | timestamp 3 | ИЗ 4 | ВнешнийИсточникДанных.ClickHouse.Таблица.test01_log 5 | ; 6 | SELECT 7 | timestamp 8 | FROM 9 | ExternalDataSource.ClickHouse.Table.test01_log 10 | ; 11 | ВЫБРАТЬ 12 | Поле1 КАК Поле1 13 | ИЗ 14 | ВнешнийИсточникДанных.ВнешнийИсточникДанных1.Куб.Куб1.ТаблицаИзмерения.ТаблицаИзмерения1 15 | ; 16 | SELECT 17 | Cube1DimensionTableDimensionTable1.Ref AS Ref 18 | FROM 19 | ExternalDataSource.ExternalDataSource1.Cube.Cube1.DimensionTable.DimensionTable1 AS Cube1DimensionTableDimensionTable1 -------------------------------------------------------------------------------- /.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /docs/assets/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | .md-content { 2 | margin-right: 0; 3 | } 4 | 5 | .md-typeset__table { 6 | padding: 0; 7 | } 8 | 9 | .md-typeset table:not([class]) { 10 | font-size: .54rem; 11 | } 12 | 13 | 14 | [data-md-color-scheme="slate"] .md-logo img { 15 | filter: invert(100%); 16 | } 17 | 18 | [data-md-color-scheme="slate"] { 19 | --md-primary-fg-color: #212121; 20 | } 21 | 22 | [data-md-color-scheme=slate][data-md-color-primary=black] { 23 | --md-typeset-a-color: #02a6f2; 24 | } 25 | 26 | [data-md-color-primary=black] .md-header { 27 | background-color: #212121; 28 | } 29 | 30 | [data-md-color-primary=black] .md-tabs { 31 | background-color: #212121; 32 | } -------------------------------------------------------------------------------- /.github/workflows/update-gradle.yaml: -------------------------------------------------------------------------------- 1 | name: Update Gradle Wrapper 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 0 * * 0" 7 | 8 | jobs: 9 | update-gradle-wrapper: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v6 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: Set up JDK 17 18 | uses: actions/setup-java@v5 19 | with: 20 | java-version: 17 21 | distribution: 'temurin' 22 | cache: gradle 23 | 24 | - name: Update Gradle Wrapper 25 | uses: gradle-update/update-gradle-wrapper-action@v2 26 | with: 27 | repo-token: ${{ secrets.GITHUB_TOKEN }} 28 | set-distribution-checksum: false 29 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gradle" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | groups: 13 | freefair: 14 | patterns: 15 | - "io.freefair.*" 16 | - package-ecosystem: "github-actions" 17 | directory: "/" 18 | schedule: 19 | interval: "daily" 20 | -------------------------------------------------------------------------------- /license/HEADER.txt: -------------------------------------------------------------------------------- 1 | This file is a part of ${project}. 2 | 3 | Copyright (c) ${year} 4 | ${name} 5 | 6 | SPDX-License-Identifier: LGPL-3.0-or-later 7 | 8 | ${project} is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 3.0 of the License, or (at your option) any later version. 12 | 13 | ${project} is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with ${project}. -------------------------------------------------------------------------------- /.github/workflows/qa.yml: -------------------------------------------------------------------------------- 1 | name: QA 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | - master 8 | pull_request: 9 | 10 | jobs: 11 | QA: 12 | runs-on: ubuntu-latest 13 | if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name 14 | steps: 15 | - uses: actions/checkout@v6 16 | with: 17 | fetch-depth: '' 18 | - run: | 19 | git fetch --prune --unshallow 20 | - name: Set up JDK 17 21 | uses: actions/setup-java@v5 22 | with: 23 | java-version: 17 24 | distribution: 'adopt' 25 | - name: SonarCloud Scan 26 | run: ./gradlew check sonar 27 | env: 28 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | java_version: ['17', '21'] 12 | os: [ubuntu-latest, windows-latest, macOS-latest] 13 | steps: 14 | - uses: actions/checkout@v6 15 | with: 16 | fetch-depth: 0 17 | - name: Set up JDK ${{ matrix.java_version }} 18 | uses: actions/setup-java@v5 19 | with: 20 | java-version: ${{ matrix.java_version }} 21 | distribution: 'adopt' 22 | - name: Build with Gradle 23 | run: ./gradlew check --stacktrace 24 | - name: Archive test results 25 | if: failure() 26 | uses: actions/upload-artifact@v6 27 | with: 28 | name: junit_report_${{ matrix.os }}_${{ matrix.java_version }} 29 | path: build/reports/tests/test 30 | -------------------------------------------------------------------------------- /docs/ru/systemRequirements.md: -------------------------------------------------------------------------------- 1 | # Системные требования 2 | 3 | Использование BSL Parser имеет ряд ограничений, ниже приведены ключевые 4 | 5 | ## Поддерживаемые версии Java 6 | 7 | BSL Parser представляет собой Java библиотеку, соответственно ее использование возможно в приложения, использующих JVM. 8 | 9 | На данный момент библиотека разрабатывается с использованием Java 11, но в рамках сборочных конвейеров происходит проверка работоспособности при использовании более свежих версий, в частности версии Java 16. 10 | 11 | ## Поддерживаемые операционные системы 12 | 13 | BSL Parser должна корректно работать на всех системах под управлением современных десктопных и серверных операционных систем, для которых существует поддержка Java: 14 | 15 | - OS семейства Windows 16 | - OS на ядре Linux 17 | - MacOS последних версий 18 | 19 | Иные OS проверку не проходили, но не исключено, что библиотека будет работать и там. 20 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Make image 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | os: [ ubuntu-latest, windows-latest, macOS-latest ] 14 | steps: 15 | - uses: actions/checkout@v6 16 | with: 17 | fetch-depth: 0 18 | - uses: actions/setup-java@v5 19 | with: 20 | java-version: 17 21 | distribution: 'adopt' 22 | - run: ./gradlew check --stacktrace 23 | - if: matrix.os == 'ubuntu-latest' 24 | run: ./gradlew build 25 | - if: matrix.os == 'ubuntu-latest' 26 | uses: AButler/upload-release-assets@v3.0 27 | with: 28 | files: './build/libs/*.jar' 29 | repo-token: ${{ secrets.GITHUB_TOKEN }} 30 | 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BSL Parser 2 | 3 | [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=1c-syntax_bsl-parser&metric=alert_status)](https://sonarcloud.io/dashboard?id=1c-syntax_bsl-parser) 4 | [![Maintainability](https://sonarcloud.io/api/project_badges/measure?project=1c-syntax_bsl-parser&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=1c-syntax_bsl-parser) 5 | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=1c-syntax_bsl-parser&metric=coverage)](https://sonarcloud.io/dashboard?id=1c-syntax_bsl-parser) 6 | 7 | ## English 8 | 9 | Collection of parsers for Language 1C (BSL) in ANTLR4 format. 10 | 11 | ## На русском 12 | 13 | Коллекция парсеров языка 1С (BSL) в формате ANTLR4. 14 | 15 | Содержит 16 | 17 | - Парсер языка 1С (BSL). Правила лексера и грамматики основаны на BNF/JFlex правилах из репозитория [IntelliJ Idea OneScript Support](https://github.com/dmpas/idea-onescript) за авторством Сергея Батанова ([@dmpas](https://github.com/dmpas)). 18 | - Парсер языка запросов 1С (SDBL) 19 | - Парсер описаний методов 20 | 21 | ## Сайт проекта (документация) 22 | - [Релизная версия](https://1c-syntax.github.io/bsl-parser/) 23 | - [Текущая (Develop) версия](https://1c-syntax.github.io/bsl-parser/dev/) 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/_1c_syntax/bsl/parser/description/package-info.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 | /** 23 | * Классы для хранения информации, прочитанной из комментариев-описаний 24 | */ 25 | @ParametersAreNonnullByDefault 26 | package com.github._1c_syntax.bsl.parser.description; 27 | 28 | import javax.annotation.ParametersAreNonnullByDefault; -------------------------------------------------------------------------------- /src/main/java/com/github/_1c_syntax/bsl/parser/description/support/package-info.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 | /** 23 | * Служебные классы для чтения и хранения информации из комментариев-описаний 24 | */ 25 | @ParametersAreNonnullByDefault 26 | package com.github._1c_syntax.bsl.parser.description.support; 27 | 28 | import javax.annotation.ParametersAreNonnullByDefault; -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 21 | 22 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-maven-central.yml: -------------------------------------------------------------------------------- 1 | name: Publish to maven central 2 | 3 | on: 4 | release: 5 | types: [published] 6 | push: 7 | branches: 8 | - develop 9 | workflow_dispatch: 10 | 11 | jobs: 12 | publish: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v6 16 | with: 17 | fetch-depth: 0 18 | - name: Set up JDK 19 | uses: actions/setup-java@v5 20 | with: 21 | java-version: 17 22 | distribution: 'temurin' 23 | cache: gradle 24 | - name: Deploy to Central Portal 25 | run: | 26 | ./gradlew publishMavenPublicationToStagingRepository 27 | ./gradlew jreleaserDeploy 28 | env: 29 | JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | JRELEASER_MAVENCENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 31 | JRELEASER_MAVENCENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 32 | JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.GPG_SIGNING_PUBLIC_KEY }} 33 | JRELEASER_GPG_SECRET_KEY: ${{ secrets.GPG_SIGNING_KEY }} 34 | JRELEASER_GPG_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSWORD }} 35 | JRELEASER_DEPLOY_MAVEN_NEXUS2_SNAPSHOT_DEPLOY_USERNAME: ${{ secrets.SONATYPE_USERNAME }} 36 | JRELEASER_DEPLOY_MAVEN_NEXUS2_SNAPSHOT_DEPLOY_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} 37 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/com/github/_1c_syntax/bsl/parser/BSLTokenizer.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.CharStreams; 25 | import org.antlr.v4.runtime.Lexer; 26 | import org.antlr.v4.runtime.Tokenizer; 27 | 28 | public class BSLTokenizer extends Tokenizer { 29 | public BSLTokenizer(String content) { 30 | this(content, new BSLLexer(CharStreams.fromString(""))); 31 | } 32 | 33 | public BSLTokenizer(String content, Lexer lexer) { 34 | super(content, lexer, BSLParser.class); 35 | } 36 | 37 | @Override 38 | protected BSLParser.FileContext rootAST() { 39 | return parser.file(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/resources/methodDescription/example3.bsl: -------------------------------------------------------------------------------- 1 | // Загружает настройку из хранилища общих настроек, как метод платформы Загрузить, 2 | // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, 3 | // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, 4 | // которая превышает 96 символов. 5 | // Кроме того, возвращает указанное значение по умолчанию, если настройки не существуют. 6 | // Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки. 7 | // 8 | // В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно 9 | // - возвращаемая ссылка заменяется на указанное значение по умолчанию; 10 | // - из данных типа Массив ссылки удаляются; 11 | // - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено; 12 | // - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно. 13 | // 14 | // Параметры: 15 | // КлючОбъекта - Строка - см. синтакс-помощник платформы. 16 | // КлючНастроек - Строка - см. синтакс-помощник платформы. 17 | // ЗначениеПоУмолчанию - Произвольный - значение, которое возвращается, если настройки не существуют. 18 | // Если не указано, возвращается значение Неопределено. 19 | // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. 20 | // ИмяПользователя - Строка - см. синтакс-помощник платформы. 21 | // 22 | // Возвращаемое значение: 23 | // Произвольный - см. синтакс-помощник платформы. 24 | // -------------------------------------------------------------------------------- /src/main/java/com/github/_1c_syntax/bsl/parser/SDBLTokenizer.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.CharStreams; 25 | import org.antlr.v4.runtime.Lexer; 26 | import org.antlr.v4.runtime.Tokenizer; 27 | 28 | public class SDBLTokenizer extends Tokenizer { 29 | public SDBLTokenizer(String content) { 30 | this(content, new SDBLLexer(CharStreams.fromString(""))); 31 | } 32 | 33 | public SDBLTokenizer(String content, Lexer lexer) { 34 | super(content, lexer, SDBLParser.class); 35 | } 36 | 37 | @Override 38 | protected SDBLParser.QueryPackageContext rootAST() { 39 | return parser.queryPackage(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/resources/sdbl/select08.sdbl: -------------------------------------------------------------------------------- 1 | ВЫБРАТЬ 2 | ЦЕЛ(СРЕДНЕЕ(Таблица.Поле)) КАК Цел, 3 | INT(СРЕДНЕЕ(Таблица.Поле)) КАК INT, 4 | ACOS(Таблица.Поле) КАК ACOS, 5 | ASIN(Таблица.Поле) КАК ASIN, 6 | ATAN(Таблица.Поле) КАК ATAN, 7 | COS(Таблица.Поле) КАК COS, 8 | SIN(Таблица.Поле) КАК SIN, 9 | TAN(Таблица.Поле) КАК TAN, 10 | LOG(Таблица.Поле) КАК LOG, 11 | LOG10(Таблица.Поле) КАК LOG10, 12 | EXP(Таблица.Поле) КАК EXP, 13 | POW(Таблица.Поле) КАК POW, 14 | SQRT(Таблица.Поле) КАК SQRT, 15 | LOWER(Таблица.Поле) КАК LOWER, 16 | НРЕГ(Таблица.Поле) КАК НРЕГ, 17 | STRINGLENGTH(Таблица.Поле) КАК STRINGLENGTH, 18 | ДЛИНАСТРОКИ(Таблица.Поле) КАК СТРДЛИНА, 19 | TRIMALL(Таблица.Поле) КАК TRIMALL, 20 | СОКРЛП(Таблица.Поле) КАК СОКРЛП, 21 | TRIML(Таблица.Поле) КАК TRIML, 22 | СОКРЛ(Таблица.Поле) КАК СОКРЛ, 23 | TRIMR(Таблица.Поле) КАК TRIMR, 24 | СОКРП(Таблица.Поле) КАК СОКРП, 25 | UPPER(Таблица.Поле) КАК UPPER, 26 | ВРЕГ(Таблица.Поле) КАК ВРЕГ, 27 | ROUND(Таблица.Поле, Таблица.Поле2) КАК ROUND, 28 | ОКР(Таблица.Поле, Таблица.Поле2) КАК ОКР, 29 | STOREDDATASIZE(Таблица.Поле) КАК STOREDDATASIZE, 30 | РазмерХранимыхДанных(Таблица.Поле) КАК РазмерХранимыхДанных, 31 | UUID(Таблица.Поле) КАК UUID, 32 | УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Таблица.Поле) КАК УНИКАЛЬНЫЙИДЕНТИФИКАТОР, 33 | STRFIND(Таблица.Поле, Таблица.Поле2) КАК STRFIND, 34 | СтрНайти(Таблица.Поле, Таблица.Поле2) КАК СтрНайти, 35 | STRREPLACE(Таблица.Поле, Таблица.Поле2, Таблица.Поле3) КАК STRREPLACE, 36 | СтрЗаменить(Таблица.Поле, Таблица.Поле2, Таблица.Поле3) КАК СтрЗаменить 37 | ИЗ РегистрСведений.Таблица КАК Таблица 38 | -------------------------------------------------------------------------------- /src/main/java/com/github/_1c_syntax/bsl/parser/BSLMethodDescriptionTokenizer.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.CharStreams; 25 | import org.antlr.v4.runtime.Tokenizer; 26 | 27 | public class BSLMethodDescriptionTokenizer 28 | extends Tokenizer { 29 | public BSLMethodDescriptionTokenizer(String content) { 30 | super(content + "\n", 31 | new BSLMethodDescriptionLexer(CharStreams.fromString("")), 32 | BSLMethodDescriptionParser.class); 33 | } 34 | 35 | @Override 36 | protected BSLMethodDescriptionParser.MethodDescriptionContext rootAST() { 37 | return parser.methodDescription(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/resources/methodDescription/example10.bsl: -------------------------------------------------------------------------------- 1 | // Развернуть каждый элемент коллекции в процессор коллекций. 2 | // Позволяет расширить имеющуюся коллекцию. 3 | // Например, разворачивание массива массивов сделает новый массив, содержащий все элементы всех массивов. 4 | // Конвейерный метод. 5 | // 6 | // Параметры: 7 | // ФункцияРазворачивания - Строка, ОписаниеОповещения - функция разворачивания. 8 | // В случае передачи Строки формируется служебное описание оповещения, в контексте которого заданы переменные 9 | // "Результат", "ДополнительныеПараметры", "Элемент". 10 | // В случае передачи ОписанияОповещения обработчик данного описания должен содержать два параметра 11 | // (имена произвольные): 12 | // * Результат - ПроцессорКоллекций - Переменная, в которую должен быть 13 | // помещен результат работы функции в виде ПроцессораКоллекций. 14 | // * ДополнительныеПараметры - Структура - Структура параметров, передаваемая функции разворачивания. 15 | // 16 | // ДополнительныеПараметры - Структура - Структура дополнительных параметров, передаваемая функции разворачивания. 17 | // Служит для передачи дополнительных данных из прикладного кода в функцию разворачивания. 18 | // По умолчанию содержит одно значение - Элемент. 19 | // 20 | // Возвращаемое значение: 21 | // ПроцессорКоллекций - Инстанс класса "ПроцессорКоллекций". 22 | // 23 | // Примеры: 24 | // 1: 25 | // ПроцессорКоллекций.Развернуть("Результат = ПроцессорыКоллекций.ИзСтроки(Элемент);"); 26 | // 27 | // 2: 28 | // Процедура МояФункцияРазворачивания(Результат, ДополнительныеПараметры) Экспорт 29 | // Результат = ПроцессорыКоллекций.ИзСтроки(ДополнительныеПараметры.Элемент); 30 | // КонецПроцедуры 31 | // 32 | // ФункцияРазворачивания = Новый ОписаниеОповещения("МояФункцияРазворачивания", ЭтотОбъект); 33 | // ПроцессорКоллекций.Развернуть(ФункцияРазворачивания); 34 | // -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 3 | 4 | # User-specific stuff 5 | .idea/**/workspace.xml 6 | .idea/**/tasks.xml 7 | .idea/**/usage.statistics.xml 8 | .idea/**/dictionaries 9 | .idea/**/shelf 10 | 11 | # Generated files 12 | .idea/**/contentModel.xml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | .idea/modules.xml 32 | .idea/*.iml 33 | .idea/modules 34 | 35 | # IntelliJ 36 | out/ 37 | 38 | # Crashlytics plugin (for Android Studio and IntelliJ) 39 | com_crashlytics_export_strings.xml 40 | crashlytics.properties 41 | crashlytics-build.properties 42 | fabric.properties 43 | 44 | # Editor-based Rest Client 45 | .idea/httpRequests 46 | 47 | .gradle/ 48 | *.zip 49 | *.ps1 50 | target/ 51 | build/ 52 | 53 | # Scala compiler user settings 54 | .idea/hydra.xml 55 | 56 | .idea/sonarlint/ 57 | 58 | intellij-bsl/src/test/resources/parser/.idea/ 59 | 60 | gen/ 61 | 62 | # Crashlytics plugin (for Android Studio and IntelliJ) 63 | 64 | \.idea/sonarlint-state\.xml 65 | 66 | \.idea/sonarlint\.xml 67 | **/antlr/.antlr/** 68 | *.java.orig 69 | *.orig 70 | /.idea/misc.xml 71 | *.tokens 72 | /.idea/inspectionProfiles/Project_Default.xml 73 | /.idea/material_theme_project_new.xml 74 | -------------------------------------------------------------------------------- /mkdocs.en.yml: -------------------------------------------------------------------------------- 1 | site_name: BSL Parser 2 | nav: 3 | - Home: 4 | - index.md 5 | - JavaDoc: javadoc/index.html 6 | theme: 7 | name: material 8 | language: en 9 | logo: 'assets/images/logo.png' 10 | favicon: 'assets/images/logo.png' 11 | palette: 12 | # Light mode 13 | - teal: "(prefers-color-scheme: light)" 14 | scheme: default 15 | primary: white 16 | accent: indigo 17 | toggle: 18 | icon: material/lightbulb-outline 19 | name: Switch to dark mode 20 | 21 | # Dark mode 22 | - media: "(prefers-color-scheme: dark)" 23 | scheme: slate 24 | primary: black 25 | accent: light blue 26 | toggle: 27 | icon: material/lightbulb 28 | name: Switch to light mode 29 | features: 30 | - navigation.tabs 31 | - search.highlight 32 | - toc.integrate 33 | - header.autohide 34 | extra: 35 | social: 36 | - icon: fontawesome/brands/github 37 | link: 'https://github.com/1c-syntax' 38 | - icon: fontawesome/brands/telegram 39 | link: 'https://t.me/bsl_language_server' 40 | alternate: 41 | - name: English 42 | link: /bsl-parser/en/ 43 | lang: en 44 | - name: Русский 45 | link: /bsl-parser/ 46 | lang: ru 47 | extra_css: 48 | - 'assets/stylesheets/extra.css' 49 | extra_javascript: 50 | - https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/tablesort.min.js 51 | - assets/javascripts/tables.js 52 | markdown_extensions: 53 | - admonition 54 | - codehilite 55 | - pymdownx.details 56 | - pymdownx.highlight 57 | - pymdownx.superfences 58 | - markdown.extensions.toc: 59 | permalink: true 60 | slugify: !!python/name:pymdownx.slugs.uslugify_cased 61 | toc_depth: 2 62 | 63 | plugins: 64 | - search: 65 | lang: 66 | - en 67 | - ru 68 | 69 | site_url: 'https://1c-syntax.github.io/bsl-parser' 70 | repo_name: '1c-syntax/bsl-parser' 71 | repo_url: 'https://github.com/1c-syntax/bsl-parser' 72 | edit_uri: 'edit/develop/docs/en' 73 | google_analytics: ['UA-150754232-1', '1c-syntax.github.io'] 74 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: BSL Parser 2 | nav: 3 | - Домашняя: 4 | - index.md 5 | - examples.md 6 | - systemRequirements.md 7 | - JavaDoc: javadoc/index.html 8 | theme: 9 | name: material 10 | language: ru 11 | logo: 'assets/images/logo.png' 12 | favicon: 'assets/images/logo.png' 13 | palette: 14 | # Light mode 15 | - teal: "(prefers-color-scheme: light)" 16 | scheme: default 17 | primary: white 18 | accent: indigo 19 | toggle: 20 | icon: material/lightbulb-outline 21 | name: Switch to dark mode 22 | 23 | # Dark mode 24 | - media: "(prefers-color-scheme: dark)" 25 | scheme: slate 26 | primary: black 27 | accent: light blue 28 | toggle: 29 | icon: material/lightbulb 30 | name: Switch to light mode 31 | features: 32 | - navigation.tabs 33 | - search.highlight 34 | - toc.integrate 35 | - header.autohide 36 | extra: 37 | social: 38 | - icon: fontawesome/brands/github 39 | link: 'https://github.com/1c-syntax' 40 | - icon: fontawesome/brands/telegram 41 | link: 'https://t.me/bsl_language_server' 42 | alternate: 43 | - name: English 44 | link: /bsl-parser/en/ 45 | lang: en 46 | - name: Русский 47 | link: /bsl-parser/ 48 | lang: ru 49 | extra_css: 50 | - 'assets/stylesheets/extra.css' 51 | extra_javascript: 52 | - https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/tablesort.min.js 53 | - assets/javascripts/tables.js 54 | markdown_extensions: 55 | - admonition 56 | - codehilite 57 | - pymdownx.details 58 | - pymdownx.highlight 59 | - pymdownx.superfences 60 | - markdown.extensions.toc: 61 | permalink: true 62 | slugify: !!python/name:pymdownx.slugs.uslugify_cased 63 | toc_depth: 2 64 | 65 | plugins: 66 | - search: 67 | lang: 68 | - en 69 | - ru 70 | 71 | site_url: 'https://1c-syntax.github.io/bsl-parser' 72 | repo_name: '1c-syntax/bsl-parser' 73 | repo_url: 'https://github.com/1c-syntax/bsl-parser' 74 | edit_uri: 'edit/develop/docs' 75 | google_analytics: ['UA-150754232-1', '1c-syntax.github.io'] 76 | -------------------------------------------------------------------------------- /src/test/java/com/github/_1c_syntax/bsl/parser/BSLTokenizerTest.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.Lexer; 25 | import org.antlr.v4.runtime.Token; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import java.util.List; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | class BSLTokenizerTest { 33 | 34 | @Test 35 | void computeTokens() { 36 | // given 37 | var tokenizer = new BSLTokenizer("Если Условие() Тогда КонецЕсли"); 38 | 39 | // when 40 | final List tokens = tokenizer.getTokens(); 41 | 42 | // then 43 | assertThat(tokens).hasSize(10); 44 | assertThat(tokens.get(9).getType()).isEqualTo(Lexer.EOF); 45 | assertThat(tokens.get(9).getChannel()).isEqualTo(Lexer.HIDDEN); 46 | } 47 | 48 | @Test 49 | void computeAST() { 50 | // given 51 | BSLTokenizer tokenizer = new BSLTokenizer("Если Условие() Тогда КонецЕсли"); 52 | 53 | // when 54 | final BSLParser.FileContext ast = tokenizer.getAst(); 55 | 56 | // then 57 | BSLParser.FileCodeBlockContext fileCodeBlock = ast.fileCodeBlock(); 58 | assertThat(fileCodeBlock).isNotNull(); 59 | assertThat(fileCodeBlock.getStart().getType()).isEqualTo(BSLParser.IF_KEYWORD); 60 | assertThat(fileCodeBlock.getStop().getType()).isEqualTo(BSLParser.ENDIF_KEYWORD); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/com/github/_1c_syntax/bsl/parser/SDBLTokenizerTest.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.Lexer; 25 | import org.antlr.v4.runtime.Token; 26 | import org.junit.jupiter.api.Test; 27 | 28 | import java.util.List; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | class SDBLTokenizerTest { 33 | 34 | @Test 35 | void computeTokens() { 36 | // given 37 | SDBLTokenizer tokenizer = new SDBLTokenizer("Выбрать Ссылка Из Справочник.Контрагенты"); 38 | 39 | // when 40 | final List tokens = tokenizer.getTokens(); 41 | 42 | // then 43 | assertThat(tokens).hasSize(10); 44 | assertThat(tokens.get(9).getType()).isEqualTo(Lexer.EOF); 45 | assertThat(tokens.get(9).getChannel()).isEqualTo(Lexer.HIDDEN); 46 | } 47 | 48 | @Test 49 | void computeAST() { 50 | // given 51 | SDBLTokenizer tokenizer = new SDBLTokenizer("Выбрать Ссылка Из Справочник.Контрагенты"); 52 | 53 | // when 54 | final SDBLParser.QueryPackageContext ast = tokenizer.getAst(); 55 | 56 | // then 57 | List queries = ast.queries(); 58 | 59 | assertThat(queries) 60 | .isNotNull() 61 | .hasSize(1); 62 | SDBLParser.QueriesContext query = queries.get(0); 63 | assertThat(query.getStart().getType()).isEqualTo(SDBLParser.SELECT); 64 | assertThat(query.getStop().getType()).isEqualTo(SDBLParser.IDENTIFIER); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/github/_1c_syntax/bsl/parser/description/support/ParameterDescription.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 ParameterDescription { 30 | /** 31 | * Имя параметра 32 | */ 33 | private final String name; 34 | /** 35 | * Возможные типы параметра. Может быть пустым 36 | */ 37 | private final List 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 | --------------------------------------------------------------------------------