diff --git a/.circleci/config.yml b/.circleci/config.yml index d64b30d92b..56d30b10c9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,20 +1,14 @@ version: 2.1 jobs: - test_tool_and_runtime_java: + test_tool: docker: - image: cimg/openjdk:11.0 steps: - checkout - run: - name: build tool + name: Build ANTLR4 command: mvn -B -V -DskipTests=true -Dmaven.javadoc.skip=true install - - run: - name: test runtime - command: | - cd runtime-testsuite - mvn -Dtest=java.** test - cd .. - run: name: test tool command: | @@ -38,27 +32,39 @@ jobs: parallelism: 4 resource_class: large environment: - TARGET: << parameters.target >> - GROUP: << parameters.test-group >> + TARGET: <> + GROUP: <> steps: - checkout - run: - name: Install << parameters.target >> pre-requisites + name: Install <> pre-requisites command: | - f=".circleci/scripts/install-linux-<< parameters.target >>.sh"; ! [ -x "$f" ] || "$f" + set -euo pipefail + f=".circleci/scripts/install-linux-<>.sh"; ! [ -x "$f" ] || "$f" - run: - name: Build ANTLR4 tool + name: Build ANTLR4 command: mvn -B -V -DskipTests=true -Dmaven.javadoc.skip=true install - run: - name: Test << parameters.target >> runtime + name: Test <> runtime + command: | + set -euo pipefail + if [ "<>" == "swift" ] + then + export PATH=$PATH:/usr/share/swift/usr/bin + fi + pushd runtime-testsuite + mvn -Dtest=<>.** test + popd + - run: + name: Extra tests of <> runtime command: | - .circleci/scripts/run-tests-<< parameters.target >>.sh + f=".circleci/scripts/run-tests-<>.sh"; ! [ -x "$f" ] || "$f" workflows: build: jobs: - - test_tool_and_runtime_java + - test_tool - test_runtime: matrix: parameters: - target: [ dart, go, python2, python3, javascript, php, cpp, dotnet ] + target: [ java, csharp, python2, python3, javascript, cpp, go, swift, php, dart ] diff --git a/.circleci/scripts/install-linux-cpp.sh b/.circleci/scripts/install-linux-cpp.sh index caec701912..3f10ef2807 100755 --- a/.circleci/scripts/install-linux-cpp.sh +++ b/.circleci/scripts/install-linux-cpp.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - echo "installing cpp SDK..." sudo apt-get update -y diff --git a/.circleci/scripts/install-linux-dotnet.sh b/.circleci/scripts/install-linux-csharp.sh similarity index 56% rename from .circleci/scripts/install-linux-dotnet.sh rename to .circleci/scripts/install-linux-csharp.sh index a20dc796e3..21047b4830 100755 --- a/.circleci/scripts/install-linux-dotnet.sh +++ b/.circleci/scripts/install-linux-csharp.sh @@ -1,14 +1,11 @@ #!/bin/bash -set -euo pipefail - echo "installing .Net SDK..." -wget https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb +rm packages-microsoft-prod.deb sudo apt-get update; \ sudo apt-get install -y apt-transport-https && \ sudo apt-get update && \ - sudo apt-get install -y dotnet-sdk-3.1 -export PATH=$PATH:~/.dotnet -echo "done installing .Net SDK" - + sudo apt-get install -y dotnet-sdk-6.0 +echo "done installing .Net SDK" \ No newline at end of file diff --git a/.circleci/scripts/install-linux-dart.sh b/.circleci/scripts/install-linux-dart.sh index 25e857606b..787ad2e218 100755 --- a/.circleci/scripts/install-linux-dart.sh +++ b/.circleci/scripts/install-linux-dart.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - echo "installing dart SDK..." sudo apt-get update sudo apt-get install apt-transport-https @@ -9,6 +7,5 @@ sudo sh -c 'wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | ap sudo sh -c 'wget -qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list' sudo apt-get update sudo apt-get install dart=2.12.1-1 -export PATH="$PATH:/usr/lib/dart/bin" echo "done installing dart SDK" sudo apt-get install -f diff --git a/.circleci/scripts/install-linux-go.sh b/.circleci/scripts/install-linux-go.sh index 363e090950..0b11c9c4a8 100755 --- a/.circleci/scripts/install-linux-go.sh +++ b/.circleci/scripts/install-linux-go.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - echo "installing go SDK..." sudo apt update sudo apt install golang-go diff --git a/.circleci/scripts/install-linux-javascript.sh b/.circleci/scripts/install-linux-javascript.sh index 2b8c8912a1..bd1e1e0a7c 100755 --- a/.circleci/scripts/install-linux-javascript.sh +++ b/.circleci/scripts/install-linux-javascript.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - # use v14 and check echo "installing nodejs..." curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - @@ -10,8 +8,8 @@ echo node version: $(node --version) echo "done installing nodejs" echo "packaging javascript runtime..." -pushd runtime/JavaScript +pushd runtime/JavaScript || exit sudo npm install sudo npm link -popd +popd || exit echo "done packaging javascript runtime" diff --git a/.circleci/scripts/install-linux-libcurl3.sh b/.circleci/scripts/install-linux-libcurl3.sh deleted file mode 100755 index 6fe59bafac..0000000000 --- a/.circleci/scripts/install-linux-libcurl3.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -echo "before patching" -ls -all /lib/x86_64-linux-gnu/ | grep libcurl - -# This would fix missing CURL_OPENSSL_3 -# use a dedicated temp dir in the user space -mkdir ~/libcurl3 -cd ~/libcurl3 -# fetch latest libcurl3 -wget http://archive.ubuntu.com/ubuntu/pool/main/c/curl/libcurl3_7.47.0-1ubuntu2_amd64.deb -# extract data.tar.xz -ar x libcurl3* data.tar.xz -# extract all from data.tar.xz -tar xf data.tar.xz -# copy libcurl.so.3 where required -sudo cp -L ~/libcurl3/usr/lib/x86_64-linux-gnu/libcurl.so.4.4.0 /lib/x86_64-linux-gnu/libcurl.so.4.4.0 -sudo ln -sf libcurl.so.4.4.0 /lib/x86_64-linux-gnu/libcurl.so.4 -cd .. -# drop dedicated temp dir -sudo rm -rf ~/libcurl3 - -echo "after patching" -ls -all /lib/x86_64-linux-gnu/ | grep libcurl diff --git a/.circleci/scripts/install-linux-php.sh b/.circleci/scripts/install-linux-php.sh index 4127d1ce61..4a60550056 100755 --- a/.circleci/scripts/install-linux-php.sh +++ b/.circleci/scripts/install-linux-php.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - sudo apt install software-properties-common sudo add-apt-repository ppa:ondrej/php sudo apt update @@ -15,8 +13,5 @@ sudo apt install php8.0-mbstring sudo apt install php8.0-xml php -v - git clone https://github.com/antlr/antlr-php-runtime.git runtime/PHP -composer install -d runtime/PHP - -mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V \ No newline at end of file +composer install -d runtime/PHP \ No newline at end of file diff --git a/.circleci/scripts/install-linux-python2.sh b/.circleci/scripts/install-linux-python2.sh index 5549c1b9c3..ae9e75addf 100755 --- a/.circleci/scripts/install-linux-python2.sh +++ b/.circleci/scripts/install-linux-python2.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - echo "installing python 2..." sudo apt-get update -y sudo apt-get install python2 diff --git a/.circleci/scripts/install-linux-python3.sh b/.circleci/scripts/install-linux-python3.sh index 4c90f519ca..e2c74d704e 100755 --- a/.circleci/scripts/install-linux-python3.sh +++ b/.circleci/scripts/install-linux-python3.sh @@ -1,7 +1,5 @@ #!/bin/bash -set -euo pipefail - echo "installing python 3..." sudo apt-get update -y sudo apt-get install python3 diff --git a/.circleci/scripts/install-linux-swift.sh b/.circleci/scripts/install-linux-swift.sh index 7390175657..dc14a375e2 100755 --- a/.circleci/scripts/install-linux-swift.sh +++ b/.circleci/scripts/install-linux-swift.sh @@ -1,36 +1,19 @@ #!/bin/bash -set -euo pipefail - echo "installing swift SDK..." -.circleci/scripts/install-linux-libcurl3.sh +sudo apt update && sudo apt upgrade +sudo apt install binutils git gnupg2 libc6-dev libcurl4 libedit2 libgcc-9-dev libpython2.7 libsqlite3-0 libstdc++-9-dev libxml2 libz3-dev pkg-config tzdata zlib1g-dev -# see https://tecadmin.net/install-swift-ubuntu-1604-xenial/ -sudo apt-get update -y -sudo apt-get install clang libicu-dev -sudo apt-get install libpython2.7 libpython2.7-dev +wget https://download.swift.org/swift-5.6.2-release/ubuntu2004/swift-5.6.2-RELEASE/swift-5.6.2-RELEASE-ubuntu20.04.tar.gz -export SWIFT_VERSION=swift-5.3.2 -echo "installing gpg key..." -wget -q -O - https://swift.org/keys/all-keys.asc | sudo gpg --import - -echo "downloading SDK gpg key..." -SWIFT_SDK=https://swift.org/builds/$SWIFT_VERSION-release/ubuntu1604/$SWIFT_VERSION-RELEASE/$SWIFT_VERSION-RELEASE-ubuntu16.04.tar.gz -echo $SWIFT_SDK -wget -q $SWIFT_SDK -sudo tar xzf $SWIFT_VERSION-RELEASE-ubuntu16.04.tar.gz -mv $SWIFT_VERSION-RELEASE-ubuntu16.04 $PWD/swift +tar xzf swift-5.6.2-RELEASE-ubuntu20.04.tar.gz -export SWIFT_HOME=$PWD/swift/$SWIFT_VERSION-RELEASE-ubuntu16.04/usr/bin/ -export PATH=$PWD/swift/usr/bin:$PATH +sudo mv swift-5.6.2-RELEASE-ubuntu20.04 /usr/share/swift -# This would fix a know linker issue mentioned in: # https://bugs.swift.org/browse/SR-2299 -sudo ln -sf ld.gold /usr/bin/ld -# This would fix missing libtinfo.so.5 -sudo apt install libncurses5 +export PATH=$PATH:/usr/share/swift/usr/bin echo "done installing swift SDK..." # check swift swift --version -swift build --version diff --git a/.circleci/scripts/run-tests-cpp.sh b/.circleci/scripts/run-tests-cpp.sh deleted file mode 100755 index 464c54c395..0000000000 --- a/.circleci/scripts/run-tests-cpp.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -pushd runtime-testsuite -export MAVEN_OPTS="-Xmx8g" -mvn -Dtest=cpp.** test -popd diff --git a/.circleci/scripts/run-tests-dart.sh b/.circleci/scripts/run-tests-dart.sh deleted file mode 100755 index 0de26275ef..0000000000 --- a/.circleci/scripts/run-tests-dart.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -dart --version - -pushd runtime-testsuite - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=dart.** test -popd diff --git a/.circleci/scripts/run-tests-dotnet.sh b/.circleci/scripts/run-tests-dotnet.sh deleted file mode 100755 index a607fab7c0..0000000000 --- a/.circleci/scripts/run-tests-dotnet.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -pushd runtime-testsuite -export MAVEN_OPTS="-Xmx8g" -mvn -Dtest=csharp.** test -popd diff --git a/.circleci/scripts/run-tests-go.sh b/.circleci/scripts/run-tests-go.sh deleted file mode 100755 index 87300f3e92..0000000000 --- a/.circleci/scripts/run-tests-go.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -go version - -pushd runtime-testsuite - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=go.** test -popd diff --git a/.circleci/scripts/run-tests-javascript.sh b/.circleci/scripts/run-tests-javascript.sh index b0b461fce0..df2d45397f 100755 --- a/.circleci/scripts/run-tests-javascript.sh +++ b/.circleci/scripts/run-tests-javascript.sh @@ -1,24 +1,11 @@ #!/bin/bash -set -euo pipefail - declare -i RESULT=0 -pushd runtime/JavaScript - +pushd runtime/JavaScript || exit echo "running jasmine tests..." npm test RESULT+=$? - -popd - -pushd runtime-testsuite - - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=javascript.** test - RESULT+=$? - -popd +popd || exit exit $RESULT diff --git a/.circleci/scripts/run-tests-php.sh b/.circleci/scripts/run-tests-php.sh deleted file mode 100755 index d28d2924c3..0000000000 --- a/.circleci/scripts/run-tests-php.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -php -v - -php_path=$(which php) -pushd runtime-testsuite - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=php.** test -popd diff --git a/.circleci/scripts/run-tests-python2.sh b/.circleci/scripts/run-tests-python2.sh index 8e2d96fe09..f0ea2637d9 100755 --- a/.circleci/scripts/run-tests-python2.sh +++ b/.circleci/scripts/run-tests-python2.sh @@ -1,9 +1,5 @@ #!/bin/bash -set -euo pipefail - -python2 --version - # TODO: https://github.com/antlr/antlr4/issues/3521 # # pushd runtime/Python2/tests @@ -14,9 +10,3 @@ python2 --version # echo "failed running native tests" # fi # popd - -pushd runtime-testsuite - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=python2.** test -popd \ No newline at end of file diff --git a/.circleci/scripts/run-tests-python3.sh b/.circleci/scripts/run-tests-python3.sh index 10a9cc7288..8dd949ecdc 100755 --- a/.circleci/scripts/run-tests-python3.sh +++ b/.circleci/scripts/run-tests-python3.sh @@ -1,9 +1,5 @@ #!/bin/bash -set -euo pipefail - -python3 --version - # TODO: https://github.com/antlr/antlr4/issues/3521 # # pushd runtime/Python3/tests @@ -14,9 +10,3 @@ python3 --version # echo "failed running native tests" # fi # popd - -pushd runtime-testsuite - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=python3.** test -popd diff --git a/.circleci/scripts/run-tests-swift.sh b/.circleci/scripts/run-tests-swift.sh index 850729d5ef..8613acdf66 100755 --- a/.circleci/scripts/run-tests-swift.sh +++ b/.circleci/scripts/run-tests-swift.sh @@ -1,9 +1,5 @@ #!/bin/bash -# Appears to be unused - -set -euo pipefail - # TODO: https://github.com/antlr/antlr4/issues/3521 # # pushd runtime/Swift @@ -14,9 +10,3 @@ set -euo pipefail # echo "failed running native tests" # fi # popd - -pushd runtime-testsuite - echo "running maven tests..." - export MAVEN_OPTS="-Xmx8g" - mvn -Dtest=swift.** test -popd diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 71028e1045..2c03b3a7e1 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -43,13 +43,11 @@ jobs: uses: actions/setup-node@v2 with: node-version: '14' - - name: Setup Dotnet 3.1 and 5.0 + - name: Setup Dotnet if: matrix.TARGET == 'csharp' uses: actions/setup-dotnet@v1 with: - dotnet-version: | - 3.1.x - 5.0.x + dotnet-version: '6.0.x' # fails due to os (Linux only), use global install # - name: Setup Dart 2.12.1 # uses: dart-lang/setup-dart@v1 diff --git a/.gitignore b/.gitignore index 5c99ef58d6..8aa0baecdf 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,8 @@ __pycache__/ *.userosscache *.sln.docstates -# User-specific files (MonoDevelop/Xamarin Studio) +# User-specific files (MonoDevelop/Xamarin Studio/Visual Studio) *.userprefs -*.user .vs/ project.lock.json @@ -47,9 +46,6 @@ bld/ [Oo]bj/ [Ll]og/ -# Visual Studio 2015 cache/options directory -.vs/ - # NetBeans user configuration files nbactions*.xml /nbproject/private/ @@ -102,3 +98,6 @@ javac-services.0.log.lck !runtime/Python3/test/ Antlr4.sln runtime/PHP + +# Swift binaries +.build/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 33db1610db..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -sudo: true - -language: java - -before_cache: - - rm -rf $HOME/.m2/repository/org/antlr -cache: - timeout: 600 - directories: - - $HOME/.m2 - - $HOME/Library/Caches/Antlr4 - - $HOME/Library/Caches/Homebrew - -stages: -# - smoke-test -# - main-test - - extended-test - -matrix: - include: - - os: linux - dist: xenial - compiler: clang - env: - - TARGET=swift - - GROUP=ALL - stage: extended-test - -before_install: - - f="./.travis/before-install-$TRAVIS_OS_NAME-$TARGET.sh"; ! [ -x "$f" ] || "$f" - -script: - - | - cd runtime-testsuite; - travis_wait 40 ../.travis/run-tests-$TARGET.sh - rc=$? - cat target/surefire-reports/*.dumpstream || true - exit $rc diff --git a/runtime-testsuite/pom.xml b/runtime-testsuite/pom.xml index 5e379d9ab4..189714b33b 100644 --- a/runtime-testsuite/pom.xml +++ b/runtime-testsuite/pom.xml @@ -123,18 +123,4 @@ - - - - includeSwiftTests - - - mac - - - - **/swift/Test*.java - - - diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Antlr4.Test.csproj.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Antlr4.Test.csproj.stg index 371c9dd766..aa1073c574 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Antlr4.Test.csproj.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Antlr4.Test.csproj.stg @@ -1,7 +1,7 @@ \ \ - \netcoreapp3.1\ + \net6.0\ \$(NoWarn);CS3021\ \Test\ \Exe\ diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Package.swift.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Package.swift.stg new file mode 100644 index 0000000000..43ad150307 --- /dev/null +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Package.swift.stg @@ -0,0 +1,11 @@ +// swift-tools-version: 5.6 + +import PackageDescription + +let package = Package( + name: "Test", + targets: [ + .executableTarget(name: "Test", path: ".", + exclude:[ "}; separator = ", ", wrap> ]), + ] +) diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Test.vcxproj.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Test.vcxproj.stg index 5a3822b41e..aefd731b6d 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Test.vcxproj.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/Test.vcxproj.stg @@ -18,7 +18,7 @@ \ \Application\ \false\ - \\ + \v143\ \false\ \ \Unicode\ \ diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/main.swift.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/main.swift.stg index 8fd8061ef3..3d43f33640 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/main.swift.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/helpers/main.swift.stg @@ -1,6 +1,5 @@ import Antlr4 import Foundation -setbuf(stdout, nil) class TreeShapeListener: ParseTreeListener{ diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java index 2a7e659392..7e48a355e5 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeRunner.java @@ -44,6 +44,39 @@ public abstract class RuntimeRunner implements AutoCloseable { protected String grammarNameToFileName(String grammarName) { return grammarName; } + private static String runtimeToolPath; + private static String compilerPath; + + protected final String getCompilerPath() { + if (compilerPath == null) { + compilerPath = getCompilerName(); + if (compilerPath != null) { + String compilerPathFromProperty = System.getProperty(getPropertyPrefix() + "-compiler"); + if (compilerPathFromProperty != null && compilerPathFromProperty.length() > 0) { + compilerPath = compilerPathFromProperty; + } + } + } + + return compilerPath; + } + + protected final String getRuntimeToolPath() { + if (runtimeToolPath == null) { + runtimeToolPath = getRuntimeToolName(); + if (runtimeToolPath != null) { + String runtimeToolPathFromProperty = System.getProperty(getPropertyPrefix() + "-exec"); + if (runtimeToolPathFromProperty != null && runtimeToolPathFromProperty.length() > 0) { + runtimeToolPath = runtimeToolPathFromProperty; + } + } + } + + return runtimeToolPath; + } + + protected String getCompilerName() { return null; } + protected String getRuntimeToolName() { return getLanguage().toLowerCase(); } protected String getTestFileWithExt() { return getTestFileName() + "." + getExtension(); } @@ -89,13 +122,11 @@ public void close() { removeTempTestDirIfRequired(); } - private final static Object runtimeInitLockObject = new Object(); - public final static String cacheDirectory; private static class InitializationStatus { public final Object lockObject = new Object(); - public Boolean isInitialized; + public volatile Boolean isInitialized; public Exception exception; } @@ -209,16 +240,14 @@ protected void addExtraRecognizerParameters(ST template) {} private boolean initAntlrRuntimeIfRequired() { String language = getLanguage(); - InitializationStatus status = runtimeInitializationStatuses.get(language); + InitializationStatus status; // Create initialization status for every runtime with lock object - if (status == null) { - synchronized (runtimeInitLockObject) { - status = runtimeInitializationStatuses.get(language); - if (status == null) { - status = new InitializationStatus(); - runtimeInitializationStatuses.put(language, status); - } + synchronized (runtimeInitializationStatuses) { + status = runtimeInitializationStatuses.get(language); + if (status == null) { + status = new InitializationStatus(); + runtimeInitializationStatuses.put(language, status); } } @@ -256,9 +285,9 @@ protected ExecutedState execute(RunOptions runOptions, CompiledState compiledSta Exception exception = null; try { List args = new ArrayList<>(); - String runtimeToolName = getRuntimeToolName(); - if (runtimeToolName != null) { - args.add(runtimeToolName); + String runtimeToolPath = getRuntimeToolPath(); + if (runtimeToolPath != null) { + args.add(runtimeToolPath); } String[] extraRunArgs = getExtraRunArgs(); if (extraRunArgs != null) { @@ -294,7 +323,7 @@ private void removeTempTestDirIfRequired() { try { deleteDirectory(dirFile); } catch (IOException e) { - throw new RuntimeException(e); + e.printStackTrace(); } } } diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/CppRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/CppRunner.java index 344064fa55..5159891095 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/CppRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/CppRunner.java @@ -10,7 +10,6 @@ import org.antlr.v4.test.runtime.states.GeneratedState; import org.stringtemplate.v4.ST; -import java.io.File; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; @@ -34,21 +33,17 @@ public String getLanguage() { private static final String runtimeSourcePath; private static final String runtimeBinaryPath; private static final String runtimeLibraryFileName; - private static final String compilerPath; + private static String compilerName; private static final String visualStudioProjectContent; - private static String visualStudioVersion; - private static String visualStudioPlatformToolset; private static final Map environment; static { - compilerPath = initCompilerFileName(); - String runtimePath = getRuntimePath("Cpp"); runtimeSourcePath = Paths.get(runtimePath, "runtime", "src").toString(); environment = new HashMap<>(); if (isWindows()) { - runtimeBinaryPath = Paths.get(runtimePath, "runtime", "bin", "vs-" + visualStudioVersion, "x64", "Release DLL").toString(); + runtimeBinaryPath = Paths.get(runtimePath, "runtime", "bin", "vs-2022", "x64", "Release DLL").toString(); runtimeLibraryFileName = Paths.get(runtimeBinaryPath, "antlr4-runtime.dll").toString(); String path = System.getenv("PATH"); environment.put("PATH", path == null ? runtimeBinaryPath : path + ";" + runtimeBinaryPath); @@ -67,56 +62,18 @@ public String getLanguage() { } } - private static String initCompilerFileName() { - if (isWindows()) { - visualStudioPlatformToolset = "v143"; - visualStudioVersion = "2022"; - String[] visualStudioVersions = new String[]{"2022", "2019"}; - String[] visualStudioEditions = new String[]{"BuildTools", "Community", "Professional", "Enterprise"}; - String[] programFilesPaths = new String[]{"Program Files", "Program Files (x86)"}; - - for (String version : visualStudioVersions) { - for (String edition : visualStudioEditions) { - for (String programFilesPath : programFilesPaths) { - String file = "C:\\" + programFilesPath + "\\Microsoft Visual Studio\\" + version + "\\" - + edition + "\\Msbuild\\Current\\Bin\\MSBuild.exe"; - if (new File(file).exists()) { - visualStudioPlatformToolset = version.equals("2022") ? "v143" : "v142"; - visualStudioVersion = version; - return file; - } - } - } + @Override + protected String getCompilerName() { + if (compilerName == null) { + if (isWindows()) { + compilerName = "MSBuild"; + } + else { + compilerName = "clang++"; } - return "MSBuild"; - } - else { - return "clang++"; } - } - @Override - protected void writeRecognizerFile(RunOptions runOptions) { - super.writeRecognizerFile(runOptions); - if (isWindows()) { - writeVisualStudioProjectFile(runOptions.grammarName, runOptions.lexerName, runOptions.parserName, - runOptions.useListener, runOptions.useVisitor); - } - } - - private void writeVisualStudioProjectFile(String grammarName, String lexerName, String parserName, - boolean useListener, boolean useVisitor - ) { - ST projectFileST = new ST(visualStudioProjectContent); - projectFileST.add("platformToolset", visualStudioPlatformToolset); - projectFileST.add("runtimeSourcePath", runtimeSourcePath); - projectFileST.add("runtimeBinaryPath", runtimeBinaryPath); - projectFileST.add("grammarName", grammarName); - projectFileST.add("lexerName", lexerName); - projectFileST.add("parserName", parserName); - projectFileST.add("useListener", useListener); - projectFileST.add("useVisitor", useVisitor); - writeFile(getTempDirPath(), "Test.vcxproj", projectFileST.render()); + return compilerName; } @Override @@ -125,10 +82,7 @@ protected void initRuntime() throws Exception { if (isWindows()) { String[] command = { - compilerPath, - "antlr4cpp-vs" + visualStudioVersion + ".vcxproj", - "/p:configuration=Release DLL", - "/p:platform=x64" + getCompilerPath(), "antlr4cpp-vs2022.vcxproj", "/p:configuration=Release DLL", "/p:platform=x64" }; runCommand(command, runtimePath + "\\runtime","build c++ ANTLR runtime using MSBuild"); @@ -144,6 +98,11 @@ protected void initRuntime() throws Exception { @Override protected CompiledState compile(RunOptions runOptions, GeneratedState generatedState) { + if (isWindows()) { + writeVisualStudioProjectFile(runOptions.grammarName, runOptions.lexerName, runOptions.parserName, + runOptions.useListener, runOptions.useVisitor); + } + Exception exception = null; try { if (!isWindows()) { @@ -152,7 +111,7 @@ protected CompiledState compile(RunOptions runOptions, GeneratedState generatedS } List buildCommand = new ArrayList<>(); - buildCommand.add(compilerPath); + buildCommand.add(getCompilerPath()); if (isWindows()) { buildCommand.add(getTestFileName() + ".vcxproj"); buildCommand.add("/p:configuration=Release"); @@ -179,6 +138,19 @@ protected CompiledState compile(RunOptions runOptions, GeneratedState generatedS return new CompiledState(generatedState, exception); } + private void writeVisualStudioProjectFile(String grammarName, String lexerName, String parserName, + boolean useListener, boolean useVisitor) { + ST projectFileST = new ST(visualStudioProjectContent); + projectFileST.add("runtimeSourcePath", runtimeSourcePath); + projectFileST.add("runtimeBinaryPath", runtimeBinaryPath); + projectFileST.add("grammarName", grammarName); + projectFileST.add("lexerName", lexerName); + projectFileST.add("parserName", parserName); + projectFileST.add("useListener", useListener); + projectFileST.add("useVisitor", useVisitor); + writeFile(getTempDirPath(), "Test.vcxproj", projectFileST.render()); + } + @Override public String getRuntimeToolName() { return null; diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/csharp/CSharpRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/csharp/CSharpRunner.java index c2126533d4..22c77674fa 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/csharp/CSharpRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/csharp/CSharpRunner.java @@ -48,7 +48,7 @@ protected void initRuntime() throws Exception { String cachePath = getCachePath(); mkdir(cachePath); String projectPath = Paths.get(getRuntimePath(), "src", "Antlr4.csproj").toString(); - String[] args = new String[]{"dotnet", "build", projectPath, "-c", "Release", "-o", cachePath}; + String[] args = new String[]{getRuntimeToolPath(), "build", projectPath, "-c", "Release", "-o", cachePath}; runCommand(args, cachePath, "build " + getTitleName() + " ANTLR runtime"); } @@ -57,7 +57,7 @@ public CompiledState compile(RunOptions runOptions, GeneratedState generatedStat Exception exception = null; try { writeFile(getTempDirPath(), testProjectFileName, cSharpTestProjectContent); - runCommand(new String[]{"dotnet", "build", testProjectFileName, "-c", "Release"}, getTempDirPath(), + runCommand(new String[]{getRuntimeToolPath(), "build", testProjectFileName, "-c", "Release"}, getTempDirPath(), "build C# test binary"); } catch (Exception e) { exception = e; diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/dart/DartRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/dart/DartRunner.java index 0a573599b6..929c9fa7ef 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/dart/DartRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/dart/DartRunner.java @@ -34,7 +34,7 @@ protected void initRuntime() throws Exception { writeFile(cachePath, "pubspec.yaml", projectTemplate.render()); - runCommand(new String[]{"dart", "pub", "get"}, cachePath); + runCommand(new String[]{getRuntimeToolPath(), "pub", "get"}, cachePath); cacheDartPackageConfig = readFile(cachePath + FileSeparator + ".dart_tool", "package_config.json"); } diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/go/GoRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/go/GoRunner.java index c5408680b2..76441d3271 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/go/GoRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/go/GoRunner.java @@ -77,7 +77,7 @@ protected String grammarParseRuleToRecognizerName(String startRuleName) { @Override protected void initRuntime() throws Exception { - String goRoot = runCommand(new String[]{"go", "env", "GOROOT"}, null, "get GO root").output.trim(); + String goRoot = runCommand(new String[]{getRuntimeToolPath(), "env", "GOROOT"}, null, "get GO root").output.trim(); try { File newGoRootDirectory = newGoRoot.toFile(); @@ -87,7 +87,7 @@ protected void initRuntime() throws Exception { String packageDir = Paths.get(newGoRootString, "src", antlrTestPackageName).toString(); FileUtils.mkdir(packageDir); - File[] runtimeFiles = Paths.get(getRuntimePath("Go"), "antlr").toFile().listFiles(new GoFileFilter()); + File[] runtimeFiles = Paths.get(getRuntimePath("Go"), "antlr").toFile().listFiles(GoFileFilter.Instance); if (runtimeFiles == null) { throw new Exception("Go runtime file list is empty."); } @@ -103,7 +103,7 @@ protected void initRuntime() throws Exception { try { new File(newGoRootString, goModFileName).deleteOnExit(); - Processor.run(new String[]{"go", "mod", "init", "test"}, newGoRootString); + Processor.run(new String[]{getRuntimeToolPath(), "mod", "init", "test"}, newGoRootString); goModContent = new String(Files.readAllBytes(Paths.get(newGoRootString, goModFileName)), StandardCharsets.UTF_8); } catch (InterruptedException | IOException e) { throw new RuntimeException(e); @@ -111,6 +111,8 @@ protected void initRuntime() throws Exception { } static class GoFileFilter implements FilenameFilter { + public final static GoFileFilter Instance = new GoFileFilter(); + public boolean accept(File dir, String name) { return name.endsWith(".go"); } diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/java/JavaRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/java/JavaRunner.java index 01b143934d..b78b2bf1d8 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/java/JavaRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/java/JavaRunner.java @@ -63,6 +63,11 @@ protected void initRuntime() { compiler = ToolProvider.getSystemJavaCompiler(); } + @Override + protected String getCompilerName() { + return "javac"; + } + @Override protected JavaCompiledState compile(RunOptions runOptions, GeneratedState generatedState) { String tempTestDir = getTempDirPath(); diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/python/PythonRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/python/PythonRunner.java index 66f6637b19..90085af5a7 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/python/PythonRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/python/PythonRunner.java @@ -12,16 +12,6 @@ public abstract class PythonRunner extends RuntimeRunner { @Override public String getExtension() { return "py"; } - @Override - public String getRuntimeToolName() { - String toolFileName = System.getProperty(getPropertyPrefix() + "-exec"); - if (toolFileName != null && toolFileName.length() > 0) { - return toolFileName; - } - - return getLanguage().toLowerCase(); - } - @Override protected void addExtraRecognizerParameters(ST template) { template.add("python3", getLanguage().equals("Python3")); diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/swift/SwiftRunner.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/swift/SwiftRunner.java index 624d4605da..1295227774 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/swift/SwiftRunner.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/swift/SwiftRunner.java @@ -9,12 +9,20 @@ import org.antlr.v4.test.runtime.*; import org.antlr.v4.test.runtime.states.CompiledState; import org.antlr.v4.test.runtime.states.GeneratedState; +import org.stringtemplate.v4.ST; import java.io.File; +import java.io.FilenameFilter; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; -import static org.antlr.v4.test.runtime.FileUtils.mkdir; -import static org.antlr.v4.test.runtime.FileUtils.moveFile; +import static org.antlr.v4.test.runtime.FileUtils.*; +import static org.antlr.v4.test.runtime.RuntimeTestUtils.getTextFromResource; +import static org.antlr.v4.test.runtime.RuntimeTestUtils.isWindows; public class SwiftRunner extends RuntimeRunner { @Override @@ -27,42 +35,71 @@ public String getTestFileName() { return "main"; } - private static final String antlrRuntimePath; - private static final String[] initPackageArgs; - private static final String[] buildProjectArgs; + private static final String swiftRuntimePath; + private static final String buildSuffix; + private static final Map environment; + + private static final String includePath; + private static final String libraryPath; static { - String swiftRuntimePath = getRuntimePath("Swift"); - antlrRuntimePath = Paths.get(swiftRuntimePath, "..", "..").normalize().toString(); - String dylibPath = antlrRuntimePath + "/.build/release/"; - initPackageArgs = new String[]{"swift", "package", "init", "--type", "executable"}; - buildProjectArgs = new String[]{"swift", "build", "-c", "release", "-Xswiftc", "-I" + dylibPath, "-Xlinker", "-L" + dylibPath, - "-Xlinker", "-lAntlr4", "-Xlinker", "-rpath", "-Xlinker", dylibPath}; + swiftRuntimePath = getRuntimePath("Swift"); + buildSuffix = isWindows() ? "x86_64-unknown-windows-msvc" : ""; + includePath = Paths.get(swiftRuntimePath, ".build", buildSuffix, "release").toString(); + environment = new HashMap<>(); + if (isWindows()) { + libraryPath = Paths.get(includePath, "Antlr4.lib").toString(); + String path = System.getenv("PATH"); + environment.put("PATH", path == null ? includePath : path + ";" + includePath); + } + else { + libraryPath = includePath; + } + } + + @Override + protected String getCompilerName() { + return "swift"; } @Override protected void initRuntime() throws Exception { - runCommand(new String[] {"swift", "build", "-c", "release"}, antlrRuntimePath, "build Swift runtime"); + runCommand(new String[] {getCompilerPath(), "build", "-c", "release"}, swiftRuntimePath, "build Swift runtime"); } @Override protected CompiledState compile(RunOptions runOptions, GeneratedState generatedState) { Exception exception = null; try { - String projectName = "Test"; - File testDir = tempTestDir.toFile(); - String projectDir = new File(testDir, projectName).getAbsolutePath(); - mkdir(projectDir); - String destDir = projectDir + "/Sources/" + projectName; - - runCommand(initPackageArgs, projectDir); - - for (GeneratedFile generatedFile : generatedState.generatedFiles) { - moveFile(testDir, destDir, generatedFile.name); - } - moveFile(testDir, destDir, getTestFileWithExt()); - - runCommand(buildProjectArgs, projectDir); + String tempDirPath = getTempDirPath(); + File tempDirFile = new File(tempDirPath); + + File[] ignoredFiles = tempDirFile.listFiles(NoSwiftFileFilter.Instance); + assert ignoredFiles != null; + List excludedFiles = Arrays.stream(ignoredFiles).map(File::getName).collect(Collectors.toList()); + + String text = getTextFromResource("org/antlr/v4/test/runtime/helpers/Package.swift.stg"); + ST outputFileST = new ST(text); + outputFileST.add("excludedFiles", excludedFiles); + writeFile(tempDirPath, "Package.swift", outputFileST.render()); + + String[] buildProjectArgs = new String[]{ + getCompilerPath(), + "build", + "-c", + "release", + "-Xswiftc", + "-I" + includePath, + "-Xlinker", + "-L" + includePath, + "-Xlinker", + "-lAntlr4", + "-Xlinker", + "-rpath", + "-Xlinker", + libraryPath + }; + runCommand(buildProjectArgs, tempDirPath); } catch (Exception e) { exception = e; } @@ -70,6 +107,14 @@ protected CompiledState compile(RunOptions runOptions, GeneratedState generatedS return new CompiledState(generatedState, exception); } + static class NoSwiftFileFilter implements FilenameFilter { + public final static NoSwiftFileFilter Instance = new NoSwiftFileFilter(); + + public boolean accept(File dir, String name) { + return !name.endsWith(".swift"); + } + } + @Override public String getRuntimeToolName() { return null; @@ -77,6 +122,15 @@ public String getRuntimeToolName() { @Override public String getExecFileName() { - return Paths.get(getTempDirPath(), "Test/.build/release/Test").toString(); + return Paths.get(getTempDirPath(), + ".build", + buildSuffix, + "release", + "Test" + (isWindows() ? ".exe" : "")).toString(); + } + + @Override + public Map getExecEnvironment() { + return environment; } } diff --git a/Package.swift b/runtime/Swift/Package.swift similarity index 61% rename from Package.swift rename to runtime/Swift/Package.swift index b8ec930c22..9de0120e70 100644 --- a/Package.swift +++ b/runtime/Swift/Package.swift @@ -1,5 +1,4 @@ -// swift-tools-version:5.3 - +// swift-tools-version:5.6 import PackageDescription @@ -15,10 +14,14 @@ let package = Package( .target( name: "Antlr4", dependencies: [], - path: "./runtime/Swift/Sources/Antlr4"), + path: "Sources/Antlr4"), .testTarget( name: "Antlr4Tests", dependencies: ["Antlr4"], - path:"./runtime/Swift/Tests/Antlr4Tests"), + path:"Tests/Antlr4Tests", + exclude: [ + "VisitorBasic.g4", "VisitorCalc.g4", "LexerA.g4", "LexerB.g4", "Threading.g4" + ] + ) ] ) diff --git a/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift b/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift index 060317920f..b78379f87a 100644 --- a/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift +++ b/runtime/Swift/Sources/Antlr4/ParserRuleContext.swift @@ -5,28 +5,30 @@ /// A rule invocation record for parsing. -/// +/// /// Contains all of the information about the current rule not stored in the /// RuleContext. It handles parse tree children list, Any ATN state /// tracing, and the default values available for rule invocations: /// start, stop, rule index, current alt number. -/// +/// /// Subclasses made for each rule and grammar track the parameters, /// return values, locals, and labels specific to that rule. These /// are the objects that are returned from rules. -/// +/// /// Note text is not an actual field of a rule return value; it is computed /// from start and stop using the input stream's toString() method. I /// could add a ctor to this so that we can pass in and store the input /// stream, but I'm not sure we want to do that. It would seem to be undefined /// to get the .text property anyway if the rule matches tokens from multiple /// input streams. -/// +/// /// I do not use getters for fields of objects that are used simply to /// group values such as this aggregate. The getters/setters are there to /// satisfy the superclass interface. -/// +/// open class ParserRuleContext: RuleContext { + public static let EMPTY = ParserRuleContext() + public var visited = false /// If we are debugging or building a parse tree for a visitor, @@ -34,7 +36,7 @@ open class ParserRuleContext: RuleContext { /// with this rule's context. This is empty for parsing w/o tree constr. /// operation because we don't the need to track the details about /// how we parse this rule. - /// + /// public var children: [ParseTree]? /// For debugging/tracing purposes, we want to track all of the nodes in @@ -44,23 +46,23 @@ open class ParserRuleContext: RuleContext { /// ATN nodes and other rules used to match rule invocations. It /// traces the rule invocation node itself but nothing inside that /// other rule's ATN submachine. - /// + /// /// There is NOT a one-to-one correspondence between the children and /// states list. There are typically many nodes in the ATN traversed /// for each element in the children list. For example, for a rule /// invocation there is the invoking state and the following state. - /// + /// /// The parser setState() method updates field s and adds it to this list /// if we are debugging/tracing. - /// + /// /// This does not trace states visited during prediction. - /// + /// public var start: Token?, stop: Token? - /// + /// /// The exception that forced this rule to return. If the rule successfully /// completed, this is `null`. - /// + /// public var exception: RecognitionException? public override init() { @@ -73,15 +75,15 @@ open class ParserRuleContext: RuleContext { /// COPY a ctx (I'm deliberately not using copy constructor) to avoid /// confusion with creating node with parent. Does not copy children. - /// + /// /// This is used in the generated parser code to flip a generic XContext /// node for rule X to a YContext for alt label Y. In that sense, it is /// not really a generic copy function. - /// + /// /// If we do an error sync() at start of a rule, we might add error nodes /// to the generic XContext so this function must copy those nodes to /// the YContext as well else they are lost! - /// + /// open func copyFrom(_ ctx: ParserRuleContext) { self.parent = ctx.parent self.invokingState = ctx.invokingState @@ -112,13 +114,13 @@ open class ParserRuleContext: RuleContext { /// internal and leaf nodes. Does not set parent link; /// other add methods must do that. Other addChild methods /// call this. - /// + /// /// We cannot set the parent pointer of the incoming node /// because the existing interfaces do not have a setParent() /// method and I don't want to break backward compatibility for this. - /// + /// /// - Since: 4.7 - /// + /// open func addAnyChild(_ t: ParseTree) { if children == nil { children = [ParseTree]() @@ -146,7 +148,7 @@ open class ParserRuleContext: RuleContext { /// Used by enterOuterAlt to toss out a RuleContext previously added as /// we entered a rule. If we have # label, we will need to remove /// generic ruleContext object. - /// + /// open func removeLastChild() { children?.removeLast() } @@ -241,19 +243,19 @@ open class ParserRuleContext: RuleContext { return Interval.of(start.getTokenIndex(), stop.getTokenIndex()) } - /// + /// /// Get the initial token in this context. /// Note that the range from start to stop is inclusive, so for rules that do not consume anything /// (for example, zero length or error productions) this token may exceed stop. - /// + /// open func getStart() -> Token? { return start } - /// + /// /// Get the final token in this context. /// Note that the range from start to stop is inclusive, so for rules that do not consume anything /// (for example, zero length or error productions) this token may precede start. - /// + /// open func getStop() -> Token? { return stop } diff --git a/runtime/Swift/Sources/Antlr4/RuleContext.swift b/runtime/Swift/Sources/Antlr4/RuleContext.swift index 0afad6065e..0178dc5a78 100644 --- a/runtime/Swift/Sources/Antlr4/RuleContext.swift +++ b/runtime/Swift/Sources/Antlr4/RuleContext.swift @@ -5,20 +5,20 @@ /// A rule context is a record of a single rule invocation. -/// +/// /// We form a stack of these context objects using the parent /// pointer. A parent pointer of null indicates that the current /// context is the bottom of the stack. The ParserRuleContext subclass /// as a children list so that we can turn this data structure into a /// tree. -/// +/// /// The root node always has a null pointer and invokingState of ATNState.INVALID_STATE_NUMBER. -/// +/// /// Upon entry to parsing, the first invoked rule function creates a /// context object (asubclass specialized for that rule such as /// SContext) and makes it the root of a parse tree, recorded by field /// Parser._ctx. -/// +/// /// public final SContext s() throws RecognitionException { /// SContext _localctx = new SContext(_ctx, getState()); <-- create new node /// enterRule(_localctx, 0, RULE_s); <-- push it @@ -26,38 +26,36 @@ /// exitRule(); <-- pop back to _localctx /// return _localctx; /// } -/// +/// /// A subsequent rule invocation of r from the start rule s pushes a /// new context object for r whose parent points at s and use invoking /// state is the state with r emanating as edge label. -/// +/// /// The invokingState fields from a context object to the root /// together form a stack of rule indication states where the root /// (bottom of the stack) has a -1 sentinel value. If we invoke start /// symbol s then call r1, which calls r2, the would look like /// this: -/// +/// /// SContext[-1] <- root node (bottom of the stack) /// R1Context[p] <- p in rule s called r1 /// R2Context[q] <- q in rule r1 called r2 -/// +/// /// So the top of the stack, _ctx, represents a call to the current /// rule and it holds the return address from another rule that invoke /// to this rule. To invoke a rule, we must always have a current context. -/// +/// /// The parent contexts are useful for computing lookahead sets and /// getting error information. -/// +/// /// These objects are used during parsing and prediction. /// For the special case of parsers, we use the subclass /// ParserRuleContext. -/// +/// /// - SeeAlso: org.antlr.v4.runtime.ParserRuleContext -/// +/// open class RuleContext: RuleNode { - public static let EMPTY = ParserRuleContext() - /// What context invoked this rule? public weak var parent: RuleContext? @@ -65,7 +63,7 @@ open class RuleContext: RuleNode { /// The "return address" is the followState of invokingState /// If parent is null, this should be ATNState.INVALID_STATE_NUMBER /// this context object represents the start rule. - /// + /// public var invokingState = ATNState.INVALID_STATE_NUMBER public init() { @@ -89,7 +87,7 @@ open class RuleContext: RuleNode { /// A context is empty if there is no invoking state; meaning nobody called /// current context. - /// + /// open func isEmpty() -> Bool { return invokingState == ATNState.INVALID_STATE_NUMBER } @@ -118,11 +116,11 @@ open class RuleContext: RuleNode { /// Return the combined text of all child nodes. This method only considers /// tokens which have been added to the parse tree. - /// + /// /// Since tokens on hidden channels (e.g. whitespace or comments) are not /// added to the parse trees, they will not appear in the output of this /// method. - /// + /// open func getText() -> String { let length = getChildCount() @@ -174,7 +172,7 @@ open class RuleContext: RuleNode { /// Print out a whole tree, not just a node, in LISP format /// (root child1 .. childN). Print just a node if this is a leaf. - /// + /// public func toStringTree(_ ruleNames: [String]?) -> String { return Trees.toStringTree(self, ruleNames) } diff --git a/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift b/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift index 6b2841d2ae..4d1c0f610a 100644 --- a/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift +++ b/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift @@ -334,17 +334,15 @@ fileprivate struct UInt8StreamIterator: IteratorProtocol { } switch stream.streamStatus { - case .notOpen, .writing, .closed: - preconditionFailure() - case .atEnd: - return nil - case .error: - hasErrorOccurred = true - return nil - case .opening, .open, .reading: - break - @unknown default: - fatalError() + case .notOpen, .writing, .closed: + preconditionFailure() + case .atEnd: + return nil + case .error: + hasErrorOccurred = true + return nil + case .opening, .open, .reading: + break } let count = stream.read(&buffer, maxLength: buffer.count) diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift b/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift index 5e5539c1fa..16bdbbd3a6 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift @@ -1,57 +1,57 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// -/// +/// /// A tuple: (ATN state, predicted alt, syntactic, semantic context). /// The syntactic context is a graph-structured stack node whose /// path(s) to the root is the rule invocation(s) /// chain used to arrive at the state. The semantic context is /// the tree of semantic predicates encountered before reaching /// an ATN state. -/// +/// public class ATNConfig: Hashable, CustomStringConvertible { - /// + /// /// This field stores the bit mask for implementing the /// _#isPrecedenceFilterSuppressed_ property as a bit within the /// existing _#reachesIntoOuterContext_ field. - /// + /// private static let SUPPRESS_PRECEDENCE_FILTER: Int = 0x40000000 - /// + /// /// The ATN state associated with this configuration - /// + /// public final let state: ATNState - /// + /// /// What alt (or lexer rule) is predicted by this configuration - /// + /// public final let alt: Int - /// + /// /// The stack of invoking states leading to the rule/states associated /// with this config. We track only those contexts pushed during /// execution of the ATN simulator. - /// + /// public internal(set) final var context: PredictionContext? - /// + /// /// We cannot execute predicates dependent upon local context unless /// we know for sure we are in the correct context. Because there is /// no way to do this efficiently, we simply cannot evaluate /// dependent predicates unless we are in the rule that initially /// invokes the ATN simulator. - /// - /// + /// + /// /// closure() tracks the depth of how far we dip into the outer context: /// depth > 0. Note that it may not be totally accurate depth since I /// don't ever decrement. TODO: make it a boolean then - /// - /// + /// + /// /// For memory efficiency, the _#isPrecedenceFilterSuppressed_ method /// is also backed by this field. Since the field is publicly accessible, the /// highest bit which would not cause the value to become negative is used to @@ -61,7 +61,7 @@ public class ATNConfig: Hashable, CustomStringConvertible { /// constructors as well as certain operations like /// _org.antlr.v4.runtime.atn.ATNConfigSet#add(org.antlr.v4.runtime.atn.ATNConfig, DoubleKeyMap)_ method are /// __completely__ unaffected by the change. - /// + /// public internal(set) final var reachesIntoOuterContext: Int = 0 public final let semanticContext: SemanticContext @@ -69,7 +69,7 @@ public class ATNConfig: Hashable, CustomStringConvertible { public init(_ state: ATNState, _ alt: Int, _ context: PredictionContext?, - _ semanticContext: SemanticContext = SemanticContext.NONE) { + _ semanticContext: SemanticContext = SemanticContext.Empty.Instance) { self.state = state self.alt = alt self.context = context @@ -105,11 +105,11 @@ public class ATNConfig: Hashable, CustomStringConvertible { self.reachesIntoOuterContext = c.reachesIntoOuterContext } - /// + /// /// This method gets the value of the _#reachesIntoOuterContext_ field /// as it existed prior to the introduction of the /// _#isPrecedenceFilterSuppressed_ method. - /// + /// public final func getOuterContextDepth() -> Int { return reachesIntoOuterContext & ~Self.SUPPRESS_PRECEDENCE_FILTER } @@ -145,7 +145,7 @@ public class ATNConfig: Hashable, CustomStringConvertible { if let context = context { buf += ",[\(context)]" } - if semanticContext != SemanticContext.NONE { + if semanticContext != SemanticContext.Empty.Instance { buf += ",\(semanticContext)" } let outerDepth = getOuterContextDepth() @@ -167,7 +167,7 @@ public func ==(lhs: ATNConfig, rhs: ATNConfig) -> Bool { if lhs === rhs { return true } - + if let l = lhs as? LexerATNConfig, let r = rhs as? LexerATNConfig { return l == r diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift b/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift index 5d940a3ea0..946af07aba 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift @@ -1,23 +1,23 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// -/// +/// /// Specialized _java.util.Set_`<`_org.antlr.v4.runtime.atn.ATNConfig_`>` that can track /// info about the set, with support for combining similar configurations using a /// graph-structured stack. /// public final class ATNConfigSet: Hashable, CustomStringConvertible { - /// + /// /// The reason that we need this is because we don't want the hash map to use /// the standard hash code and equals. We need all configurations with the same /// `(s,i,_,semctx)` to be equal. Unfortunately, this key effectively doubles /// the number of objects associated with ATNConfigs. The other solution is to /// use a hash table that lets us specify the equals/hashcode operation. - /// + /// /// @@ -29,27 +29,27 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { /// private var readonly = false - /// + /// /// All configs but hashed by (s, i, _, pi) not including context. Wiped out /// when we go readonly as this set becomes a DFA state. - /// + /// private var configLookup: LookupDictionary - /// + /// /// Track the elements as they are added to the set; supports get(i) - /// + /// public private(set) var configs = [ATNConfig]() // TODO: these fields make me pretty uncomfortable but nice to pack up info together, saves recomputation // TODO: can we track conflicts as they are added to save scanning configs later? public internal(set) var uniqueAlt = ATN.INVALID_ALT_NUMBER //TODO no default - /// + /// /// Currently this is only used when we detect SLL conflict; this does /// not necessarily represent the ambiguous alternatives. In fact, /// I should also point out that this seems to include predicated alternatives /// that have predicates that evaluate to false. Computed in computeTargetState(). - /// + /// internal var conflictingAlts: BitSet? // Used in parser and lexer. In lexer, it indicates we hit a pred @@ -59,11 +59,11 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { public internal(set) var dipsIntoOuterContext = false //TODO no default - /// + /// /// Indicates that this configuration set is part of a full context /// LL prediction. It will be used to determine how to merge $. With SLL /// it's a wildcard whereas it is not for LL context merge. - /// + /// public let fullCtx: Bool private var cachedHashCode = -1 @@ -80,16 +80,16 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { return try add(config, &mergeCache) } - /// + /// /// Adding a new config means merging contexts with existing configs for /// `(s, i, pi, _)`, where `s` is the /// _org.antlr.v4.runtime.atn.ATNConfig#state_, `i` is the _org.antlr.v4.runtime.atn.ATNConfig#alt_, and /// `pi` is the _org.antlr.v4.runtime.atn.ATNConfig#semanticContext_. We use /// `(s,i,pi)` as key. - /// + /// /// This method updates _#dipsIntoOuterContext_ and /// _#hasSemanticContext_ when necessary. - /// + /// @discardableResult public func add( _ config: ATNConfig, @@ -98,7 +98,7 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { throw ANTLRError.illegalState(msg: "This set is readonly") } - if config.semanticContext != SemanticContext.NONE { + if config.semanticContext != SemanticContext.Empty.Instance { hasSemanticContext = true } if config.getOuterContextDepth() > 0 { @@ -137,9 +137,9 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { } - /// + /// /// Return a List holding list of configs - /// + /// public func elements() -> [ATNConfig] { return configs } @@ -152,14 +152,14 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { return states } - /// + /// /// Gets the complete set of represented alternatives for the configuration /// set. - /// + /// /// - returns: the set of represented alternatives in this configuration set - /// + /// /// - since: 4.3 - /// + /// public func getAlts() -> BitSet { let alts = BitSet() for config in configs { @@ -171,7 +171,7 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { public func getPredicates() -> [SemanticContext] { var preds = [SemanticContext]() for config in configs { - if config.semanticContext != SemanticContext.NONE { + if config.semanticContext != SemanticContext.Empty.Instance { preds.append(config.semanticContext) } } @@ -279,11 +279,11 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { return buf } - /// + /// /// override /// public func toArray(a : [T]) -> [T] { /// return configLookup.toArray(a); - /// + /// private func configHash(_ stateNumber: Int,_ context: PredictionContext?) -> Int{ var hashCode = MurmurHash.initialize(7) hashCode = MurmurHash.update(hashCode, stateNumber) @@ -428,11 +428,11 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { } if !config.isPrecedenceFilterSuppressed() { - /// + /// /// In the future, this elimination step could be updated to also /// filter the prediction context for alternatives predicting alt>1 /// (basically a graph subtraction algorithm). - /// + /// let context = statesFromAlt1[config.state.stateNumber] if context != nil && context == config.context { // eliminated @@ -456,9 +456,9 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { var nPredAlts = 0 for i in 1...nalts { if altToPred[i] == nil { - altToPred[i] = SemanticContext.NONE + altToPred[i] = SemanticContext.Empty.Instance } - else if altToPred[i] != SemanticContext.NONE { + else if altToPred[i] != SemanticContext.Empty.Instance { nPredAlts += 1 } } @@ -487,23 +487,23 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { return alts.getMinElement() } - /// + /// /// Walk the list of configurations and split them according to /// those that have preds evaluating to true/false. If no pred, assume /// true pred and include in succeeded set. Returns Pair of sets. - /// + /// /// Create a new set so as not to alter the incoming parameter. - /// + /// /// Assumption: the input stream has been restored to the starting point /// prediction, which is where predicates need to evaluate. - /// + /// public func splitAccordingToSemanticValidity( _ outerContext: ParserRuleContext, _ evalSemanticContext: (SemanticContext, ParserRuleContext, Int, Bool) throws -> Bool) rethrows -> (ATNConfigSet, ATNConfigSet) { let succeeded = ATNConfigSet(fullCtx) let failed = ATNConfigSet(fullCtx) for config in configs { - if config.semanticContext != SemanticContext.NONE { + if config.semanticContext != SemanticContext.Empty.Instance { let predicateEvaluationResult = try evalSemanticContext(config.semanticContext, outerContext, config.alt,fullCtx) if predicateEvaluationResult { try! succeeded.add(config) @@ -520,7 +520,7 @@ public final class ATNConfigSet: Hashable, CustomStringConvertible { public func dupConfigsWithoutSemanticPredicates() -> ATNConfigSet { let dup = ATNConfigSet() for config in configs { - let c = ATNConfig(config, SemanticContext.NONE) + let c = ATNConfig(config, SemanticContext.Empty.Instance) try! dup.add(c) } return dup diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNDeserializer.swift b/runtime/Swift/Sources/Antlr4/atn/ATNDeserializer.swift index 8677ebf6fb..e9b5e71b9d 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNDeserializer.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNDeserializer.swift @@ -47,7 +47,7 @@ public class ATNDeserializer { continue } - var ruleIndex = data[p] + let ruleIndex = data[p] p += 1 let s = try stateFactory(stype, ruleIndex)! if stype == ATNState.LOOP_END { @@ -102,7 +102,7 @@ public class ATNDeserializer { ruleToStartState.append(startState) if atn.grammarType == ATNType.lexer { - var tokenType = data[p] + let tokenType = data[p] p += 1 ruleToTokenType.append(tokenType) } @@ -179,9 +179,9 @@ public class ATNDeserializer { for _ in 0.. [IntervalSet?]? { - + guard let s = s else { return nil } @@ -39,7 +39,7 @@ public class LL1Analyzer { look[alt] = IntervalSet() var lookBusy = Set() let seeThruPreds = false // fail to get lookahead upon pred - _LOOK(s.transition(alt).target, nil, PredictionContext.EMPTY, + _LOOK(s.transition(alt).target, nil, EmptyPredictionContext.Instance, look[alt]!, &lookBusy, BitSet(), seeThruPreds, false) // Wipe out lookahead for this alternative if we found nothing // or we had a predicate when we !seeThruPreds @@ -50,44 +50,44 @@ public class LL1Analyzer { return look } - /// + /// /// Compute set of tokens that can follow `s` in the ATN in the /// specified `ctx`. - /// + /// /// If `ctx` is `null` and the end of the rule containing /// `s` is reached, _org.antlr.v4.runtime.Token#EPSILON_ is added to the result set. /// If `ctx` is not `null` and the end of the outermost rule is /// reached, _org.antlr.v4.runtime.Token#EOF_ is added to the result set. - /// + /// /// - parameter s: the ATN state /// - parameter ctx: the complete parser context, or `null` if the context /// should be ignored - /// + /// /// - returns: The set of tokens that can follow `s` in the ATN in the /// specified `ctx`. - /// + /// public func LOOK(_ s: ATNState, _ ctx: RuleContext?) -> IntervalSet { return LOOK(s, nil, ctx) } - /// + /// /// Compute set of tokens that can follow `s` in the ATN in the /// specified `ctx`. - /// + /// /// If `ctx` is `null` and the end of the rule containing /// `s` is reached, _org.antlr.v4.runtime.Token#EPSILON_ is added to the result set. /// If `ctx` is not `null` and the end of the outermost rule is /// reached, _org.antlr.v4.runtime.Token#EOF_ is added to the result set. - /// + /// /// - parameter s: the ATN state /// - parameter stopState: the ATN state to stop at. This can be a /// _org.antlr.v4.runtime.atn.BlockEndState_ to detect epsilon paths through a closure. /// - parameter ctx: the complete parser context, or `null` if the context /// should be ignored - /// + /// /// - returns: The set of tokens that can follow `s` in the ATN in the /// specified `ctx`. - /// + /// public func LOOK(_ s: ATNState, _ stopState: ATNState?, _ ctx: RuleContext?) -> IntervalSet { let r = IntervalSet() @@ -98,16 +98,16 @@ public class LL1Analyzer { return r } - /// + /// /// Compute set of tokens that can follow `s` in the ATN in the /// specified `ctx`. - /// + /// /// If `ctx` is `null` and `stopState` or the end of the /// rule containing `s` is reached, _org.antlr.v4.runtime.Token#EPSILON_ is added to /// the result set. If `ctx` is not `null` and `addEOF` is /// `true` and `stopState` or the end of the outermost rule is /// reached, _org.antlr.v4.runtime.Token#EOF_ is added to the result set. - /// + /// /// - parameter s: the ATN state. /// - parameter stopState: the ATN state to stop at. This can be a /// _org.antlr.v4.runtime.atn.BlockEndState_ to detect epsilon paths through a closure. @@ -127,7 +127,7 @@ public class LL1Analyzer { /// - parameter addEOF: Add _org.antlr.v4.runtime.Token#EOF_ to the result if the end of the /// outermost context is reached. This parameter has no effect if `ctx` /// is `null`. - /// + /// internal func _LOOK(_ s: ATNState, _ stopState: ATNState?, _ ctx: PredictionContext?, @@ -168,7 +168,7 @@ public class LL1Analyzer { return } - if ctx != PredictionContext.EMPTY { + if ctx != EmptyPredictionContext.Instance { let removed = try! calledRuleStack.get(s.ruleIndex!) try! calledRuleStack.clear(s.ruleIndex!) defer { diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerATNConfig.swift b/runtime/Swift/Sources/Antlr4/atn/LexerATNConfig.swift index 38e55dc5e6..8c241a8ffd 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerATNConfig.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerATNConfig.swift @@ -1,14 +1,14 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// public class LexerATNConfig: ATNConfig { - /// + /// /// This is the backing field for _#getLexerActionExecutor_. - /// + /// private let lexerActionExecutor: LexerActionExecutor? fileprivate let passedThroughNonGreedyDecision: Bool @@ -19,7 +19,7 @@ public class LexerATNConfig: ATNConfig { self.passedThroughNonGreedyDecision = false self.lexerActionExecutor = nil - super.init(state, alt, context, SemanticContext.NONE) + super.init(state, alt, context, SemanticContext.Empty.Instance) } public init(_ state: ATNState, @@ -29,7 +29,7 @@ public class LexerATNConfig: ATNConfig { self.lexerActionExecutor = lexerActionExecutor self.passedThroughNonGreedyDecision = false - super.init(state, alt, context, SemanticContext.NONE) + super.init(state, alt, context, SemanticContext.Empty.Instance) } public init(_ c: LexerATNConfig, _ state: ATNState) { @@ -60,10 +60,10 @@ public class LexerATNConfig: ATNConfig { return source.passedThroughNonGreedyDecision || target is DecisionState && (target as! DecisionState).nonGreedy } - /// + /// /// Gets the _org.antlr.v4.runtime.atn.LexerActionExecutor_ capable of executing the embedded /// action(s) for the current configuration. - /// + /// public final func getLexerActionExecutor() -> LexerActionExecutor? { return lexerActionExecutor } diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerATNSimulator.swift b/runtime/Swift/Sources/Antlr4/atn/LexerATNSimulator.swift index 5b373c6448..207d956305 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerATNSimulator.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerATNSimulator.swift @@ -389,7 +389,7 @@ open class LexerATNSimulator: ATNSimulator { final func computeStartState(_ input: CharStream, _ p: ATNState) throws -> ATNConfigSet { - let initialContext = PredictionContext.EMPTY + let initialContext = EmptyPredictionContext.Instance let configs = ATNConfigSet(true, isOrdered: true) let length = p.getNumberOfTransitions() for i in 0..? // LAME globals to avoid parameters!!!!! I need these down deep in predTransition @@ -389,18 +389,18 @@ open class ParserATNSimulator: ATNSimulator { } - /// + /// /// Performs ATN simulation to compute a predicted alternative based /// upon the remaining input, but also updates the DFA cache to avoid /// having to traverse the ATN again for the same input sequence. - /// + /// /// There are some key conditions we're looking for after computing a new /// set of ATN configs (proposed DFA state): /// if the set is empty, there is no viable alternative for current symbol /// does the state uniquely predict an alternative? /// does the state have a conflict that would prevent us from /// putting it on the work list? - /// + /// /// We also have some key operations to do: /// add an edge from previous DFA state to potentially new DFA state, D, /// upon current symbol but only if adding to work list, which means in all @@ -412,14 +412,14 @@ open class ParserATNSimulator: ATNSimulator { /// reporting an ambiguity /// reporting a context sensitivity /// reporting insufficient predicates - /// + /// /// cover these cases: /// dead end /// single alt /// single alt + preds /// conflict /// conflict + preds - /// + /// final func execATN(_ dfa: DFA, _ s0: DFAState, _ input: TokenStream, _ startIndex: Int, _ outerContext: ParserRuleContext) throws -> Int { @@ -537,17 +537,17 @@ open class ParserATNSimulator: ATNSimulator { } } - /// + /// /// Get an existing target state for an edge in the DFA. If the target state /// for the edge has not yet been computed or is otherwise not available, /// this method returns `null`. - /// + /// /// - parameter previousD: The current DFA state /// - parameter t: The next input symbol /// - returns: The existing target DFA state for the given input symbol /// `t`, or `null` if the target state for this edge is not /// already cached - /// + /// func getExistingTargetState(_ previousD: DFAState, _ t: Int) -> DFAState? { let edges = previousD.edges if edges == nil || (t + 1) < 0 || (t + 1) >= (edges!.count) { @@ -557,18 +557,18 @@ open class ParserATNSimulator: ATNSimulator { return edges![t + 1] } - /// + /// /// Compute a target state for an edge in the DFA, and attempt to add the /// computed state and corresponding edge to the DFA. - /// + /// /// - parameter dfa: The DFA /// - parameter previousD: The current DFA state /// - parameter t: The next input symbol - /// + /// /// - returns: The computed target DFA state for the given input symbol /// `t`. If `t` does not lead to a valid DFA state, this method /// returns _#ERROR_. - /// + /// func computeTargetState(_ dfa: DFA, _ previousD: DFAState, _ t: Int) throws -> DFAState { guard let reach = try computeReachSet(previousD.configs, t, false) else { @@ -721,30 +721,30 @@ open class ParserATNSimulator: ATNSimulator { // We do not check predicates here because we have checked them // on-the-fly when doing full context prediction. - /// + /// /// In non-exact ambiguity detection mode, we might actually be able to /// detect an exact ambiguity, but I'm not going to spend the cycles /// needed to check. We only emit ambiguity warnings in exact ambiguity /// mode. - /// + /// /// For example, we might know that we have conflicting configurations. /// But, that does not mean that there is no way forward without a /// conflict. It's possible to have nonconflicting alt subsets as in: - /// + /// /// LL altSubSets=[{1, 2}, {1, 2}, {1}, {1, 2}] - /// + /// /// from - /// + /// /// [(17,1,[5 $]), (13,1,[5 10 $]), (21,1,[5 10 $]), (11,1,[$]), /// (13,2,[5 10 $]), (21,2,[5 10 $]), (11,2,[$])] - /// + /// /// In this case, (17,1,[5 $]) indicates there is some next sequence that /// would resolve this without conflict to alternative 1. Any other viable /// next sequence, however, is associated with a conflict. We stop /// looking for input because no amount of further lookahead will alter /// the fact that we should predict alternative 1. We just can't say for /// sure that there is an ambiguity without looking further. - /// + /// reportAmbiguity(dfa, D, startIndex, input.index(), foundExactAmbig, reach.getAlts(), reach) } @@ -764,17 +764,17 @@ open class ParserATNSimulator: ATNSimulator { let intermediate = ATNConfigSet(fullCtx) - /// + /// /// Configurations already in a rule stop state indicate reaching the end /// of the decision rule (local context) or end of the start rule (full /// context). Once reached, these configurations are never updated by a /// closure operation, so they are handled separately for the performance /// advantage of having a smaller intermediate set when calling closure. - /// + /// /// For full-context reach operations, separate handling is required to /// ensure that the alternative matching the longest overall sequence is /// chosen when multiple such configurations can match the input. - /// + /// var skippedStopStates: [ATNConfig]? = nil // First figure out where we can reach on input t @@ -810,16 +810,16 @@ open class ParserATNSimulator: ATNSimulator { var reach: ATNConfigSet? = nil - /// + /// /// This block optimizes the reach operation for intermediate sets which /// trivially indicate a termination state for the overall /// adaptivePredict operation. - /// + /// /// The conditions assume that intermediate /// contains all configurations relevant to the reach set, but this /// condition is not true when one or more configurations have been /// withheld in skippedStopStates, or when the current symbol is EOF. - /// + /// if skippedStopStates == nil && t != CommonToken.EOF { if intermediate.size() == 1 { // Don't pursue the closure if there is just one state. @@ -836,10 +836,10 @@ open class ParserATNSimulator: ATNSimulator { } } - /// + /// /// If the reach set could not be trivially determined, perform a closure /// operation on the intermediate set to compute its initial value. - /// + /// if reach == nil { reach = ATNConfigSet(fullCtx) var closureBusy = Set() @@ -850,28 +850,28 @@ open class ParserATNSimulator: ATNSimulator { } if t == BufferedTokenStream.EOF { - /// + /// /// After consuming EOF no additional input is possible, so we are /// only interested in configurations which reached the end of the /// decision rule (local context) or end of the start rule (full /// context). Update reach to contain only these configurations. This /// handles both explicit EOF transitions in the grammar and implicit /// EOF transitions following the end of the decision or start rule. - /// + /// /// When reach==intermediate, no closure operation was performed. In /// this case, removeAllConfigsNotInRuleStopState needs to check for /// reachable rule stop states as well as configurations already in /// a rule stop state. - /// + /// /// This is handled before the configurations in skippedStopStates, /// because any configurations potentially added from that list are /// already guaranteed to meet this condition whether or not it's /// required. - /// + /// reach = removeAllConfigsNotInRuleStopState(reach!, reach! === intermediate) } - /// + /// /// If skippedStopStates is not null, then it contains at least one /// configuration. For full-context reach operations, these /// configurations reached the end of the start rule, in which case we @@ -879,7 +879,7 @@ open class ParserATNSimulator: ATNSimulator { /// closure operation reached such a state. This ensures adaptivePredict /// chooses an alternative matching the longest overall sequence when /// multiple alternatives are viable. - /// + /// if let reach = reach { if let skippedStopStates = skippedStopStates, (!fullCtx || !PredictionMode.hasConfigInRuleStopState(reach)) { assert(!skippedStopStates.isEmpty, "Expected: !skippedStopStates.isEmpty()") @@ -895,26 +895,26 @@ open class ParserATNSimulator: ATNSimulator { return reach } - /// + /// /// Return a configuration set containing only the configurations from /// `configs` which are in a _org.antlr.v4.runtime.atn.RuleStopState_. If all /// configurations in `configs` are already in a rule stop state, this /// method simply returns `configs`. - /// + /// /// When `lookToEndOfRule` is true, this method uses /// _org.antlr.v4.runtime.atn.ATN#nextTokens_ for each configuration in `configs` which is /// not already in a rule stop state to see if a rule stop state is reachable /// from the configuration via epsilon-only transitions. - /// + /// /// - parameter configs: the configuration set to update /// - parameter lookToEndOfRule: when true, this method checks for rule stop states /// reachable by epsilon-only transitions from each configuration in /// `configs`. - /// + /// /// - returns: `configs` if all configurations in `configs` are in a /// rule stop state, otherwise return a new configuration set containing only /// the configurations from `configs` which are in a rule stop state - /// + /// final func removeAllConfigsNotInRuleStopState(_ configs: ATNConfigSet, _ lookToEndOfRule: Bool) -> ATNConfigSet { return configs.removeAllConfigsNotInRuleStopState(&mergeCache,lookToEndOfRule,atn) } @@ -934,10 +934,10 @@ open class ParserATNSimulator: ATNSimulator { return configs } - /// + /// /// parrt internal source braindump that doesn't mess up /// external API spec. - /// + /// /// applyPrecedenceFilter is an optimization to avoid highly /// nonlinear prediction of expressions and other left recursive /// rules. The precedence predicates such as {3>=prec}? Are highly @@ -948,23 +948,23 @@ open class ParserATNSimulator: ATNSimulator { /// these predicates out of context, the resulting conflict leads /// to full LL evaluation and nonlinear prediction which shows up /// very clearly with fairly large expressions. - /// + /// /// Example grammar: - /// + /// /// e : e '*' e /// | e '+' e /// | INT /// ; - /// + /// /// We convert that to the following: - /// + /// /// e[int prec] /// : INT /// ( {3>=prec}? '*' e[4] /// | {2>=prec}? '+' e[3] /// )* /// ; - /// + /// /// The (..)* loop has a decision for the inner block as well as /// an enter or exit decision, which is what concerns us here. At /// the 1st + of input 1+2+3, the loop entry sees both predicates @@ -976,7 +976,7 @@ open class ParserATNSimulator: ATNSimulator { /// cannot evaluate those predicates because we have fallen off /// the edge of the stack and will in general not know which prec /// parameter is the right one to use in the predicate. - /// + /// /// Because we have special information, that these are precedence /// predicates, we can resolve them without failing over to full /// LL despite their context sensitive nature. We make an @@ -991,7 +991,7 @@ open class ParserATNSimulator: ATNSimulator { /// the same value and so we can decide to enter the loop instead /// of matching it later. That means we can strip out the other /// configuration for the exit branch. - /// + /// /// So imagine we have (14,1,$,{2>=prec}?) and then /// (14,2,$-dipsIntoOuterContext,{2>=prec}?). The optimization /// allows us to collapse these two configurations. We know that @@ -1003,33 +1003,33 @@ open class ParserATNSimulator: ATNSimulator { /// enter the loop as it is consistent with the notion of operator /// precedence. It's also how the full LL conflict resolution /// would work. - /// + /// /// The solution requires a different DFA start state for each /// precedence level. - /// + /// /// The basic filter mechanism is to remove configurations of the /// form (p, 2, pi) if (p, 1, pi) exists for the same p and pi. In /// other words, for the same ATN state and predicate context, /// remove any configuration associated with an exit branch if /// there is a configuration associated with the enter branch. - /// + /// /// It's also the case that the filter evaluates precedence /// predicates and resolves conflicts according to precedence /// levels. For example, for input 1+2+3 at the first +, we see /// prediction filtering - /// + /// /// [(11,1,[$],{3>=prec}?), (14,1,[$],{2>=prec}?), (5,2,[$],up=1), /// (11,2,[$],up=1), (14,2,[$],up=1)],hasSemanticContext=true,dipsIntoOuterContext - /// + /// /// to - /// + /// /// [(11,1,[$]), (14,1,[$]), (5,2,[$],up=1)],dipsIntoOuterContext - /// + /// /// This filters because {3>=prec}? evals to true and collapses /// (11,1,[$],{3>=prec}?) and (11,2,[$],up=1) since early conflict /// resolution based upon rules of operator precedence fits with /// our usual match first alt upon conflict. - /// + /// /// We noticed a problem where a recursive call resets precedence /// to 0. Sam's fix: each config has flag indicating if it has /// returned from an expr[0] call. then just don't filter any @@ -1040,15 +1040,15 @@ open class ParserATNSimulator: ATNSimulator { /// after leaving the rule stop state of the LR rule containing /// state p, corresponding to a rule invocation with precedence /// level 0" - /// + /// - /// + /// /// This method transforms the start state computed by /// _#computeStartState_ to the special start state used by a /// precedence DFA for a particular precedence value. The transformation /// process applies the following changes to the start state's configuration /// set. - /// + /// /// * Evaluate the precedence predicates for each configuration using /// _org.antlr.v4.runtime.atn.SemanticContext#evalPrecedence_. /// * When _org.antlr.v4.runtime.atn.ATNConfig#isPrecedenceFilterSuppressed_ is `false`, @@ -1056,7 +1056,7 @@ open class ParserATNSimulator: ATNSimulator { /// for which another configuration that predicts alternative 1 is in the /// same ATN state with the same prediction context. This transformation is /// valid for the following reasons: - /// + /// /// * The closure block cannot contain any epsilon transitions which bypass /// the body of the closure, so all states reachable via alternative 1 are /// part of the precedence alternatives of the transformed left-recursive @@ -1069,7 +1069,7 @@ open class ParserATNSimulator: ATNSimulator { /// _org.antlr.v4.runtime.atn.ATNConfig#isPrecedenceFilterSuppressed_ property marks ATN /// configurations which do not meet this condition, and therefore are not /// eligible for elimination during the filtering process. - /// + /// /// The prediction context must be considered by this filter to address /// situations like the following. /// ``` @@ -1085,13 +1085,13 @@ open class ParserATNSimulator: ATNSimulator { /// configurations distinguishes between them, and prevents the alternative /// which stepped out to `prog` (and then back in to `statement` /// from being eliminated by the filter. - /// + /// /// - parameter configs: The configuration set computed by /// _#computeStartState_ as the start state for the DFA. /// - returns: The transformed configuration set representing the start state /// for a precedence DFA at a particular precedence level (determined by /// calling _org.antlr.v4.runtime.Parser#getPrecedence_). - /// + /// final internal func applyPrecedenceFilter(_ configs: ATNConfigSet) throws -> ATNConfigSet { return try configs.applyPrecedenceFilter(&mergeCache,parser,_outerContext) } @@ -1109,18 +1109,18 @@ open class ParserATNSimulator: ATNSimulator { _ configs: ATNConfigSet, _ nalts: Int) -> [SemanticContext?]? { // REACH=[1|1|[]|0:0, 1|2|[]|0:1] - /// + /// /// altToPred starts as an array of all null contexts. The entry at index i /// corresponds to alternative i. altToPred[i] may have one of three values: /// 1. null: no ATNConfig c is found such that c.alt==i - /// 2. SemanticContext.NONE: At least one ATNConfig c exists such that - /// c.alt==i and c.semanticContext==SemanticContext.NONE. In other words, + /// 2. SemanticContext.Empty.Instance: At least one ATNConfig c exists such that + /// c.alt==i and c.semanticContext==SemanticContext.Empty.Instance. In other words, /// alt i has at least one unpredicated config. /// 3. Non-NONE Semantic Context: There exists at least one, and for all - /// ATNConfig c such that c.alt==i, c.semanticContext!=SemanticContext.NONE. - /// + /// ATNConfig c such that c.alt==i, c.semanticContext!=SemanticContext.Empty.Instance. + /// /// From this, it is clear that NONE||anything==NONE. - /// + /// let altToPred = configs.getPredsForAmbigAlts(ambigAlts,nalts) if debug { print("getPredsForAmbigAlts result \(String(describing: altToPred))") @@ -1134,13 +1134,13 @@ open class ParserATNSimulator: ATNSimulator { var containsPredicate = false for (i, pred) in altToPred.enumerated().dropFirst() { - // unpredicated is indicated by SemanticContext.NONE + // unpredicated is indicated by SemanticContext.Empty.Instance assert(pred != nil, "Expected: pred!=null") if let ambigAlts = ambigAlts, try! ambigAlts.get(i) { pairs.append(DFAState.PredPrediction(pred!, i)) } - if pred != SemanticContext.NONE { + if pred != SemanticContext.Empty.Instance { containsPredicate = true } } @@ -1152,25 +1152,25 @@ open class ParserATNSimulator: ATNSimulator { return pairs ///pairs.toArray(new, DFAState.PredPrediction[pairs.size()]); } - /// + /// /// This method is used to improve the localization of error messages by /// choosing an alternative rather than throwing a /// _org.antlr.v4.runtime.NoViableAltException_ in particular prediction scenarios where the /// _#ERROR_ state was reached during ATN simulation. - /// + /// /// The default implementation of this method uses the following /// algorithm to identify an ATN configuration which successfully parsed the /// decision entry rule. Choosing such an alternative ensures that the /// _org.antlr.v4.runtime.ParserRuleContext_ returned by the calling rule will be complete /// and valid, and the syntax error will be reported later at a more /// localized location. - /// + /// /// * If a syntactically valid path or paths reach the end of the decision rule and /// they are semantically valid if predicated, return the min associated alt. /// * Else, if a semantically invalid but syntactically valid path exist /// or paths exist, return the minimum associated alt. /// * Otherwise, return _org.antlr.v4.runtime.atn.ATN#INVALID_ALT_NUMBER_. - /// + /// /// In some scenarios, the algorithm described above could predict an /// alternative which will result in a _org.antlr.v4.runtime.FailedPredicateException_ in /// the parser. Specifically, this could occur if the __only__ configuration @@ -1182,16 +1182,16 @@ open class ParserATNSimulator: ATNSimulator { /// predicate which is preventing the parser from successfully parsing the /// decision rule, which helps developers identify and correct logic errors /// in semantic predicates. - /// + /// /// - parameter configs: The ATN configurations which were valid immediately before /// the _#ERROR_ state was reached /// - parameter outerContext: The is the \gamma_0 initial parser context from the paper /// or the parser stack at the instant before prediction commences. - /// + /// /// - returns: The value to return from _#adaptivePredict_, or /// _org.antlr.v4.runtime.atn.ATN#INVALID_ALT_NUMBER_ if a suitable alternative was not /// identified and _#adaptivePredict_ should report an error instead. - /// + /// final internal func getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(_ configs: ATNConfigSet, _ outerContext: ParserRuleContext) throws -> Int { let (semValidConfigs, semInvalidConfigs) = try splitAccordingToSemanticValidity(configs, outerContext) @@ -1216,16 +1216,16 @@ open class ParserATNSimulator: ATNSimulator { return configs.getAltThatFinishedDecisionEntryRule() } - /// + /// /// Walk the list of configurations and split them according to /// those that have preds evaluating to true/false. If no pred, assume /// true pred and include in succeeded set. Returns Pair of sets. - /// + /// /// Create a new set so as not to alter the incoming parameter. - /// + /// /// Assumption: the input stream has been restored to the starting point /// prediction, which is where predicates need to evaluate. - /// + /// final internal func splitAccordingToSemanticValidity( _ configs: ATNConfigSet, _ outerContext: ParserRuleContext) throws -> (ATNConfigSet, ATNConfigSet) { @@ -1233,19 +1233,19 @@ open class ParserATNSimulator: ATNSimulator { return try configs.splitAccordingToSemanticValidity(outerContext, evalSemanticContext) } - /// + /// /// Look through a list of predicate/alt pairs, returning alts for the /// pairs that win. A `NONE` predicate indicates an alt containing an /// unpredicated config which behaves as "always true." If !complete /// then we stop at the first predicate that evaluates to true. This /// includes pairs with null predicates. - /// + /// final internal func evalSemanticContext(_ predPredictions: [DFAState.PredPrediction], _ outerContext: ParserRuleContext, _ complete: Bool) throws -> BitSet { let predictions = BitSet() for pair in predPredictions { - if pair.pred == SemanticContext.NONE { + if pair.pred == SemanticContext.Empty.Instance { try! predictions.set(pair.alt) if !complete { break @@ -1273,13 +1273,13 @@ open class ParserATNSimulator: ATNSimulator { return predictions } - /// + /// /// Evaluate a semantic context within a specific parser context. - /// + /// /// This method might not be called for every semantic context evaluated /// during the prediction process. In particular, we currently do not /// evaluate the following but it may change in the future: - /// + /// /// * Precedence predicates (represented by /// _org.antlr.v4.runtime.atn.SemanticContext.PrecedencePredicate_) are not currently evaluated /// through this method. @@ -1289,7 +1289,7 @@ open class ParserATNSimulator: ATNSimulator { /// Implementations which require evaluation results from individual /// predicates should override this method to explicitly handle evaluation of /// the operands within operator predicates. - /// + /// /// - parameter pred: The semantic context to evaluate /// - parameter parserCallStack: The parser context in which to evaluate the /// semantic context @@ -1297,20 +1297,20 @@ open class ParserATNSimulator: ATNSimulator { /// - parameter fullCtx: `true` if the evaluation is occurring during LL /// prediction; otherwise, `false` if the evaluation is occurring /// during SLL prediction - /// + /// /// - since: 4.3 - /// + /// internal func evalSemanticContext(_ pred: SemanticContext, _ parserCallStack: ParserRuleContext, _ alt: Int, _ fullCtx: Bool) throws -> Bool { return try pred.eval(parser, parserCallStack) } - /// + /// /// TODO: If we are doing predicates, there is no point in pursuing /// closure operations if we reach a DFA state that uniquely predicts /// alternative. We will not be caching that DFA state and it is a /// waste to pursue the closure. Might have to advance when we do /// ambig detection thought :( - /// + /// final internal func closure(_ config: ATNConfig, _ configs: ATNConfigSet, _ closureBusy: inout Set, @@ -1344,7 +1344,7 @@ open class ParserATNSimulator: ATNSimulator { for i in 0.., @@ -1478,50 +1478,50 @@ open class ParserATNSimulator: ATNSimulator { //print("That took: "+(finishTime-startTime)+ " ms"); } - /// + /// /// Implements first-edge (loop entry) elimination as an optimization /// during closure operations. See antlr/antlr4#1398. - /// + /// /// The optimization is to avoid adding the loop entry config when /// the exit path can only lead back to the same /// StarLoopEntryState after popping context at the rule end state /// (traversing only epsilon edges, so we're still in closure, in /// this same rule). - /// + /// /// We need to detect any state that can reach loop entry on /// epsilon w/o exiting rule. We don't have to look at FOLLOW /// links, just ensure that all stack tops for config refer to key /// states in LR rule. - /// + /// /// To verify we are in the right situation we must first check /// closure is at a StarLoopEntryState generated during LR removal. /// Then we check that each stack top of context is a return state /// from one of these cases: - /// + /// /// 1. 'not' expr, '(' type ')' expr. The return state points at loop entry state /// 2. expr op expr. The return state is the block end of internal block of (...)* /// 3. 'between' expr 'and' expr. The return state of 2nd expr reference. /// That state points at block end of internal block of (...)*. /// 4. expr '?' expr ':' expr. The return state points at block end, /// which points at loop entry state. - /// + /// /// If any is true for each stack top, then closure does not add a /// config to the current config set for edge[0], the loop entry branch. - /// + /// /// Conditions fail if any context for the current config is: - /// + /// /// a. empty (we'd fall out of expr to do a global FOLLOW which could /// even be to some weird spot in expr) or, /// b. lies outside of expr or, /// c. lies within expr but at a state not the BlockEndState /// generated during LR removal - /// + /// /// Do we need to evaluate predicates ever in closure for this case? - /// + /// /// No. Predicates, including precedence predicates, are only /// evaluated when computing a DFA start state. I.e., only before /// the lookahead (but not parser) consumes a token. - /// + /// /// There are no epsilon edges allowed in LR rule alt blocks or in /// the "primary" part (ID here). If closure is in /// StarLoopEntryState any lookahead operation will have consumed a @@ -1533,9 +1533,9 @@ open class ParserATNSimulator: ATNSimulator { /// closure starting at edges[0], edges[1] emanating from /// StarLoopEntryState. That means it is not performing closure on /// StarLoopEntryState during compute-start-state. - /// + /// /// How do we know this always gives same prediction answer? - /// + /// /// Without predicates, loop entry and exit paths are ambiguous /// upon remaining input +b (in, say, a+b). Either paths lead to /// valid parses. Closure can lead to consuming + immediately or by @@ -1543,30 +1543,30 @@ open class ParserATNSimulator: ATNSimulator { /// again to StarLoopEntryState to match +b. In this special case, /// we choose the more efficient path, which is to take the bypass /// path. - /// + /// /// The lookahead language has not changed because closure chooses /// one path over the other. Both paths lead to consuming the same /// remaining input during a lookahead operation. If the next token /// is an operator, lookahead will enter the choice block with /// operators. If it is not, lookahead will exit expr. Same as if /// closure had chosen to enter the choice block immediately. - /// + /// /// Closure is examining one config (some loopentrystate, some alt, /// context) which means it is considering exactly one alt. Closure /// always copies the same alt to any derived configs. - /// + /// /// How do we know this optimization doesn't mess up precedence in /// our parse trees? - /// + /// /// Looking through expr from left edge of stat only has to confirm /// that an input, say, a+b+c; begins with any valid interpretation /// of an expression. The precedence actually doesn't matter when /// making a decision in stat seeing through expr. It is only when /// parsing rule expr that we must use the precedence to get the /// right interpretation and, hence, parse tree. - /// + /// /// - 4.6 - /// + /// internal func canDropLoopEntryEdgeInLeftRecursiveRule(_ config: ATNConfig) -> Bool { if ParserATNSimulator.TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT { return false @@ -1799,27 +1799,27 @@ open class ParserATNSimulator: ATNSimulator { return ATNConfig(config, t.target, newContext) } - /// + /// /// Gets a _java.util.BitSet_ containing the alternatives in `configs` /// which are part of one or more conflicting alternative subsets. - /// + /// /// - parameter configs: The _org.antlr.v4.runtime.atn.ATNConfigSet_ to analyze. /// - returns: The alternatives in `configs` which are part of one or more /// conflicting alternative subsets. If `configs` does not contain any /// conflicting subsets, this method returns an empty _java.util.BitSet_. - /// + /// final func getConflictingAlts(_ configs: ATNConfigSet) -> BitSet { let altsets = PredictionMode.getConflictingAltSubsets(configs) return PredictionMode.getAlts(altsets) } - /// + /// /// Sam pointed out a problem with the previous definition, v3, of /// ambiguous states. If we have another state associated with conflicting /// alternatives, we should keep going. For example, the following grammar - /// + /// /// s : (ID | ID ID?) ';' ; - /// + /// /// When the ATN simulation reaches the state before ';', it has a DFA /// state that looks like: [12|1|[], 6|2|[], 12|2|[]]. Naturally /// 12|1|[] and 12|2|[] conflict, but we cannot stop processing this node @@ -1831,13 +1831,13 @@ open class ParserATNSimulator: ATNSimulator { /// ignore the conflict between alts 1 and 2. We ignore a set of /// conflicting alts when there is an intersection with an alternative /// associated with a single alt state in the state→config-list map. - /// + /// /// It's also the case that we might have two conflicting configurations but /// also a 3rd nonconflicting configuration for a different alternative: /// [1|1|[], 1|2|[], 8|3|[]]. This can come about from grammar: - /// + /// /// a : A | A | A B ; - /// + /// /// After matching input A, we reach the stop state for rule A, state 1. /// State 8 is the state right before B. Clearly alternatives 1 and 2 /// conflict and no amount of further lookahead will separate the two. @@ -1848,7 +1848,7 @@ open class ParserATNSimulator: ATNSimulator { /// looking for input reasonably, I don't declare the state done. We /// ignore a set of conflicting alts when we have an alternative /// that we still need to pursue. - /// + /// final func getConflictingAltsOrUniqueAlt(_ configs: ATNConfigSet) -> BitSet { var conflictingAlts: BitSet if configs.uniqueAlt != ATN.INVALID_ALT_NUMBER { @@ -1878,11 +1878,11 @@ open class ParserATNSimulator: ATNSimulator { return try getTokenName(input.LA(1)) } - /// + /// /// Used for debugging in adaptivePredict around execATN but I cut /// it out for clarity now that alg. works well. We can leave this /// "dead" code for a bit. - /// + /// public final func dumpDeadEndConfigs(_ nvae: NoViableAltException) { errPrint("dead end configs: ") for c in nvae.getDeadEndConfigs()!.configs { @@ -1921,24 +1921,24 @@ open class ParserATNSimulator: ATNSimulator { return alt } - /// + /// /// Add an edge to the DFA, if possible. This method calls /// _#addDFAState_ to ensure the `to` state is present in the /// DFA. If `from` is `null`, or if `t` is outside the /// range of edges that can be represented in the DFA tables, this method /// returns without adding the edge to the DFA. - /// + /// /// If `to` is `null`, this method returns `null`. /// Otherwise, this method returns the _org.antlr.v4.runtime.dfa.DFAState_ returned by calling /// _#addDFAState_ for the `to` state. - /// + /// /// - parameter dfa: The DFA /// - parameter from: The source state for the edge /// - parameter t: The input symbol /// - parameter to: The target state for the edge - /// + /// /// - returns: the result of calling _#addDFAState_ on `to` - /// + /// @discardableResult private final func addDFAEdge(_ dfa: DFA, _ from: DFAState, @@ -1969,38 +1969,38 @@ open class ParserATNSimulator: ATNSimulator { return to } - /// + /// /// Add state `D` to the DFA if it is not already present, and return /// the actual instance stored in the DFA. If a state equivalent to `D` /// is already in the DFA, the existing state is returned. Otherwise this /// method returns `D` after adding it to the DFA. - /// + /// /// If `D` is _#ERROR_, this method returns _#ERROR_ and /// does not change the DFA. - /// + /// /// - parameter dfa: The dfa /// - parameter D: The DFA state to add /// - returns: The state stored in the DFA. This will be either the existing /// state if `D` is already in the DFA, or `D` itself if the /// state was not already present. - /// + /// private final func addDFAState(_ dfa: DFA, _ D: DFAState) -> DFAState { if D == ATNSimulator.ERROR { return D } - + return dfa.statesMutex.synchronized { if let existing = dfa.states[D] { return existing } D.stateNumber = dfa.states.count - + if !D.configs.isReadonly() { try! D.configs.optimizeConfigs(self) D.configs.setReadonly(true) } - + dfa.states[D] = D if debug { print("adding new DFA state: \(D)") @@ -2026,9 +2026,9 @@ open class ParserATNSimulator: ATNSimulator { parser.getErrorListenerDispatch().reportContextSensitivity(parser, dfa, startIndex, stopIndex, prediction, configs) } - /// + /// /// If context sensitive parsing, we know it's ambiguity not conflict - /// + /// // configs that LL not SLL considered conflictin internal func reportAmbiguity(_ dfa: DFA, _ D: DFAState, // the DFA state from execATN() that had SLL conflicts diff --git a/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift b/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift index d7ab6f9f68..8ef0a166aa 100644 --- a/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift +++ b/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift @@ -1,24 +1,18 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// import Foundation public class PredictionContext: Hashable, CustomStringConvertible { - /// - /// Represents `$` in local context prediction, which means wildcard. - /// `+x = *`. - /// - public static let EMPTY = EmptyPredictionContext() - - /// + /// /// Represents `$` in an array in full context mode, when `$` /// doesn't mean wildcard: `$ + x = [$,x]`. Here, /// `$` = _#EMPTY_RETURN_STATE_. - /// + /// public static let EMPTY_RETURN_STATE = Int(Int32.max) private static let INITIAL_HASH = UInt32(1) @@ -31,44 +25,44 @@ public class PredictionContext: Hashable, CustomStringConvertible { return oldGlobalNodeCount }() - /// + /// /// Stores the computed hash code of this _org.antlr.v4.runtime.atn.PredictionContext_. The hash /// code is computed in parts to match the following reference algorithm. - /// - /// + /// + /// /// private int referenceHashCode() { /// int hash = _org.antlr.v4.runtime.misc.MurmurHash#initialize MurmurHash.initialize_(_#INITIAL_HASH_); - /// + /// /// for (int i = 0; i < _#size()_; i++) { /// hash = _org.antlr.v4.runtime.misc.MurmurHash#update MurmurHash.update_(hash, _#getParent getParent_(i)); /// } - /// + /// /// for (int i = 0; i < _#size()_; i++) { /// hash = _org.antlr.v4.runtime.misc.MurmurHash#update MurmurHash.update_(hash, _#getReturnState getReturnState_(i)); /// } - /// + /// /// hash = _org.antlr.v4.runtime.misc.MurmurHash#finish MurmurHash.finish_(hash, 2 * _#size()_); /// return hash; /// } - /// - /// + /// + /// public let cachedHashCode: Int init(_ cachedHashCode: Int) { self.cachedHashCode = cachedHashCode } - /// + /// /// Convert a _org.antlr.v4.runtime.RuleContext_ tree to a _org.antlr.v4.runtime.atn.PredictionContext_ graph. /// Return _#EMPTY_ if `outerContext` is empty or null. - /// + /// public static func fromRuleContext(_ atn: ATN, _ outerContext: RuleContext?) -> PredictionContext { - let _outerContext = outerContext ?? RuleContext.EMPTY + let _outerContext = outerContext ?? ParserRuleContext.EMPTY // if we are in RuleContext of start rule, s, then PredictionContext // is EMPTY. Nobody called us. (if we are empty, return empty) - if (_outerContext.parent == nil || _outerContext === RuleContext.EMPTY) { - return PredictionContext.EMPTY + if (_outerContext.parent == nil || _outerContext === ParserRuleContext.EMPTY) { + return EmptyPredictionContext.Instance } // If we have a parent, convert it to a PredictionContext graph @@ -94,11 +88,11 @@ public class PredictionContext: Hashable, CustomStringConvertible { } - /// + /// /// This means only the _#EMPTY_ context is in set. - /// + /// public func isEmpty() -> Bool { - return self === PredictionContext.EMPTY + return self === EmptyPredictionContext.Instance } public func hasEmptyPath() -> Bool { @@ -176,33 +170,33 @@ public class PredictionContext: Hashable, CustomStringConvertible { rootIsWildcard, &mergeCache) } - /// + /// /// Merge two _org.antlr.v4.runtime.atn.SingletonPredictionContext_ instances. - /// + /// /// Stack tops equal, parents merge is same; return left graph. - /// - /// + /// + /// /// Same stack top, parents differ; merge parents giving array node, then /// remainders of those graphs. A new root node is created to point to the /// merged parents. - /// - /// + /// + /// /// Different stack tops pointing to same parent. Make array node for the /// root where both element in the root point to the same (original) /// parent. - /// - /// + /// + /// /// Different stack tops pointing to different parents. Make array node for /// the root where each element points to the corresponding original /// parent. - /// - /// + /// + /// /// - parameter a: the first _org.antlr.v4.runtime.atn.SingletonPredictionContext_ /// - parameter b: the second _org.antlr.v4.runtime.atn.SingletonPredictionContext_ /// - parameter rootIsWildcard: `true` if this is a local-context merge, /// otherwise false to indicate a full-context merge /// - parameter mergeCache: - /// + /// public static func mergeSingletons( _ a: SingletonPredictionContext, _ b: SingletonPredictionContext, @@ -285,66 +279,66 @@ public class PredictionContext: Hashable, CustomStringConvertible { } } - /// + /// /// Handle case where at least one of `a` or `b` is /// _#EMPTY_. In the following diagrams, the symbol `$` is used /// to represent _#EMPTY_. - /// + /// /// Local-Context Merges - /// + /// /// These local-context merge operations are used when `rootIsWildcard` /// is true. - /// + /// /// _#EMPTY_ is superset of any graph; return _#EMPTY_. - /// - /// + /// + /// /// _#EMPTY_ and anything is `#EMPTY`, so merged parent is /// `#EMPTY`; return left graph. - /// - /// + /// + /// /// Special case of last merge if local context. - /// - /// + /// + /// /// Full-Context Merges - /// + /// /// These full-context merge operations are used when `rootIsWildcard` /// is false. - /// - /// - /// + /// + /// + /// /// Must keep all contexts; _#EMPTY_ in array is a special value (and /// null parent). - /// - /// - /// - /// + /// + /// + /// + /// /// - parameter a: the first _org.antlr.v4.runtime.atn.SingletonPredictionContext_ /// - parameter b: the second _org.antlr.v4.runtime.atn.SingletonPredictionContext_ /// - parameter rootIsWildcard: `true` if this is a local-context merge, /// otherwise false to indicate a full-context merge - /// + /// public static func mergeRoot(_ a: SingletonPredictionContext, _ b: SingletonPredictionContext, _ rootIsWildcard: Bool) -> PredictionContext? { if rootIsWildcard { - if a === PredictionContext.EMPTY { - return PredictionContext.EMPTY + if a === EmptyPredictionContext.Instance { + return EmptyPredictionContext.Instance } // * + b = * - if b === PredictionContext.EMPTY { - return PredictionContext.EMPTY + if b === EmptyPredictionContext.Instance { + return EmptyPredictionContext.Instance } // a + * = * } else { - if a === PredictionContext.EMPTY && b === PredictionContext.EMPTY { - return PredictionContext.EMPTY + if a === EmptyPredictionContext.Instance && b === EmptyPredictionContext.Instance { + return EmptyPredictionContext.Instance } // $ + $ = $ - if a === PredictionContext.EMPTY { + if a === EmptyPredictionContext.Instance { // $ + x = [$,x] let payloads = [b.returnState, EMPTY_RETURN_STATE] let parents = [b.parent, nil] let joined = ArrayPredictionContext(parents, payloads) return joined } - if b === PredictionContext.EMPTY { + if b === EmptyPredictionContext.Instance { // x + $ = [$,x] ($ is always first if present) let payloads = [a.returnState, EMPTY_RETURN_STATE] let parents = [a.parent, nil] @@ -355,25 +349,25 @@ public class PredictionContext: Hashable, CustomStringConvertible { return nil } - /// + /// /// Merge two _org.antlr.v4.runtime.atn.ArrayPredictionContext_ instances. - /// + /// /// Different tops, different parents. - /// - /// + /// + /// /// Shared top, same parents. - /// - /// + /// + /// /// Shared top, different parents. - /// - /// + /// + /// /// Shared top, all shared parents. - /// - /// + /// + /// /// Equal tops, merge parents and reduce top to /// _org.antlr.v4.runtime.atn.SingletonPredictionContext_. - /// - /// + /// + /// public static func mergeArrays( _ a: ArrayPredictionContext, _ b: ArrayPredictionContext, @@ -530,7 +524,7 @@ public class PredictionContext: Hashable, CustomStringConvertible { } for current in nodes { - if current === EMPTY { + if current === EmptyPredictionContext.Instance { continue } let length = current.size() @@ -601,7 +595,7 @@ public class PredictionContext: Hashable, CustomStringConvertible { let updated: PredictionContext if parents.isEmpty { - updated = EMPTY + updated = EmptyPredictionContext.Instance } else if parents.count == 1 { updated = SingletonPredictionContext.create(parents[0], context.getReturnState(0)) @@ -648,7 +642,7 @@ public class PredictionContext: Hashable, CustomStringConvertible { } public func toStrings(_ recognizer: Recognizer, _ currentState: Int) -> [String] { - return toStrings(recognizer, PredictionContext.EMPTY, currentState) + return toStrings(recognizer, EmptyPredictionContext.Instance, currentState) } // FROM SAM diff --git a/runtime/Swift/Sources/Antlr4/atn/PredictionContextCache.swift b/runtime/Swift/Sources/Antlr4/atn/PredictionContextCache.swift index 491c40ce10..813c6223b7 100644 --- a/runtime/Swift/Sources/Antlr4/atn/PredictionContextCache.swift +++ b/runtime/Swift/Sources/Antlr4/atn/PredictionContextCache.swift @@ -1,15 +1,15 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// -/// +/// /// Used to cache _org.antlr.v4.runtime.atn.PredictionContext_ objects. Its used for the shared /// context cash associated with contexts in DFA states. This cache /// can be used for both lexers and parsers. -/// +/// public final class PredictionContextCache { private var cache = [PredictionContext: PredictionContext]() @@ -21,11 +21,11 @@ public final class PredictionContextCache { /// Add a context to the cache and return it. If the context already exists, /// return that one instead and do not add a new context to the cache. /// Protect shared cache from unsafe thread access. - /// + /// @discardableResult public func add(_ ctx: PredictionContext) -> PredictionContext { - if ctx === PredictionContext.EMPTY { - return PredictionContext.EMPTY + if ctx === EmptyPredictionContext.Instance { + return EmptyPredictionContext.Instance } if let existing = cache[ctx] { // print(name+" reuses "+existing); diff --git a/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift b/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift index ef4b1fdefe..e14a7fdde7 100644 --- a/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift +++ b/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift @@ -1,49 +1,43 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// -/// +/// /// A tree structure used to record the semantic context in which /// an ATN configuration is valid. It's either a single predicate, /// a conjunction `p1&&p2`, or a sum of products `p1||p2`. -/// +/// /// I have scoped the _org.antlr.v4.runtime.atn.SemanticContext.AND_, _org.antlr.v4.runtime.atn.SemanticContext.OR_, and _org.antlr.v4.runtime.atn.SemanticContext.Predicate_ subclasses of /// _org.antlr.v4.runtime.atn.SemanticContext_ within the scope of this outer class. -/// +/// import Foundation public class SemanticContext: Hashable, CustomStringConvertible { - /// - /// The default _org.antlr.v4.runtime.atn.SemanticContext_, which is semantically equivalent to - /// a predicate of the form `{true`?}. - /// - public static let NONE: SemanticContext = Predicate() - - /// + /// /// For context independent predicates, we evaluate them without a local /// context (i.e., null context). That way, we can evaluate them without /// having to create proper rule-specific context during prediction (as /// opposed to the parser, which creates them naturally). In a practical /// sense, this avoids a cast exception from RuleContext to myruleContext. - /// + /// /// For context dependent predicates, we must pass in a local context so that /// references such as $arg evaluate properly as _localctx.arg. We only /// capture context dependent predicates in the context in which we begin /// prediction, so we passed in the outer context here in case of context /// dependent predicate evaluation. - /// + /// public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { fatalError(#function + " must be overridden") } - /// + /// /// Evaluate the precedence predicates for the context and reduce the result. - /// + /// /// - parameter parser: The parser instance. /// - parameter parserCallStack: /// - returns: The simplified semantic context after precedence predicates are @@ -56,7 +50,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { /// precedence predicate evaluation. /// * A non-`null` _org.antlr.v4.runtime.atn.SemanticContext_: the new simplified /// semantic context after precedence predicates are evaluated. - /// + /// public func evalPrecedence(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> SemanticContext? { return self } @@ -69,6 +63,22 @@ public class SemanticContext: Hashable, CustomStringConvertible { fatalError(#function + " must be overridden") } + public class Empty: SemanticContext { + // + /// The default _org.antlr.v4.runtime.atn.SemanticContext_, which is semantically equivalent to + /// a predicate of the form `{true?}. + /// + public static let Instance: Empty = Empty() + + public override func hash(into hasher: inout Hasher) { + } + + override + public var description: String { + return "{true}?" + } + } + public class Predicate: SemanticContext { public let ruleIndex: Int public let predIndex: Int @@ -127,7 +137,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { override public func evalPrecedence(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> SemanticContext? { if parser.precpred(parserCallStack, precedence) { - return SemanticContext.NONE + return SemanticContext.Empty.Instance } else { return nil } @@ -145,32 +155,32 @@ public class SemanticContext: Hashable, CustomStringConvertible { } } - /// + /// /// This is the base class for semantic context "operators", which operate on /// a collection of semantic context "operands". - /// + /// /// - 4.3 - /// + /// public class Operator: SemanticContext { - /// + /// /// Gets the operands for the semantic context operator. - /// + /// /// - returns: a collection of _org.antlr.v4.runtime.atn.SemanticContext_ operands for the /// operator. - /// + /// /// - 4.3 - /// + /// public func getOperands() -> Array { fatalError(#function + " must be overridden") } } - /// + /// /// A semantic context which is true whenever none of the contained contexts /// is false. - /// + /// public class AND: Operator { public let opnds: [SemanticContext] @@ -211,13 +221,13 @@ public class SemanticContext: Hashable, CustomStringConvertible { hasher.combine(opnds) } - /// - /// - /// - /// + /// + /// + /// + /// /// The evaluation of predicates by this context is short-circuiting, but /// unordered. - /// + /// override public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { for opnd in opnds { @@ -242,7 +252,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { // The AND context is false if any element is false return nil } - else if evaluated != SemanticContext.NONE { + else if evaluated != SemanticContext.Empty.Instance { // Reduce the result by skipping true elements operands.append(evaluated!) } @@ -252,7 +262,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { return self } - return operands.reduce(SemanticContext.NONE, SemanticContext.and) + return operands.reduce(SemanticContext.Empty.Instance, SemanticContext.and) } override @@ -262,10 +272,10 @@ public class SemanticContext: Hashable, CustomStringConvertible { } } - /// + /// /// A semantic context which is true whenever at least one of the contained /// contexts is true. - /// + /// public class OR: Operator { public final var opnds: [SemanticContext] @@ -305,13 +315,13 @@ public class SemanticContext: Hashable, CustomStringConvertible { hasher.combine(opnds) } - /// - /// - /// - /// + /// + /// + /// + /// /// The evaluation of predicates by this context is short-circuiting, but /// unordered. - /// + /// override public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { for opnd in opnds { @@ -329,9 +339,9 @@ public class SemanticContext: Hashable, CustomStringConvertible { for context in opnds { let evaluated = try context.evalPrecedence(parser, parserCallStack) differs = differs || (evaluated != context) - if evaluated == SemanticContext.NONE { + if evaluated == SemanticContext.Empty.Instance { // The OR context is true if any element is true - return SemanticContext.NONE + return SemanticContext.Empty.Instance } else if let evaluated = evaluated { // Reduce the result by skipping false elements @@ -354,10 +364,10 @@ public class SemanticContext: Hashable, CustomStringConvertible { } public static func and(_ a: SemanticContext?, _ b: SemanticContext?) -> SemanticContext { - if a == nil || a == SemanticContext.NONE { + if a == nil || a == SemanticContext.Empty.Instance { return b! } - if b == nil || b == SemanticContext.NONE { + if b == nil || b == SemanticContext.Empty.Instance { return a! } let result: AND = AND(a!, b!) @@ -368,10 +378,10 @@ public class SemanticContext: Hashable, CustomStringConvertible { return result } - /// - /// + /// + /// /// - seealso: org.antlr.v4.runtime.atn.ParserATNSimulator#getPredsForAmbigAlts - /// + /// public static func or(_ a: SemanticContext?, _ b: SemanticContext?) -> SemanticContext { if a == nil { return b! @@ -379,8 +389,8 @@ public class SemanticContext: Hashable, CustomStringConvertible { if b == nil { return a! } - if a == SemanticContext.NONE || b == SemanticContext.NONE { - return SemanticContext.NONE + if a == SemanticContext.Empty.Instance || b == SemanticContext.Empty.Instance { + return SemanticContext.Empty.Instance } let result: OR = OR(a!, b!) if result.opnds.count == 1 { diff --git a/runtime/Swift/Sources/Antlr4/atn/SingletonPredictionContext.swift b/runtime/Swift/Sources/Antlr4/atn/SingletonPredictionContext.swift index e40971492d..2947efa2d1 100644 --- a/runtime/Swift/Sources/Antlr4/atn/SingletonPredictionContext.swift +++ b/runtime/Swift/Sources/Antlr4/atn/SingletonPredictionContext.swift @@ -1,8 +1,8 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// @@ -24,7 +24,7 @@ public class SingletonPredictionContext: PredictionContext { public static func create(_ parent: PredictionContext?, _ returnState: Int) -> SingletonPredictionContext { if returnState == PredictionContext.EMPTY_RETURN_STATE && parent == nil { // someone can pass in the bits of an array ctx that mean $ - return PredictionContext.EMPTY + return EmptyPredictionContext.Instance } return SingletonPredictionContext(parent, returnState) } diff --git a/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift b/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift index 360abb9278..acc2f8ed82 100644 --- a/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift +++ b/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift @@ -1,11 +1,11 @@ -/// +/// /// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. /// Use of this file is governed by the BSD 3-clause license that /// can be found in the LICENSE.txt file in the project root. -/// +/// -/// +/// /// A DFA state represents a set of possible ATN configurations. /// As Aho, Sethi, Ullman p. 117 says "The DFA uses its state /// to keep track of all possible states the ATN can be in after @@ -21,22 +21,22 @@ /// jump from rule to rule, emulating rule invocations (method calls). /// I have to add a stack to simulate the proper lookahead sequences for /// the underlying LL grammar from which the ATN was derived. -/// +/// /// I use a set of ATNConfig objects not simple states. An ATNConfig /// is both a state (ala normal conversion) and a RuleContext describing /// the chain of rules (if any) followed to arrive at that state. -/// +/// /// A DFA state may have multiple references to a particular state, /// but with different ATN contexts (with same or different alts) /// meaning that state was reached via a different set of rule invocations. -/// +/// public final class DFAState: Hashable, CustomStringConvertible { public internal(set) var stateNumber = ATNState.INVALID_STATE_NUMBER public internal(set) var configs: ATNConfigSet - /// + /// /// `edges[symbol]` points to target of symbol. Shift up by 1 so (-1) /// _org.antlr.v4.runtime.Token#EOF_ maps to `edges[0]`. /// @@ -44,51 +44,51 @@ public final class DFAState: Hashable, CustomStringConvertible { public internal(set) var isAcceptState = false - /// + /// /// if accept state, what ttype do we match or alt do we predict? /// This is set to _org.antlr.v4.runtime.atn.ATN#INVALID_ALT_NUMBER_ when _#predicates_`!=null` or /// _#requiresFullContext_. - /// + /// public internal(set) var prediction = ATN.INVALID_ALT_NUMBER public internal(set) var lexerActionExecutor: LexerActionExecutor? - /// + /// /// Indicates that this state was created during SLL prediction that /// discovered a conflict between the configurations in the state. Future /// _org.antlr.v4.runtime.atn.ParserATNSimulator#execATN_ invocations immediately jumped doing /// full context prediction if this field is true. - /// + /// public internal(set) var requiresFullContext = false - /// + /// /// During SLL parsing, this is a list of predicates associated with the /// ATN configurations of the DFA state. When we have predicates, /// _#requiresFullContext_ is `false` since full context prediction evaluates predicates /// on-the-fly. If this is not null, then _#prediction_ is /// _org.antlr.v4.runtime.atn.ATN#INVALID_ALT_NUMBER_. - /// + /// /// We only use these for non-_#requiresFullContext_ but conflicting states. That /// means we know from the context (it's $ or we don't dip into outer /// context) that it's an ambiguity not a conflict. - /// + /// /// This list is computed by _org.antlr.v4.runtime.atn.ParserATNSimulator#predicateDFAState_. - /// + /// public internal(set) var predicates: [PredPrediction]? - + /// /// mutex for states changes. /// internal private(set) var mutex = Mutex() - /// + /// /// Map a predicate to a predicted alternative. - /// + /// public final class PredPrediction: CustomStringConvertible { public let pred: SemanticContext - // never null; at least SemanticContext.NONE + // never null; at least SemanticContext.Empty.Instance public let alt: Int public init(_ pred: SemanticContext, _ alt: Int) { @@ -105,10 +105,10 @@ public final class DFAState: Hashable, CustomStringConvertible { self.configs = configs } - /// + /// /// Get the set of all alts mentioned by all ATN configurations in this /// DFA state. - /// + /// public func getAltSet() -> Set? { return configs.getAltSet() } diff --git a/runtime/Swift/Sources/Antlr4/misc/utils/Mutex.swift b/runtime/Swift/Sources/Antlr4/misc/utils/Mutex.swift index 5be0c28a8a..082ce54959 100644 --- a/runtime/Swift/Sources/Antlr4/misc/utils/Mutex.swift +++ b/runtime/Swift/Sources/Antlr4/misc/utils/Mutex.swift @@ -1,42 +1,29 @@ import Foundation -/// +/// /// Using class so it can be shared even if /// it appears to be a field in a class. -/// +/// class Mutex { - - /// + /// /// The mutex instance. - /// - private var mutex = pthread_mutex_t() - - /// - /// Initialization - /// - init() { - pthread_mutex_init(&mutex, nil) - } - - /// + /// + private let semaphore = DispatchSemaphore(value: 1) + + /// /// Running the supplied closure synchronously. - /// + /// /// - Parameter closure: the closure to run /// - Returns: the value returned by the closure /// - Throws: the exception populated by the closure run - /// + /// @discardableResult func synchronized(closure: () throws -> R) rethrows -> R { - pthread_mutex_lock(&mutex) + semaphore.wait() defer { - pthread_mutex_unlock(&mutex) + semaphore.signal() } return try closure() } - - deinit { - // free the mutex resource - pthread_mutex_destroy(&mutex) - } } diff --git a/tool-testsuite/pom.xml b/tool-testsuite/pom.xml index 89199dd821..fa05ff6408 100644 --- a/tool-testsuite/pom.xml +++ b/tool-testsuite/pom.xml @@ -30,40 +30,40 @@ org.antlr ST4 - 4.3.1 + 4.3.3 test org.antlr antlr4-runtime-testsuite ${project.version} - test - test-jar + test + test-jar org.antlr antlr4 ${project.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${jUnitVersion} - test - - - org.junit.jupiter - junit-jupiter-engine - ${jUnitVersion} - test - - - org.junit.jupiter - junit-jupiter-params - ${jUnitVersion} - test - + test + + + org.junit.jupiter + junit-jupiter-api + ${jUnitVersion} + test + + + org.junit.jupiter + junit-jupiter-engine + ${jUnitVersion} + test + + + org.junit.jupiter + junit-jupiter-params + ${jUnitVersion} + test + @@ -76,17 +76,8 @@ -Dfile.encoding=UTF-8 - - **/Test*.java - - - ../../antlr4-python2/src - ../../antlr4-python3/src - ../../antlr4-cpp/src - ../../antlr4-javascript/src - - + \ No newline at end of file diff --git a/tool/pom.xml b/tool/pom.xml index b559c3980e..bbeafc7649 100644 --- a/tool/pom.xml +++ b/tool/pom.xml @@ -44,12 +44,12 @@ org.glassfish javax.json - 1.0.4 + 1.1.4 com.ibm.icu icu4j - 69.1 + 71.1