diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 06fb9e44..95d6479e 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -8,12 +8,12 @@ jobs:
strategy:
fail-fast: false
matrix:
- java_version: ['11', '17']
+ java_version: ['17', '20']
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java_version }}
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
@@ -21,7 +21,7 @@ jobs:
run: ./gradlew check --stacktrace
- name: Archive test results
if: failure()
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: junit_report_${{ matrix.os }}_${{ matrix.java_version }}
path: build/reports/tests/test
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
index 7b4e2240..07f8ab54 100644
--- a/.github/workflows/gh-pages.yml
+++ b/.github/workflows/gh-pages.yml
@@ -17,10 +17,10 @@ jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'adopt'
@@ -29,7 +29,7 @@ jobs:
run: ./gradlew --no-daemon javadoc
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: '3.6'
architecture: 'x64'
diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml
index 10e07d86..59f8c880 100644
--- a/.github/workflows/javadoc.yml
+++ b/.github/workflows/javadoc.yml
@@ -6,11 +6,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
- java-version: 11
+ java-version: 17
distribution: 'adopt'
- name: Check javadoc build
run: ./gradlew javadoc --stacktrace
diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml
index cc61c447..a82508d5 100644
--- a/.github/workflows/qa.yml
+++ b/.github/workflows/qa.yml
@@ -12,18 +12,18 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: ''
- run: |
git fetch --prune --unshallow
- - name: Set up JDK 11
- uses: actions/setup-java@v3
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
with:
- java-version: 11
+ java-version: 17
distribution: 'adopt'
- name: SonarCloud Scan
- run: ./gradlew check sonarqube
+ run: ./gradlew check sonar
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d49a2424..4dd80a14 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,16 +12,16 @@ jobs:
matrix:
os: [ ubuntu-latest, windows-latest, macOS-latest ]
steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
with:
- java-version: 11
+ java-version: 17
distribution: 'adopt'
- run: ./gradlew check --stacktrace
- if: matrix.os == 'ubuntu-latest'
run: ./gradlew build
- if: matrix.os == 'ubuntu-latest'
- uses: AButler/upload-release-assets@v2.0
+ uses: AButler/upload-release-assets@v3.0
with:
files: './build/libs/*.jar'
repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 4f38879f..b589d56e 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,9 +1,6 @@
-
-
-
-
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index 05730e05..0a83bc69 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -26,5 +26,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 91928488..b6f95dc8 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -6,12 +6,12 @@ plugins {
jacoco
`java-library`
antlr
- id("org.sonarqube") version "4.3.0.3225"
+ id("org.sonarqube") version "4.4.1.3373"
id("org.cadixdev.licenser") version "0.6.1"
id("com.github.gradle-git-version-calculator") version "1.1.0"
- id("io.freefair.javadoc-links") version "6.5.1"
- id("io.freefair.javadoc-utf-8") version "6.6.1"
- id("com.github.ben-manes.versions") version "0.47.0"
+ id("io.freefair.javadoc-links") version "8.4"
+ id("io.freefair.javadoc-utf-8") version "8.4"
+ id("com.github.ben-manes.versions") version "0.50.0"
id("me.champeau.gradle.jmh") version "0.5.3"
}
@@ -32,7 +32,7 @@ dependencies {
implementation(antlrGroupId, antlrArtifactId, antlrVersion)
antlr(antlrGroupId, antlrArtifactId, antlrVersion)
- implementation("com.github.1c-syntax", "utils", "0.3.4")
+ implementation("com.github.1c-syntax", "utils", "0.5.1")
testImplementation("org.junit.jupiter", "junit-jupiter-api", "5.6.1")
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", "5.6.1")
@@ -46,8 +46,8 @@ dependencies {
}
java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
withSourcesJar()
withJavadocJar()
}
@@ -106,10 +106,12 @@ tasks.generateGrammarSource {
outputDirectory = file("src/main/gen/com/github/_1c_syntax/bsl/parser")
}
-tasks.generateGrammarSource {
- doLast {
- tasks.updateLicenseMain.get().actions[0].execute(tasks.updateLicenseMain.get())
- }
+tasks.updateLicenseMain {
+ mustRunAfter(tasks.generateGrammarSource)
+}
+
+tasks.checkLicenseMain {
+ dependsOn(tasks.updateLicenseMain)
}
tasks.test {
@@ -163,7 +165,7 @@ tasks.clean {
}
}
-sonarqube {
+sonar {
properties {
property("sonar.sourceEncoding", "UTF-8")
property("sonar.host.url", "https://sonarcloud.io")
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..c36ba246
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx1024m -XX:MaxMetaspaceSize=512m
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e708b1c0..41d9927a 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 41dfb879..a5952066 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 4f906e0c..1b6c7873 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
+ JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=`expr $i + 1`
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/src/main/antlr/BSLParser.g4 b/src/main/antlr/BSLParser.g4
index 47550281..0bc012fe 100644
--- a/src/main/antlr/BSLParser.g4
+++ b/src/main/antlr/BSLParser.g4
@@ -169,7 +169,7 @@ subCodeBlock : subVars? codeBlock;
// statements
continueStatement : CONTINUE_KEYWORD;
breakStatement : BREAK_KEYWORD;
-raiseStatement : RAISE_KEYWORD (expression? | doCall);
+raiseStatement : RAISE_KEYWORD (doCall | expression)?;
ifStatement
: ifBranch elsifBranch* elseBranch? ENDIF_KEYWORD
;
diff --git a/src/main/antlr/SDBLLexer.g4 b/src/main/antlr/SDBLLexer.g4
index f085fff2..4aaa75ca 100644
--- a/src/main/antlr/SDBLLexer.g4
+++ b/src/main/antlr/SDBLLexer.g4
@@ -97,9 +97,13 @@ WHEN: RU_K RU_O RU_G RU_D RU_A
WHERE: RU_G RU_D RU_E | W H E R E;
// KEYWORDS RU EN
+ACOS: A C O S;
+ASIN: A S I N;
+ATAN: A T A N;
AVG: RU_S RU_R RU_E RU_D RU_N RU_E RU_E | A V G;
BEGINOFPERIOD: RU_N RU_A RU_CH RU_A RU_L RU_O RU_P RU_E RU_R RU_I RU_O RU_D RU_A | B E G I N O F P E R I O D;
BOOLEAN: RU_B RU_U RU_L RU_E RU_V RU_O | B O O L E A N;
+COS: C O S;
COUNT: RU_K RU_O RU_L RU_I RU_CH RU_E RU_S RU_T RU_V RU_O | C O U N T;
DATE: RU_D RU_A RU_T RU_A | D A T E;
DATEADD: RU_D RU_O RU_B RU_A RU_V RU_I RU_T RU_SOFT_SIGN RU_K RU_D RU_A RU_T RU_E | D A T E A D D;
@@ -110,8 +114,15 @@ DAYOFYEAR: RU_D RU_E RU_N RU_SOFT_SIGN RU_G RU_O RU_D RU_A
EMPTYTABLE: RU_P RU_U RU_S RU_T RU_A RU_YA RU_T RU_A RU_B RU_L RU_I RU_C RU_A | E M P T Y T A B L E;
EMPTYREF: RU_P RU_U RU_S RU_T RU_A RU_YA RU_S RU_S RU_Y RU_L RU_K RU_A | E M P T Y R E F;
ENDOFPERIOD: RU_K RU_O RU_N RU_E RU_C RU_P RU_E RU_R RU_I RU_O RU_D RU_A | E N D O F P E R I O D;
+EXP: E X P;
+// TODO найти англ вариант GROUPEDBY: RU_S RU_G RU_R RU_U RU_P RU_P RU_I RU_R RU_O RU_V RU_A RU_N RU_O RU_P RU_O | УТОНИЧТЬ;
HALFYEAR: RU_P RU_O RU_L RU_U RU_G RU_O RU_D RU_I RU_E | H A L F Y E A R;
HOUR: RU_CH RU_A RU_S | H O U R;
+// TODO добавить метод лев без конфликта с левым соединением LEFT: RU_L RU_E RU_V | L E F T;
+INT: RU_C RU_E RU_L | I N T;
+LOG: L O G;
+LOG10: L O G NUM_1 NUM_0;
+LOWER: RU_N RU_R RU_E RU_G | L O W E R;
MAX: RU_M RU_A RU_K RU_S RU_I RU_M RU_U RU_M | M A X;
MIN: RU_M RU_I RU_N RU_I RU_M RU_U RU_M | M I N;
MINUTE: RU_M RU_I RU_N RU_U RU_T RU_A | M I N U T E;
@@ -127,17 +138,34 @@ RECORDAUTONUMBER:
REFPRESENTATION:
RU_P RU_R RU_E RU_D RU_S RU_T RU_A RU_V RU_L RU_E RU_N RU_I RU_E RU_S RU_S RU_Y RU_L RU_K RU_I
| R E F P R E S E N T A T I O N;
+POW: P O W;
+// TODO см Лев RIGHT: RU_P RU_R RU_A RU_V | R I G H T;
+ROUND: RU_O RU_K RU_R | R O U N D;
SECOND: RU_S RU_E RU_K RU_U RU_N RU_D RU_A | S E C O N D;
+SIN: S I N;
+SQRT: S Q R T;
+STOREDDATASIZE: RU_R RU_A RU_Z RU_M RU_E RU_R RU_H RU_R RU_A RU_N RU_I RU_M RU_Y RU_H RU_D RU_A RU_N RU_N RU_Y RU_H
+ | S T O R E D D A T A S I Z E;
STRING: RU_S RU_T RU_R RU_O RU_K RU_A | S T R I N G;
+STRINGLENGTH: RU_D RU_L RU_I RU_N RU_A RU_S RU_T RU_R RU_O RU_K RU_I | S T R I N G L E N G T H;
+STRFIND: RU_S RU_T RU_R RU_N RU_A RU_J RU_T RU_I | S T R F I N D;
+STRREPLACE: RU_S RU_T RU_R RU_Z RU_A RU_M RU_E RU_N RU_I RU_T RU_SOFT_SIGN | S T R R E P L A C E;
SUBSTRING: RU_P RU_O RU_D RU_S RU_T RU_R RU_O RU_K RU_A | S U B S T R I N G;
SUM: RU_S RU_U RU_M RU_M RU_A | S U M;
+TAN: T A N;
TENDAYS: RU_D RU_E RU_K RU_A RU_D RU_A | T E N D A Y S;
+TRIMALL: RU_S RU_O RU_K RU_R RU_L RU_P | T R I M A L L;
+TRIML: RU_S RU_O RU_K RU_R RU_L | T R I M L;
+TRIMR: RU_S RU_O RU_K RU_R RU_P | T R I M R;
TYPE: RU_T RU_I RU_P | T Y P E;
+UPPER: RU_V RU_R RU_E RU_G | U P P E R;
VALUE: RU_Z RU_N RU_A RU_CH RU_E RU_N RU_I RU_E | V A L U E;
VALUETYPE: RU_T RU_I RU_P RU_Z RU_N RU_A RU_CH RU_E RU_N RU_I RU_YA | V A L U E T Y P E;
WEEK: RU_N RU_E RU_D RU_E RU_L RU_YA | W E E K;
WEEKDAY: RU_D RU_E RU_N RU_SOFT_SIGN RU_N RU_E RU_D RU_E RU_L RU_I | W E E K D A Y;
YEAR: RU_G RU_O RU_D | Y E A R;
+UUID: RU_U RU_N RU_I RU_K RU_A RU_L RU_SOFT_SIGN RU_N RU_Y RU_J RU_I RU_D RU_E RU_N RU_T RU_I RU_F RU_I RU_K RU_A RU_T RU_O RU_R
+ | U U I D;
// MDO TYPES RU EN
ACCOUNTING_REGISTER_TYPE:
@@ -164,8 +192,8 @@ ENUM_TYPE: RU_P RU_E RU_R RU_E RU_CH RU_I RU_S RU_L RU_E RU_N RU_I RU_E
EXCHANGE_PLAN_TYPE:
PLAN_RU RU_O RU_B RU_M RU_E RU_N RU_A | E X C H A N G E P L A N;
EXTERNAL_DATA_SOURCE_TYPE:
- RU_V RU_N RU_E RU_SH RU_N RU_I RU_J RU_I RU_S RU_T RU_O RU_CH RU_N RU_I RU_K RU_D RU_A RU_N RU_N RU_Y RU_H
- | E X T E R N A L D A T A S O U R C E;
+ (RU_V RU_N RU_E RU_SH RU_N RU_I RU_J RU_I RU_S RU_T RU_O RU_CH RU_N RU_I RU_K RU_D RU_A RU_N RU_N RU_Y RU_H
+ | E X T E R N A L D A T A S O U R C E) -> pushMode(EXTERNAL_DATA_SOURCE_MODE);
FILTER_CRITERION_TYPE:
RU_K RU_R RU_I RU_T RU_E RU_R RU_I RU_J RU_O RU_T RU_B RU_O RU_R RU_A | F I L T E R C R I T E R I O N;
INFORMATION_REGISTER_TYPE:
@@ -277,6 +305,10 @@ fragment H: 'H' | 'h';
fragment W: 'W' | 'w';
fragment X: 'X' | 'x';
fragment Y: 'Y' | 'y';
+fragment Z: 'Z' | 'z';
+
+fragment NUM_0: '0';
+fragment NUM_1: '1';
// LITERALS
fragment DIGIT: [0-9];
@@ -357,3 +389,13 @@ ID_TASK_TYPE : TASK_TYPE -> type(TASK_TYPE), popMode;
ID_DOT : DOT -> type(DOT), pushMode(DOT_MODE), popMode;
ID_IDENTIFIER : IDENTIFIER -> type(IDENTIFIER), popMode;
ID_UNKNOWN : . -> channel(HIDDEN), type(UNKNOWN);
+
+mode EXTERNAL_DATA_SOURCE_MODE;
+EDS_TABLE: (RU_T RU_A RU_B RU_L RU_I RU_C RU_A | T A B L E) -> popMode;
+EDS_CUBE: (RU_K RU_U RU_B | C U B E);
+EDS_CUBE_DIMTABLE: (RU_T RU_A RU_B RU_L RU_I RU_C RU_A RU_I RU_Z RU_M RU_E RU_R RU_E RU_N RU_I RU_YA
+ | D I M E N S I O N T A B L E) -> popMode;
+EDS_WHITE_SPACE : WHITE_SPACE -> channel(HIDDEN), type(WHITE_SPACE);
+EDS_MUL: MUL -> type(MUL);
+EDS_DOT : DOT -> type(DOT);
+EDS_IDENTIFIER : IDENTIFIER -> type(IDENTIFIER);
diff --git a/src/main/antlr/SDBLParser.g4 b/src/main/antlr/SDBLParser.g4
index 02e71a1c..a80e25fb 100644
--- a/src/main/antlr/SDBLParser.g4
+++ b/src/main/antlr/SDBLParser.g4
@@ -228,6 +228,12 @@ builtInFunctions:
| (doCall=DATEDIFF LPAREN firstdate=expression COMMA seconddate=expression COMMA periodType=(SECOND | MINUTE | HOUR | DAY | MONTH | QUARTER | YEAR) RPAREN)
| (doCall=(VALUETYPE | PRESENTATION | REFPRESENTATION | GROUPEDBY) LPAREN value=expression RPAREN)
| (doCall=ISNULL LPAREN first=logicalExpression COMMA second=logicalExpression RPAREN)
+ | (doCall=(ACOS | ASIN | ATAN | COS | SIN | TAN | LOG | LOG10 | EXP | POW | SQRT | INT) LPAREN decimal=expression RPAREN)
+ | (doCall=(LOWER | STRINGLENGTH | TRIMALL | TRIML | TRIMR | UPPER) LPAREN string=expression RPAREN)
+ | (doCall=ROUND LPAREN decimal=expression COMMA precise=expression RPAREN)
+ | (doCall=(STOREDDATASIZE | UUID) LPAREN value=expression RPAREN)
+ | (doCall=STRFIND LPAREN string=expression COMMA substring1=expression RPAREN)
+ | (doCall=STRREPLACE LPAREN string=expression COMMA substring1=expression COMMA substring1=expression RPAREN)
;
// агрегатные ф-ии
@@ -279,6 +285,7 @@ logicalExpression:
condidions+=predicate
((AND | OR) condidions+=predicate)*
;
+
predicate: NOT* (
booleanPredicate=expression // булево
| likePredicate
@@ -308,7 +315,7 @@ dataSources: tables+=dataSource (COMMA tables+=dataSource)*;
dataSource:
(LPAREN dataSource RPAREN)
| ((
- ((virtualTable | table | parameterTable) alias?)
+ ((virtualTable | table | parameterTable | externalDataSourceTable) alias?)
| (LPAREN (virtualTable | table | parameterTable | subquery) RPAREN alias?)
) joins+=joinPart*)
;
@@ -345,6 +352,10 @@ virtualTableParameter: logicalExpression?;
// таблица как параметр, соединяться ни с чем не может
parameterTable: parameter;
+externalDataSourceTable:
+ mdo DOT EDS_TABLE DOT tableName=identifier
+ | mdo DOT EDS_CUBE DOT cubeName=identifier DOT EDS_CUBE_DIMTABLE DOT tableName=identifier;
+
// соединения таблиц
joinPart:
( // тип соединения
@@ -453,6 +464,43 @@ identifier:
| WEEK
| WEEKDAY
| YEAR
+ | ORDER
+ | GROUP
+ | INDEX
+ | SET
+ | RIGHT
+ | LEFT
+ | INNER
+ | FULL
+ | JOIN
+ | OUTER
+ | FOR
+ | UPDATE
+ | ALL
+ | UNION
+ | ACOS
+ | ASIN
+ | ATAN
+ | COS
+ | SIN
+ | TAN
+ | LOG
+ | LOG10
+ | EXP
+ | POW
+ | SQRT
+ | INT
+ | LOWER
+ | STRINGLENGTH
+ | TRIMALL
+ | TRIML
+ | TRIMR
+ | UPPER
+ | ROUND
+ | STOREDDATASIZE
+ | UUID
+ | STRFIND
+ | STRREPLACE
;
// параметр запроса
diff --git a/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLLexerTest.java b/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLLexerTest.java
index 0c5614f7..d52eae88 100644
--- a/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLLexerTest.java
+++ b/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLLexerTest.java
@@ -135,6 +135,33 @@ void testKeyWords() {
}
+ @Test
+ void testKeyWordsP2() {
+ assertMatch("ЦЕЛ", "int", SDBLLexer.INT);
+ assertMatch("ACOS", "ACOs", SDBLLexer.ACOS);
+ assertMatch("ASIN", "ASIn", SDBLLexer.ASIN);
+ assertMatch("ATAN", "ATaN", SDBLLexer.ATAN);
+ assertMatch("COS", "cOS", SDBLLexer.COS);
+ assertMatch("SIN", "SiN", SDBLLexer.SIN);
+ assertMatch("TAN", "TAn", SDBLLexer.TAN);
+ assertMatch("LOG", "LOg", SDBLLexer.LOG);
+ assertMatch("LOG10", "loG10", SDBLLexer.LOG10);
+ assertMatch("EXP", "EXp", SDBLLexer.EXP);
+ assertMatch("POW", "POw", SDBLLexer.POW);
+ assertMatch("SQRT", "SqRT", SDBLLexer.SQRT);
+ assertMatch("LOWER", "Нрег", SDBLLexer.LOWER);
+ assertMatch("STRINGLENGTH", "ДлинаСТроки", SDBLLexer.STRINGLENGTH);
+ assertMatch("TRIMALL", "Сокрлп", SDBLLexer.TRIMALL);
+ assertMatch("TRIML", "Сокрл", SDBLLexer.TRIML);
+ assertMatch("TRIMR", "СокрП", SDBLLexer.TRIMR);
+ assertMatch("UPPER", "вреГ", SDBLLexer.UPPER);
+ assertMatch("ROUND", "окр", SDBLLexer.ROUND);
+ assertMatch("STOREDDATASIZE", "РазмерХранимыхДанных", SDBLLexer.STOREDDATASIZE);
+ assertMatch("UUID", "УникальныйиДентификатор", SDBLLexer.UUID);
+ assertMatch("STRFIND", "стрнайТи", SDBLLexer.STRFIND);
+ assertMatch("STRREPLACE", "стрЗАМЕнить", SDBLLexer.STRREPLACE);
+ }
+
@Test
void testStandardFields() {
assertMatch("ТочкаМаршрута", "RoutePoint", SDBLLexer.ROUTEPOINT_FIELD);
@@ -177,4 +204,26 @@ void testMDOTT() {
assertMatch(".ДанныеГрафика", ".SCHEDULEDATA", SDBLLexer.DOT, SDBLLexer.SCHEDULE_DATA_VT);
assertMatch(".ЗадачиПоИсполнителю", ".TASKBYPERFORMER", SDBLLexer.DOT, SDBLLexer.TASK_BY_PERFORMER_VT);
}
+
+ @Test
+ void testExternalTypes() {
+ assertMatch("ВнешнийИсточникДанных.ВИД1.Таблица",
+ "ExternalDataSource.EDS1.Table",
+ SDBLLexer.EXTERNAL_DATA_SOURCE_TYPE,
+ SDBLLexer.DOT,
+ SDBLLexer.IDENTIFIER,
+ SDBLLexer.DOT,
+ SDBLLexer.EDS_TABLE);
+ assertMatch("ВнешнийИсточникДанных.ВИД1.Куб.Куб1.ТаблицаИзмерения",
+ "ExternalDataSource.EDS1.Cube.Cube1.DimensionTable",
+ SDBLLexer.EXTERNAL_DATA_SOURCE_TYPE,
+ SDBLLexer.DOT,
+ SDBLLexer.IDENTIFIER,
+ SDBLLexer.DOT,
+ SDBLLexer.EDS_CUBE,
+ SDBLLexer.DOT,
+ SDBLLexer.IDENTIFIER,
+ SDBLLexer.DOT,
+ SDBLLexer.EDS_CUBE_DIMTABLE);
+ }
}
diff --git a/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLParserTest.java b/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLParserTest.java
index c79b794c..e16f3c88 100644
--- a/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLParserTest.java
+++ b/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLParserTest.java
@@ -300,6 +300,31 @@ void testSelect05() {
);
}
+ @Test
+ void testSelect06() {
+ checkSource("src/test/resources/sdbl/select06.sdbl",
+ pair(SDBLParser.RULE_queries, 4),
+ pair(SDBLParser.RULE_dataSource, 4)
+ );
+ }
+
+ @Test
+ void testSelect07() {
+ checkSource("src/test/resources/sdbl/select07.sdbl",
+ pair(SDBLParser.RULE_queries, 1),
+ pair(SDBLParser.RULE_dataSource, 1)
+ );
+ }
+
+ @Test
+ void testSelect08() {
+ checkSource("src/test/resources/sdbl/select08.sdbl",
+ pair(SDBLParser.RULE_queries, 1),
+ pair(SDBLParser.RULE_dataSource, 1),
+ pair(SDBLParser.RULE_builtInFunctions, 35)
+ );
+ }
+
private void checkSource(String filePath, Pair... rules) {
var exampleString = TestUtils.getSourceFromFile(filePath);
setInput(exampleString);
diff --git a/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLTokenizerTest.java b/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLTokenizerTest.java
index ecef5215..122fa9c5 100644
--- a/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLTokenizerTest.java
+++ b/src/test/java/com/github/_1c_syntax/bsl/parser/SDBLTokenizerTest.java
@@ -24,6 +24,7 @@
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Token;
import org.junit.jupiter.api.Test;
+import utils.TestUtils;
import java.util.List;
@@ -62,5 +63,4 @@ void computeAST() {
assertThat(query.getStart().getType()).isEqualTo(SDBLParser.SELECT);
assertThat(query.getStop().getType()).isEqualTo(SDBLParser.IDENTIFIER);
}
-
}
\ No newline at end of file
diff --git a/src/test/resources/sdbl/select06.sdbl b/src/test/resources/sdbl/select06.sdbl
new file mode 100644
index 00000000..b3484e8e
--- /dev/null
+++ b/src/test/resources/sdbl/select06.sdbl
@@ -0,0 +1,19 @@
+ВЫБРАТЬ
+timestamp
+ИЗ
+ВнешнийИсточникДанных.ClickHouse.Таблица.test01_log
+;
+SELECT
+timestamp
+FROM
+ExternalDataSource.ClickHouse.Table.test01_log
+;
+ВЫБРАТЬ
+Поле1 КАК Поле1
+ИЗ
+ВнешнийИсточникДанных.ВнешнийИсточникДанных1.Куб.Куб1.ТаблицаИзмерения.ТаблицаИзмерения1
+;
+SELECT
+Cube1DimensionTableDimensionTable1.Ref AS Ref
+FROM
+ExternalDataSource.ExternalDataSource1.Cube.Cube1.DimensionTable.DimensionTable1 AS Cube1DimensionTableDimensionTable1
\ No newline at end of file
diff --git a/src/test/resources/sdbl/select07.sdbl b/src/test/resources/sdbl/select07.sdbl
new file mode 100644
index 00000000..3ba9b0a1
--- /dev/null
+++ b/src/test/resources/sdbl/select07.sdbl
@@ -0,0 +1,2 @@
+ВЫБРАТЬ *
+ИЗ РегистрСведений.Таблица КАК Таблица
diff --git a/src/test/resources/sdbl/select08.sdbl b/src/test/resources/sdbl/select08.sdbl
new file mode 100644
index 00000000..6a6dc03d
--- /dev/null
+++ b/src/test/resources/sdbl/select08.sdbl
@@ -0,0 +1,37 @@
+ВЫБРАТЬ
+ ЦЕЛ(СРЕДНЕЕ(Таблица.Поле)) КАК Цел,
+ INT(СРЕДНЕЕ(Таблица.Поле)) КАК INT,
+ ACOS(Таблица.Поле) КАК ACOS,
+ ASIN(Таблица.Поле) КАК ASIN,
+ ATAN(Таблица.Поле) КАК ATAN,
+ COS(Таблица.Поле) КАК COS,
+ SIN(Таблица.Поле) КАК SIN,
+ TAN(Таблица.Поле) КАК TAN,
+ LOG(Таблица.Поле) КАК LOG,
+ LOG10(Таблица.Поле) КАК LOG10,
+ EXP(Таблица.Поле) КАК EXP,
+ POW(Таблица.Поле) КАК POW,
+ SQRT(Таблица.Поле) КАК SQRT,
+ LOWER(Таблица.Поле) КАК LOWER,
+ НРЕГ(Таблица.Поле) КАК НРЕГ,
+ STRINGLENGTH(Таблица.Поле) КАК STRINGLENGTH,
+ ДЛИНАСТРОКИ(Таблица.Поле) КАК СТРДЛИНА,
+ TRIMALL(Таблица.Поле) КАК TRIMALL,
+ СОКРЛП(Таблица.Поле) КАК СОКРЛП,
+ TRIML(Таблица.Поле) КАК TRIML,
+ СОКРЛ(Таблица.Поле) КАК СОКРЛ,
+ TRIMR(Таблица.Поле) КАК TRIMR,
+ СОКРП(Таблица.Поле) КАК СОКРП,
+ UPPER(Таблица.Поле) КАК UPPER,
+ ВРЕГ(Таблица.Поле) КАК ВРЕГ,
+ ROUND(Таблица.Поле, Таблица.Поле2) КАК ROUND,
+ ОКР(Таблица.Поле, Таблица.Поле2) КАК ОКР,
+ STOREDDATASIZE(Таблица.Поле) КАК STOREDDATASIZE,
+ РазмерХранимыхДанных(Таблица.Поле) КАК РазмерХранимыхДанных,
+ UUID(Таблица.Поле) КАК UUID,
+ УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Таблица.Поле) КАК УНИКАЛЬНЫЙИДЕНТИФИКАТОР,
+ STRFIND(Таблица.Поле, Таблица.Поле2) КАК STRFIND,
+ СтрНайти(Таблица.Поле, Таблица.Поле2) КАК СтрНайти,
+ STRREPLACE(Таблица.Поле, Таблица.Поле2, Таблица.Поле3) КАК STRREPLACE,
+ СтрЗаменить(Таблица.Поле, Таблица.Поле2, Таблица.Поле3) КАК СтрЗаменить
+ИЗ РегистрСведений.Таблица КАК Таблица