diff --git a/.travis.yml b/.travis.yml index d9969b6eb..2897de583 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,13 @@ 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: diff --git a/.travis/before-install-osx-dotnet.sh b/.travis/before-install-osx-dotnet.sh index c784ba091..300747d3e 100755 --- a/.travis/before-install-osx-dotnet.sh +++ b/.travis/before-install-osx-dotnet.sh @@ -2,6 +2,11 @@ set -euo pipefail +cache_dir="$HOME/Library/Caches/Antlr4" +dotnet_url='https://download.microsoft.com/download/B/9/F/B9F1AF57-C14A-4670-9973-CDF47209B5BF/dotnet-dev-osx-x64.1.0.4.pkg' +dotnet_file=$(basename "$dotnet_url") +dotnet_shasum='63b5d99028cd8b2454736076106c96ba7d05f0fc' + thisdir=$(dirname "$0") # OpenSSL setup for dotnet core @@ -10,10 +15,23 @@ ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/ ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/ # download dotnet core -curl https://download.microsoft.com/download/B/9/F/B9F1AF57-C14A-4670-9973-CDF47209B5BF/dotnet-dev-osx-x64.1.0.4.pkg -o /tmp/dotnet-dev-osx-x64.1.0.4.pkg +mkdir -p "$cache_dir" +(cd "$cache_dir" + if [ -f "$dotnet_file" ] + then + if ! shasum -s -c <<<"$dotnet_shasum $dotnet_file" + then + rm -f "$dotnet_file" + fi + fi + if ! [ -f "$dotnet_file" ] + then + curl "$dotnet_url" -o "$dotnet_file" + fi +) # install dotnet core -sudo installer -pkg /tmp/dotnet-dev-osx-x64.1.0.4.pkg -target / +sudo installer -pkg "$cache_dir/$dotnet_file" -target / # make the link ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/ diff --git a/.travis/run-tests-swift.sh b/.travis/run-tests-swift.sh index 8c63070aa..b78a1bb42 100755 --- a/.travis/run-tests-swift.sh +++ b/.travis/run-tests-swift.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -euo pipefail + # linux specific setup, those setup have to be # here since environment variables doesn't pass # across scripts @@ -13,10 +15,20 @@ if [ $TRAVIS_OS_NAME == "linux" ]; then curl https://swift.org/builds/$SWIFT_VERSION-release/ubuntu1404/$SWIFT_VERSION-RELEASE/$SWIFT_VERSION-RELEASE-ubuntu14.04.tar.gz -s | tar xz -C swift &> /dev/null fi +if [ -z "${JAVA_HOME-}" ] +then + export JAVA_HOME="$(dirname $(java -XshowSettings:properties -version 2>&1 | + grep 'java\.home' | awk '{ print $3 }'))" +fi + # check swift swift --version swift build --version +pushd ../runtime/Swift +./boot.py --test +popd + if [ $GROUP == "LEXER" ]; then mvn -q -Dgroups="org.antlr.v4.test.runtime.category.LexerTests" -Dtest=swift.* test elif [ $GROUP == "PARSER" ]; then diff --git a/appveyor.yml b/appveyor.yml index 61ef31a41..b58a381c0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,11 @@ version: '4.7.1-SNAPSHOT+AppVeyor.{build}' -os: Windows Server 2012 +cache: + - '%USERPROFILE%\.m2' + - '%USERPROFILE%\.nuget\packages -> **\project.json' +build: off build_script: - - mvn -DskipTests install -q --batch-mode + - mvn -DskipTests install --batch-mode + - msbuild runtime/CSharp/runtime/CSharp/Antlr4.vs2013.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:detailed + - msbuild ./runtime-testsuite/target/classes/CSharp/runtime/CSharp/Antlr4.vs2013.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:detailed test_script: - - mvn install -q -Dantlr-python2-python="C:\Python27\python.exe" -Dantlr-python3-python="C:\Python35\python.exe" -Dantlr-javascript-nodejs="C:\Program Files (x86)\nodejs\node.exe" --batch-mode -build: - verbosity: minimal + - mvn install -Dantlr-python2-python="C:\Python27\python.exe" -Dantlr-python3-python="C:\Python35\python.exe" -Dantlr-javascript-nodejs="C:\Program Files (x86)\nodejs\node.exe" --batch-mode diff --git a/contributors.txt b/contributors.txt index 867396142..a270f1248 100644 --- a/contributors.txt +++ b/contributors.txt @@ -161,8 +161,13 @@ YYYY/MM/DD, github id, Full name, email 2017/07/27, matthauck, Matt Hauck, matthauck@gmail.com 2017/07/27, shirou, WAKAYAMA Shirou, shirou.faw@gmail.com 2017/08/20, tiagomazzutti, Tiago Mazzutti, tiagomzt@gmail.com +2017/08/20, milanaleksic, Milan Aleksic, milanaleksic@gmail.com 2017/08/29, Eddy Reyes, eddy@mindsight.io 2017/09/09, brauliobz, Bráulio Bezerra, brauliobezerra@gmail.com 2017/09/11, sachinjain024, Sachin Jain, sachinjain024@gmail.com 2017/10/06, bramp, Andrew Brampton, brampton@gmail.com -2017/10/15, simkimsia, Sim Kim Sia, kimcity@gmail.com \ No newline at end of file +2017/10/15, simkimsia, Sim Kim Sia, kimcity@gmail.com +2017/10/27, Griffon26, Maurice van der Pot, griffon26@kfk4ever.com +2017/05/29, rlfnb, Ralf Neeb, rlfnb@rlfnb.de +2017/10/29, gendalph, Максим Прохоренко, Maxim\dotProhorenko@gm@il.com +2017/11/02, jasonmoo, Jason Mooberry, jason.mooberry@gmail.com diff --git a/doc/antlr-project-testing.md b/doc/antlr-project-testing.md index c83167b5f..335f2da2b 100644 --- a/doc/antlr-project-testing.md +++ b/doc/antlr-project-testing.md @@ -59,8 +59,7 @@ Now, make sure C# runtime is built and installed locally. ```bash cd ~/antlr/code/antlr4/runtime/CSharp/runtime/CSharp # kill previous ones manually as "xbuild /t:Clean" didn't seem to do it -rm Antlr4.Runtime/bin/net20/Release/Antlr4.Runtime.dll -rm Antlr4.Runtime/obj/net20/Release/Antlr4.Runtime.dll +find . -name '*.dll' -exec rm {} \; # build xbuild /p:Configuration=Release Antlr4.Runtime/Antlr4.Runtime.mono.csproj ``` diff --git a/doc/getting-started.md b/doc/getting-started.md index 30acdb65a..5c57119f7 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -22,15 +22,15 @@ Or just download in browser from website: [http://www.antlr.org/download.html](http://www.antlr.org/download.html) and put it somewhere rational like `/usr/local/lib`. -2. Add `antlr-4.5.3-complete.jar` to your `CLASSPATH`: +2. Add `antlr-4.7-complete.jar` to your `CLASSPATH`: ``` -$ export CLASSPATH=".:/usr/local/lib/antlr-4.5.3-complete.jar:$CLASSPATH" +$ export CLASSPATH=".:/usr/local/lib/antlr-4.7-complete.jar:$CLASSPATH" ``` It's also a good idea to put this in your `.bash_profile` or whatever your startup script is. 3. Create aliases for the ANTLR Tool, and `TestRig`. ``` -$ alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.5.3-complete.jar:$CLASSPATH" org.antlr.v4.Tool' +$ alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.7-complete.jar:$CLASSPATH" org.antlr.v4.Tool' $ alias grun='java org.antlr.v4.gui.TestRig' ``` diff --git a/doc/swift-target.md b/doc/swift-target.md index 4f4e6e7c1..d9c451311 100644 --- a/doc/swift-target.md +++ b/doc/swift-target.md @@ -19,6 +19,16 @@ except you need to specify the language target, for example: ``` $ antlr4 -Dlanguage=Swift MyGrammar.g4 ``` + +If you integrate this as a build step inside Xcode, then you should use the +"gnu" message format to have any error messages parsed by Xcode. You may +also want to use the `-o` option to put the autogenerated files in a +separate subdirectory. + +``` +antlr4 -Dlanguage=Swift -message-format gnu -o Autogen MyGrammar.g4 +``` + For a full list of antlr4 tool options, please visit the [tool documentation page](tool-options.md). diff --git a/pom.xml b/pom.xml index 5e4c72eb4..116291e75 100644 --- a/pom.xml +++ b/pom.xml @@ -130,6 +130,20 @@ test + + + maven-clean-plugin + 3.0.0 + + + + runtime/Swift/.build + runtime/Swift/Tests/Antlr4Tests/gen + + + + + diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg index 2a203e969..64d560df5 100755 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg @@ -72,7 +72,7 @@ TokenStartColumnEquals(i) ::= <%self._tokenStartCharPositionInLine == %> ImportListener(X) ::= "" -GetExpectedTokenNames() ::= "try self.getExpectedTokens().toString(self.tokenNames)" +GetExpectedTokenNames() ::= "try self.getExpectedTokens().toString(self.getVocabulary())" RuleInvocationStack() ::= "getRuleInvocationStack().description.replacingOccurrences(of: \"\\\"\", with: \"\")" diff --git a/runtime/Cpp/CMakeLists.txt b/runtime/Cpp/CMakeLists.txt index c91e38e38..3ec785aac 100644 --- a/runtime/Cpp/CMakeLists.txt +++ b/runtime/Cpp/CMakeLists.txt @@ -25,7 +25,8 @@ project(LIBANTLR4) if(CMAKE_VERSION VERSION_EQUAL "3.0.0" OR CMAKE_VERSION VERSION_GREATER "3.0.0") - CMAKE_POLICY(SET CMP0026 OLD) + CMAKE_POLICY(SET CMP0026 NEW) + CMAKE_POLICY(SET CMP0054 OLD) CMAKE_POLICY(SET CMP0045 OLD) CMAKE_POLICY(SET CMP0042 OLD) endif() diff --git a/runtime/Cpp/cmake/ExternalAntlr4Cpp.cmake b/runtime/Cpp/cmake/ExternalAntlr4Cpp.cmake index e1c28821a..a77c09307 100644 --- a/runtime/Cpp/cmake/ExternalAntlr4Cpp.cmake +++ b/runtime/Cpp/cmake/ExternalAntlr4Cpp.cmake @@ -206,11 +206,13 @@ macro(antlr4cpp_process_grammar # export generated cpp files into list foreach(generated_file ${generated_files}) list(APPEND antlr4cpp_src_files_${antlr4cpp_project_namespace} ${generated_file}) + if (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set_source_files_properties( ${generated_file} PROPERTIES COMPILE_FLAGS -Wno-overloaded-virtual ) + endif () endforeach(generated_file) message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} Generated: ${generated_files}") diff --git a/runtime/Cpp/demo/CMakeLists.txt b/runtime/Cpp/demo/CMakeLists.txt index a91c40ddc..85a730c16 100644 --- a/runtime/Cpp/demo/CMakeLists.txt +++ b/runtime/Cpp/demo/CMakeLists.txt @@ -1,6 +1,6 @@ # -*- mode:cmake -*- if(NOT UNIX) - message(FATAL "Unsupported operating system") + message(WARNING "Unsupported operating system") endif() set(antlr4-demo-GENERATED_SRC @@ -45,11 +45,17 @@ set(antlr4-demo_SRC ${antlr4-demo-GENERATED_SRC} ) +if (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + set (flags_1 "-Wno-overloaded-virtual") +else() + set (flags_1 "-MP /wd4251") +endif() + foreach( src_file ${antlr4-demo_SRC} ) set_source_files_properties( ${src_file} PROPERTIES - COMPILE_FLAGS -Wno-overloaded-virtual + COMPILE_FLAGS "${COMPILE_FLAGS} ${flags_1}" ) endforeach( src_file ${antlr4-demo_SRC} ) @@ -58,6 +64,10 @@ add_executable(antlr4-demo ) #add_precompiled_header(antlr4-demo ${PROJECT_SOURCE_DIR}/runtime/src/antlrcpp-Prefix.h) +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + target_compile_options(antlr4-demo PRIVATE "/MT$<$:d>") +endif() + add_dependencies(antlr4-demo GenerateParser) target_link_libraries(antlr4-demo antlr4_static) diff --git a/runtime/Cpp/runtime/CMakeLists.txt b/runtime/Cpp/runtime/CMakeLists.txt index dcd21b8b0..0c2d53418 100644 --- a/runtime/Cpp/runtime/CMakeLists.txt +++ b/runtime/Cpp/runtime/CMakeLists.txt @@ -44,11 +44,13 @@ elseif(APPLE) target_link_libraries(antlr4_static ${COREFOUNDATION_LIBRARY}) endif() -if (MSVC_VERSION) +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(disabled_compile_warnings "/wd4251") else() set(disabled_compile_warnings "-Wno-overloaded-virtual") -endif() +endif () + + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(disabled_compile_warnings "${disabled_compile_warnings} -Wno-dollar-in-identifier-extension -Wno-four-char-constants") elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") @@ -61,16 +63,21 @@ if (WIN32) set(extra_share_compile_flags "-DANTLR4CPP_EXPORTS") set(extra_static_compile_flags "-DANTLR4CPP_STATIC") endif(WIN32) -if (MSVC_VERSION) +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") target_compile_options(antlr4_shared PRIVATE "/MD$<$:d>") target_compile_options(antlr4_static PRIVATE "/MT$<$:d>") endif() set(static_lib_suffix "") -if (MSVC_VERSION) +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(static_lib_suffix "-static") endif() +if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + set(extra_share_compile_flags "-DANTLR4CPP_EXPORTS -MP /wd4251") + set(extra_static_compile_flags "-DANTLR4CPP_STATIC -MP") +endif() + set_target_properties(antlr4_shared PROPERTIES VERSION ${ANTLR_VERSION} SOVERSION ${ANTLR_VERSION} diff --git a/runtime/Cpp/runtime/src/antlr4-common.h b/runtime/Cpp/runtime/src/antlr4-common.h index 316256276..ec1ccc758 100644 --- a/runtime/Cpp/runtime/src/antlr4-common.h +++ b/runtime/Cpp/runtime/src/antlr4-common.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/runtime/Cpp/runtime/src/atn/ATN.cpp b/runtime/Cpp/runtime/src/atn/ATN.cpp index 98c0675a7..21924a27d 100755 --- a/runtime/Cpp/runtime/src/atn/ATN.cpp +++ b/runtime/Cpp/runtime/src/atn/ATN.cpp @@ -87,21 +87,21 @@ misc::IntervalSet ATN::nextTokens(ATNState *s, RuleContext *ctx) const { } -misc::IntervalSet& ATN::nextTokens(ATNState *s) const { - if (!s->nextTokenWithinRule.isReadOnly()) { +misc::IntervalSet const& ATN::nextTokens(ATNState *s) const { + if (!s->_nextTokenUpdated) { std::unique_lock lock { _mutex }; - if (!s->nextTokenWithinRule.isReadOnly()) { - s->nextTokenWithinRule = nextTokens(s, nullptr); - s->nextTokenWithinRule.setReadOnly(true); + if (!s->_nextTokenUpdated) { + s->_nextTokenWithinRule = nextTokens(s, nullptr); + s->_nextTokenUpdated = true; } } - return s->nextTokenWithinRule; + return s->_nextTokenWithinRule; } void ATN::addState(ATNState *state) { if (state != nullptr) { //state->atn = this; - state->stateNumber = (int)states.size(); + state->stateNumber = static_cast(states.size()); } states.push_back(state); @@ -114,7 +114,7 @@ void ATN::removeState(ATNState *state) { int ATN::defineDecisionState(DecisionState *s) { decisionToState.push_back(s); - s->decision = (int)decisionToState.size() - 1; + s->decision = static_cast(decisionToState.size() - 1); return s->decision; } @@ -154,7 +154,7 @@ misc::IntervalSet ATN::getExpectedTokens(size_t stateNumber, RuleContext *contex if (ctx->parent == nullptr) { break; } - ctx = (RuleContext *)ctx->parent; + ctx = static_cast(ctx->parent); } if (following.contains(Token::EPSILON)) { diff --git a/runtime/Cpp/runtime/src/atn/ATN.h b/runtime/Cpp/runtime/src/atn/ATN.h index 053dfdc1c..9c40cee30 100755 --- a/runtime/Cpp/runtime/src/atn/ATN.h +++ b/runtime/Cpp/runtime/src/atn/ATN.h @@ -70,7 +70,7 @@ namespace atn { /// staying in same rule. is in set if we reach end of /// rule. /// - virtual misc::IntervalSet& nextTokens(ATNState *s) const; + virtual misc::IntervalSet const& nextTokens(ATNState *s) const; virtual void addState(ATNState *state); diff --git a/runtime/Cpp/runtime/src/atn/ATNState.h b/runtime/Cpp/runtime/src/atn/ATNState.h index 96e8fedb7..6c73d9435 100755 --- a/runtime/Cpp/runtime/src/atn/ATNState.h +++ b/runtime/Cpp/runtime/src/atn/ATNState.h @@ -70,12 +70,17 @@ namespace atn { /// /// /// + class ANTLR4CPP_PUBLIC ATN; + class ANTLR4CPP_PUBLIC ATNState { public: ATNState(); + ATNState(ATNState const&) = delete; virtual ~ATNState(); + ATNState& operator=(ATNState const&) = delete; + static const size_t INITIAL_NUM_TRANSITIONS = 4; static const size_t INVALID_STATE_NUMBER = static_cast(-1); // std::numeric_limits::max(); @@ -102,9 +107,6 @@ namespace atn { bool epsilonOnlyTransitions = false; public: - /// Used to cache lookahead during parsing, not used during construction. - misc::IntervalSet nextTokenWithinRule; - virtual size_t hashCode(); bool operator == (const ATNState &other); @@ -117,6 +119,14 @@ namespace atn { virtual void addTransition(size_t index, Transition *e); virtual Transition* removeTransition(size_t index); virtual size_t getStateType() = 0; + + private: + /// Used to cache lookahead during parsing, not used during construction. + + misc::IntervalSet _nextTokenWithinRule; + std::atomic _nextTokenUpdated { false }; + + friend class ATN; }; } // namespace atn diff --git a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp index 906581eb7..25ac26028 100755 --- a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp +++ b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp @@ -181,23 +181,21 @@ size_t LexerATNSimulator::execATN(CharStream *input, dfa::DFAState *ds0) { } dfa::DFAState *LexerATNSimulator::getExistingTargetState(dfa::DFAState *s, size_t t) { - if (s->edges.empty()|| /*t < MIN_DFA_EDGE ||*/ t > MAX_DFA_EDGE) { // MIN_DFA_EDGE is 0, hence code gives a warning, if left in. - return nullptr; - } - + dfa::DFAState* retval = nullptr; _edgeLock.readLock(); - auto iterator = s->edges.find(t - MIN_DFA_EDGE); + if (t <= MAX_DFA_EDGE) { + auto iterator = s->edges.find(t - MIN_DFA_EDGE); #if DEBUG_ATN == 1 - if (iterator != s->edges.end()) { - std::cout << std::string("reuse state ") << s->stateNumber << std::string(" edge to ") << iterator->second->stateNumber << std::endl; - } + if (iterator != s->edges.end()) { + std::cout << std::string("reuse state ") << s->stateNumber << std::string(" edge to ") << iterator->second->stateNumber << std::endl; + } #endif + + if (iterator != s->edges.end()) + retval = iterator->second; + } _edgeLock.readUnlock(); - - if (iterator == s->edges.end()) - return nullptr; - - return iterator->second; + return retval; } dfa::DFAState *LexerATNSimulator::computeTargetState(CharStream *input, dfa::DFAState *s, size_t t) { diff --git a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.h b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.h index 0941ae2f2..fa113f849 100755 --- a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.h +++ b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.h @@ -86,6 +86,7 @@ namespace atn { LexerATNSimulator(const ATN &atn, std::vector &decisionToDFA, PredictionContextCache &sharedContextCache); LexerATNSimulator(Lexer *recog, const ATN &atn, std::vector &decisionToDFA, PredictionContextCache &sharedContextCache); + virtual ~LexerATNSimulator () {} virtual void copyState(LexerATNSimulator *simulator); virtual size_t match(CharStream *input, size_t mode); diff --git a/runtime/Cpp/runtime/src/atn/LexerActionExecutor.cpp b/runtime/Cpp/runtime/src/atn/LexerActionExecutor.cpp index c9c32f074..1ae510f75 100755 --- a/runtime/Cpp/runtime/src/atn/LexerActionExecutor.cpp +++ b/runtime/Cpp/runtime/src/atn/LexerActionExecutor.cpp @@ -101,7 +101,7 @@ size_t LexerActionExecutor::generateHashCode() const { for (auto lexerAction : _lexerActions) { hash = MurmurHash::update(hash, lexerAction); } - MurmurHash::finish(hash, _lexerActions.size()); + hash = MurmurHash::finish(hash, _lexerActions.size()); return hash; } diff --git a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp index 5e82bbaff..aaa9e820c 100755 --- a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp +++ b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp @@ -257,14 +257,12 @@ size_t ParserATNSimulator::execATN(dfa::DFA &dfa, dfa::DFAState *s0, TokenStream } dfa::DFAState *ParserATNSimulator::getExistingTargetState(dfa::DFAState *previousD, size_t t) { + dfa::DFAState* retval; _edgeLock.readLock(); auto iterator = previousD->edges.find(t); + retval = (iterator == previousD->edges.end()) ? nullptr : iterator->second; _edgeLock.readUnlock(); - if (iterator == previousD->edges.end()) { - return nullptr; - } - - return iterator->second; + return retval; } dfa::DFAState *ParserATNSimulator::computeTargetState(dfa::DFA &dfa, dfa::DFAState *previousD, size_t t) { diff --git a/runtime/Cpp/runtime/src/misc/Interval.cpp b/runtime/Cpp/runtime/src/misc/Interval.cpp index 97486bf3f..bb521eb9d 100755 --- a/runtime/Cpp/runtime/src/misc/Interval.cpp +++ b/runtime/Cpp/runtime/src/misc/Interval.cpp @@ -7,8 +7,6 @@ using namespace antlr4::misc; -Interval::~Interval() = default; - size_t antlr4::misc::numericToSymbol(ssize_t v) { return static_cast(v); } diff --git a/runtime/Cpp/runtime/src/misc/Interval.h b/runtime/Cpp/runtime/src/misc/Interval.h index 19a17cac9..0198ee5ae 100755 --- a/runtime/Cpp/runtime/src/misc/Interval.h +++ b/runtime/Cpp/runtime/src/misc/Interval.h @@ -28,57 +28,54 @@ namespace misc { Interval(); explicit Interval(size_t a_, size_t b_); // For unsigned -> signed mappings. Interval(ssize_t a_, ssize_t b_); - Interval(Interval const&) = default; - virtual ~Interval(); - Interval& operator=(Interval const&) = default; /// return number of elements between a and b inclusively. x..x is length 1. /// if b < a, then length is 0. 9..10 has length 2. - virtual size_t length() const; + size_t length() const; bool operator == (const Interval &other) const; - virtual size_t hashCode() const; + size_t hashCode() const; /// /// Does this start completely before other? Disjoint - virtual bool startsBeforeDisjoint(const Interval &other) const; + bool startsBeforeDisjoint(const Interval &other) const; /// /// Does this start at or before other? Nondisjoint - virtual bool startsBeforeNonDisjoint(const Interval &other) const; + bool startsBeforeNonDisjoint(const Interval &other) const; /// /// Does this.a start after other.b? May or may not be disjoint - virtual bool startsAfter(const Interval &other) const; + bool startsAfter(const Interval &other) const; /// /// Does this start completely after other? Disjoint - virtual bool startsAfterDisjoint(const Interval &other) const; + bool startsAfterDisjoint(const Interval &other) const; /// /// Does this start after other? NonDisjoint - virtual bool startsAfterNonDisjoint(const Interval &other) const; + bool startsAfterNonDisjoint(const Interval &other) const; /// /// Are both ranges disjoint? I.e., no overlap? - virtual bool disjoint(const Interval &other) const; + bool disjoint(const Interval &other) const; /// /// Are two intervals adjacent such as 0..41 and 42..42? - virtual bool adjacent(const Interval &other) const; + bool adjacent(const Interval &other) const; - virtual bool properlyContains(const Interval &other) const; + bool properlyContains(const Interval &other) const; /// /// Return the interval computed from combining this and other - virtual Interval Union(const Interval &other) const; + Interval Union(const Interval &other) const; /// /// Return the interval in common between this and o - virtual Interval intersection(const Interval &other) const; + Interval intersection(const Interval &other) const; - virtual std::string toString() const; + std::string toString() const; private: }; diff --git a/runtime/Cpp/runtime/src/misc/IntervalSet.cpp b/runtime/Cpp/runtime/src/misc/IntervalSet.cpp index ab4d240cc..031b9ba5b 100755 --- a/runtime/Cpp/runtime/src/misc/IntervalSet.cpp +++ b/runtime/Cpp/runtime/src/misc/IntervalSet.cpp @@ -13,52 +13,32 @@ using namespace antlr4; using namespace antlr4::misc; -IntervalSet const IntervalSet::COMPLETE_CHAR_SET = []() { - IntervalSet complete = IntervalSet::of(Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE); - complete.setReadOnly(true); - return complete; -}(); +IntervalSet const IntervalSet::COMPLETE_CHAR_SET = + IntervalSet::of(Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE); -IntervalSet const IntervalSet::EMPTY_SET = []() { - IntervalSet empty; - empty.setReadOnly(true); - return empty; -}(); +IntervalSet const IntervalSet::EMPTY_SET; -IntervalSet::IntervalSet() { - InitializeInstanceFields(); -} - -IntervalSet::IntervalSet(const std::vector &intervals) : IntervalSet() { - _intervals = intervals; +IntervalSet::IntervalSet() : _intervals() { } IntervalSet::IntervalSet(const IntervalSet &set) : IntervalSet() { - addAll(set); + _intervals = set._intervals; } -IntervalSet::IntervalSet(int n, ...) : IntervalSet() { - va_list vlist; - va_start(vlist, n); - - for (int i = 0; i < n; i++) { - add(va_arg(vlist, int)); - } +IntervalSet::IntervalSet(IntervalSet&& set) : IntervalSet(std::move(set._intervals)) { } -IntervalSet::~IntervalSet() -{ +IntervalSet::IntervalSet(std::vector&& intervals) : _intervals(std::move(intervals)) { } -IntervalSet& IntervalSet::operator=(const IntervalSet& other) -{ - if (_readonly) { - throw IllegalStateException("can't alter read only IntervalSet"); - } +IntervalSet& IntervalSet::operator=(const IntervalSet& other) { + _intervals = other._intervals; + return *this; +} - _intervals.clear(); - - return addAll(other); +IntervalSet& IntervalSet::operator=(IntervalSet&& other) { + _intervals = move(other._intervals); + return *this; } IntervalSet IntervalSet::of(ssize_t a) { @@ -70,16 +50,10 @@ IntervalSet IntervalSet::of(ssize_t a, ssize_t b) { } void IntervalSet::clear() { - if (_readonly) { - throw IllegalStateException("can't alter read only IntervalSet"); - } _intervals.clear(); } void IntervalSet::add(ssize_t el) { - if (_readonly) { - throw IllegalStateException("can't alter read only IntervalSet"); - } add(el, el); } @@ -88,10 +62,6 @@ void IntervalSet::add(ssize_t a, ssize_t b) { } void IntervalSet::add(const Interval &addition) { - if (_readonly) { - throw IllegalStateException("can't alter read only IntervalSet"); - } - if (addition.b < addition.a) { return; } @@ -150,7 +120,7 @@ IntervalSet IntervalSet::Or(const std::vector &sets) { IntervalSet& IntervalSet::addAll(const IntervalSet &set) { // walk set and add each interval - for (auto &interval : set._intervals) { + for (auto const& interval : set._intervals) { add(interval); } return *this; @@ -339,7 +309,7 @@ ssize_t IntervalSet::getMinElement() const { return _intervals[0].a; } -std::vector IntervalSet::getIntervals() const { +std::vector const& IntervalSet::getIntervals() const { return _intervals; } @@ -516,10 +486,6 @@ void IntervalSet::remove(size_t el) { } void IntervalSet::remove(ssize_t el) { - if (_readonly) { - throw IllegalStateException("can't alter read only IntervalSet"); - } - for (size_t i = 0; i < _intervals.size(); ++i) { Interval &interval = _intervals[i]; ssize_t a = interval.a; @@ -553,17 +519,3 @@ void IntervalSet::remove(ssize_t el) { } } } - -bool IntervalSet::isReadOnly() const { - return _readonly; -} - -void IntervalSet::setReadOnly(bool readonly) { - if (_readonly && !readonly) - throw IllegalStateException("Can't alter readonly IntervalSet"); - _readonly = readonly; -} - -void IntervalSet::InitializeInstanceFields() { - _readonly = false; -} diff --git a/runtime/Cpp/runtime/src/misc/IntervalSet.h b/runtime/Cpp/runtime/src/misc/IntervalSet.h index c9d38756d..af09e3465 100755 --- a/runtime/Cpp/runtime/src/misc/IntervalSet.h +++ b/runtime/Cpp/runtime/src/misc/IntervalSet.h @@ -6,7 +6,7 @@ #pragma once #include "misc/Interval.h" -#include +#include "Exceptions.h" namespace antlr4 { namespace misc { @@ -28,20 +28,27 @@ namespace misc { static IntervalSet const COMPLETE_CHAR_SET; static IntervalSet const EMPTY_SET; - protected: + private: /// The list of sorted, disjoint intervals. std::vector _intervals; - std::atomic _readonly; + + explicit IntervalSet(std::vector&& intervals); public: IntervalSet(); - IntervalSet(const std::vector &intervals); - IntervalSet(const IntervalSet &set); - IntervalSet(int numArgs, ...); + IntervalSet(IntervalSet const& set); + IntervalSet(IntervalSet&& set); - virtual ~IntervalSet(); + template + IntervalSet(int, T1 t1, T_NEXT&&... next) : IntervalSet() + { + // The first int argument is an ignored count for compatibility + // with the previous varargs based interface. + addItems(t1, std::forward(next)...); + } - IntervalSet& operator=(const IntervalSet &set); + IntervalSet& operator=(IntervalSet const& set); + IntervalSet& operator=(IntervalSet&& set); /// Create a set with a single element, el. static IntervalSet of(ssize_t a); @@ -49,11 +56,11 @@ namespace misc { /// Create a set with all ints within range [a..b] (inclusive) static IntervalSet of(ssize_t a, ssize_t b); - virtual void clear(); + void clear(); /// Add a single element to the set. An isolated element is stored /// as a range el..el. - virtual void add(ssize_t el); + void add(ssize_t el); /// Add interval; i.e., add all integers from a to b to set. /// If b &sets); // Copy on write so we can cache a..a intervals and sets of that. - virtual void add(const Interval &addition); - virtual IntervalSet& addAll(const IntervalSet &set); + void add(const Interval &addition); + IntervalSet& addAll(const IntervalSet &set); - virtual IntervalSet complement(ssize_t minElement, ssize_t maxElement) const; + template + void addItems(T1 t1, T_NEXT&&... next) + { + add(t1); + addItems(std::forward(next)...); + } + + IntervalSet complement(ssize_t minElement, ssize_t maxElement) const; /// Given the set of possible values (rather than, say UNICODE or MAXINT), /// return a new set containing all elements in vocabulary, but not in /// this. The computation is (vocabulary - this). /// /// 'this' is assumed to be either a subset or equal to vocabulary. - virtual IntervalSet complement(const IntervalSet &vocabulary) const; + IntervalSet complement(const IntervalSet &vocabulary) const; /// Compute this-other via this&~other. /// Return a new set containing all elements in this but not in other. /// other is assumed to be a subset of this; /// anything that is in other but not in this will be ignored. - virtual IntervalSet subtract(const IntervalSet &other) const; + IntervalSet subtract(const IntervalSet &other) const; /** * Compute the set difference between two interval sets. The specific @@ -93,23 +106,23 @@ namespace misc { */ static IntervalSet subtract(const IntervalSet &left, const IntervalSet &right); - virtual IntervalSet Or(const IntervalSet &a) const; + IntervalSet Or(const IntervalSet &a) const; /// Return a new set with the intersection of this set with other. Because /// the intervals are sorted, we can use an iterator for each list and /// just walk them together. This is roughly O(min(n,m)) for interval /// list lengths n and m. - virtual IntervalSet And(const IntervalSet &other) const; + IntervalSet And(const IntervalSet &other) const; /// Is el in any range of this set? - virtual bool contains(size_t el) const; // For mapping of e.g. Token::EOF to -1 etc. - virtual bool contains(ssize_t el) const; + bool contains(size_t el) const; // For mapping of e.g. Token::EOF to -1 etc. + bool contains(ssize_t el) const; /// return true if this set has no members - virtual bool isEmpty() const; + bool isEmpty() const; /// If this set is a single integer, return it otherwise Token.INVALID_TYPE. - virtual ssize_t getSingleElement() const; + ssize_t getSingleElement() const; /** * Returns the maximum value contained in the set. @@ -117,7 +130,7 @@ namespace misc { * @return the maximum value contained in the set. If the set is empty, this * method returns {@link Token#INVALID_TYPE}. */ - virtual ssize_t getMaxElement() const; + ssize_t getMaxElement() const; /** * Returns the minimum value contained in the set. @@ -125,50 +138,48 @@ namespace misc { * @return the minimum value contained in the set. If the set is empty, this * method returns {@link Token#INVALID_TYPE}. */ - virtual ssize_t getMinElement() const; + ssize_t getMinElement() const; /// /// Return a list of Interval objects. - virtual std::vector getIntervals() const; + std::vector const& getIntervals() const; - virtual size_t hashCode() const; + size_t hashCode() const; /// Are two IntervalSets equal? Because all intervals are sorted /// and disjoint, equals is a simple linear walk over both lists /// to make sure they are the same. bool operator == (const IntervalSet &other) const; - virtual std::string toString() const; - virtual std::string toString(bool elemAreChar) const; + std::string toString() const; + std::string toString(bool elemAreChar) const; /** * @deprecated Use {@link #toString(Vocabulary)} instead. */ - virtual std::string toString(const std::vector &tokenNames) const; - virtual std::string toString(const dfa::Vocabulary &vocabulary) const; + std::string toString(const std::vector &tokenNames) const; + std::string toString(const dfa::Vocabulary &vocabulary) const; protected: /** * @deprecated Use {@link #elementName(Vocabulary, int)} instead. */ - virtual std::string elementName(const std::vector &tokenNames, ssize_t a) const; - virtual std::string elementName(const dfa::Vocabulary &vocabulary, ssize_t a) const; + std::string elementName(const std::vector &tokenNames, ssize_t a) const; + std::string elementName(const dfa::Vocabulary &vocabulary, ssize_t a) const; public: - virtual size_t size() const; - virtual std::vector toList() const; - virtual std::set toSet() const; + size_t size() const; + std::vector toList() const; + std::set toSet() const; /// Get the ith element of ordered set. Used only by RandomPhrase so /// don't bother to implement if you're not doing that for a new /// ANTLR code gen target. - virtual ssize_t get(size_t i) const; - virtual void remove(size_t el); // For mapping of e.g. Token::EOF to -1 etc. - virtual void remove(ssize_t el); - virtual bool isReadOnly() const; - virtual void setReadOnly(bool readonly); + ssize_t get(size_t i) const; + void remove(size_t el); // For mapping of e.g. Token::EOF to -1 etc. + void remove(ssize_t el); private: - void InitializeInstanceFields(); + void addItems() { /* No-op */ } }; } // namespace atn diff --git a/runtime/Go/antlr/utils.go b/runtime/Go/antlr/utils.go index 860639693..b9d328f10 100644 --- a/runtime/Go/antlr/utils.go +++ b/runtime/Go/antlr/utils.go @@ -353,12 +353,11 @@ func PrintArrayJavaStyle(sa []string) string { return buffer.String() } - // murmur hash const ( - c1_32 = 0xCC9E2D51 - c2_32 = 0x1B873593 - n1_32 = 0xE6546B64 + c1_32 uint = 0xCC9E2D51 + c2_32 uint = 0x1B873593 + n1_32 uint = 0xE6546B64 ) func murmurInit(seed int) int { @@ -366,23 +365,25 @@ func murmurInit(seed int) int { } func murmurUpdate(h1 int, k1 int) int { - k1 *= c1_32 - k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15) - k1 *= c2_32 + var k1u uint + k1u = uint(k1) * c1_32 + k1u = (k1u << 15) | (k1u >> 17) // rotl32(k1u, 15) + k1u *= c2_32 - h1 ^= k1 - h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13) - h1 = h1*5 + 0xe6546b64 - return h1 + var h1u = uint(h1) ^ k1u + h1u = (h1u << 13) | (h1u >> 19) // rotl32(h1u, 13) + h1u = h1u*5 + 0xe6546b64 + return int(h1u) } func murmurFinish(h1 int, numberOfWords int) int { - h1 ^= (numberOfWords * 4) - h1 ^= h1 >> 16 - h1 *= 0x85ebca6b - h1 ^= h1 >> 13 - h1 *= 0xc2b2ae35 - h1 ^= h1 >> 16 + var h1u uint = uint(h1) + h1u ^= uint(numberOfWords * 4) + h1u ^= h1u >> 16 + h1u *= uint(0x85ebca6b) + h1u ^= h1u >> 13 + h1u *= 0xc2b2ae35 + h1u ^= h1u >> 16 - return h1 + return int(h1u) } diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java index d415cdfb2..76524ebd8 100755 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java @@ -270,7 +270,7 @@ public class ParserATNSimulator extends ATNSimulator { public static final boolean retry_debug = false; /** Just in case this optimization is bad, add an ENV variable to turn it off */ - public static final boolean TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT = Boolean.parseBoolean(System.getenv("TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT")); + public static final boolean TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT = Boolean.parseBoolean(getSafeEnv("TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT")); protected final Parser parser; @@ -2181,4 +2181,14 @@ public class ParserATNSimulator extends ATNSimulator { public Parser getParser() { return parser; } + + public static String getSafeEnv(String envName) { + try { + return System.getenv(envName); + } + catch(SecurityException e) { + // use the default value + } + return null; + } } diff --git a/runtime/Swift/Sources/Antlr4/ANTLRErrorListener.swift b/runtime/Swift/Sources/Antlr4/ANTLRErrorListener.swift index 56d1987f3..486ae0f2c 100644 --- a/runtime/Swift/Sources/Antlr4/ANTLRErrorListener.swift +++ b/runtime/Swift/Sources/Antlr4/ANTLRErrorListener.swift @@ -93,7 +93,7 @@ public protocol ANTLRErrorListener: class { _ stopIndex: Int, _ exact: Bool, _ ambigAlts: BitSet, - _ configs: ATNConfigSet) throws + _ configs: ATNConfigSet) /// /// This method is called when an SLL conflict occurs and the parser is about @@ -123,7 +123,7 @@ public protocol ANTLRErrorListener: class { _ startIndex: Int, _ stopIndex: Int, _ conflictingAlts: BitSet?, - _ configs: ATNConfigSet) throws + _ configs: ATNConfigSet) /// /// This method is called by the parser when a full-context prediction has a @@ -168,5 +168,5 @@ public protocol ANTLRErrorListener: class { _ startIndex: Int, _ stopIndex: Int, _ prediction: Int, - _ configs: ATNConfigSet) throws + _ configs: ATNConfigSet) } diff --git a/runtime/Swift/Sources/Antlr4/ANTLRErrorStrategy.swift b/runtime/Swift/Sources/Antlr4/ANTLRErrorStrategy.swift index 325418b5e..7ca228ff8 100644 --- a/runtime/Swift/Sources/Antlr4/ANTLRErrorStrategy.swift +++ b/runtime/Swift/Sources/Antlr4/ANTLRErrorStrategy.swift @@ -63,7 +63,7 @@ public protocol ANTLRErrorStrategy { /// - throws: _RecognitionException_ if the error strategy could not recover from /// the recognition exception /// - func recover(_ recognizer: Parser, _ e: AnyObject) throws + func recover(_ recognizer: Parser, _ e: RecognitionException) throws /// /// This method provides the error handler with an opportunity to handle @@ -115,5 +115,5 @@ public protocol ANTLRErrorStrategy { /// - parameter recognizer: the parser instance /// - parameter e: the recognition exception to report /// - func reportError(_ recognizer: Parser, _ e: AnyObject) + func reportError(_ recognizer: Parser, _ e: RecognitionException) } diff --git a/runtime/Swift/Sources/Antlr4/BailErrorStrategy.swift b/runtime/Swift/Sources/Antlr4/BailErrorStrategy.swift index 1753fa751..d1e81140c 100644 --- a/runtime/Swift/Sources/Antlr4/BailErrorStrategy.swift +++ b/runtime/Swift/Sources/Antlr4/BailErrorStrategy.swift @@ -40,14 +40,14 @@ public class BailErrorStrategy: DefaultErrorStrategy { /// rule function catches. Use _Exception#getCause()_ to get the /// original _org.antlr.v4.runtime.RecognitionException_. /// - override public func recover(_ recognizer: Parser, _ e: AnyObject) throws { - var context: ParserRuleContext? = recognizer.getContext() - while let contextWrap = context{ + override public func recover(_ recognizer: Parser, _ e: RecognitionException) throws { + var context = recognizer.getContext() + while let contextWrap = context { contextWrap.exception = e context = (contextWrap.getParent() as? ParserRuleContext) } - throw ANTLRException.recognition(e: e) + throw ANTLRException.recognition(e: e) } /// @@ -56,15 +56,14 @@ public class BailErrorStrategy: DefaultErrorStrategy { /// override public func recoverInline(_ recognizer: Parser) throws -> Token { - let e: InputMismatchException = try InputMismatchException(recognizer) - var context: ParserRuleContext? = recognizer.getContext() + let e = InputMismatchException(recognizer) + var context = recognizer.getContext() while let contextWrap = context { contextWrap.exception = e context = (contextWrap.getParent() as? ParserRuleContext) } - throw ANTLRException.recognition(e: e) - + throw ANTLRException.recognition(e: e) } /// diff --git a/runtime/Swift/Sources/Antlr4/BaseErrorListener.swift b/runtime/Swift/Sources/Antlr4/BaseErrorListener.swift index 9a9805b96..8db84a00b 100644 --- a/runtime/Swift/Sources/Antlr4/BaseErrorListener.swift +++ b/runtime/Swift/Sources/Antlr4/BaseErrorListener.swift @@ -33,7 +33,7 @@ open class BaseErrorListener: ANTLRErrorListener { _ stopIndex: Int, _ exact: Bool, _ ambigAlts: BitSet, - _ configs: ATNConfigSet) throws { + _ configs: ATNConfigSet) { } @@ -42,7 +42,7 @@ open class BaseErrorListener: ANTLRErrorListener { _ startIndex: Int, _ stopIndex: Int, _ conflictingAlts: BitSet?, - _ configs: ATNConfigSet) throws { + _ configs: ATNConfigSet) { } @@ -51,6 +51,6 @@ open class BaseErrorListener: ANTLRErrorListener { _ startIndex: Int, _ stopIndex: Int, _ prediction: Int, - _ configs: ATNConfigSet) throws { + _ configs: ATNConfigSet) { } } diff --git a/runtime/Swift/Sources/Antlr4/BufferedTokenStream.swift b/runtime/Swift/Sources/Antlr4/BufferedTokenStream.swift index cbf40b3cc..2805f8855 100644 --- a/runtime/Swift/Sources/Antlr4/BufferedTokenStream.swift +++ b/runtime/Swift/Sources/Antlr4/BufferedTokenStream.swift @@ -176,7 +176,7 @@ public class BufferedTokenStream: TokenStream { let index = tokens.count - 1 throw ANTLRError.indexOutOfBounds(msg: "token index \(i) out of range 0..\(index)") } - return tokens[i] //tokens[i] + return tokens[i] } /// @@ -202,7 +202,6 @@ public class BufferedTokenStream: TokenStream { return subset } - //TODO: LT(i)!.getType(); public func LA(_ i: Int) throws -> Int { return try LT(i)!.getType() } @@ -273,11 +272,11 @@ public class BufferedTokenStream: TokenStream { fetchedEOF = false } - public func getTokens() -> Array { + public func getTokens() -> [Token] { return tokens } - public func getTokens(_ start: Int, _ stop: Int) throws -> Array? { + public func getTokens(_ start: Int, _ stop: Int) throws -> [Token]? { return try getTokens(start, stop, nil) } @@ -286,40 +285,36 @@ public class BufferedTokenStream: TokenStream { /// the token type BitSet. Return null if no tokens were found. This /// method looks at both on and off channel tokens. /// - public func getTokens(_ start: Int, _ stop: Int, _ types: Set?) throws -> Array? { + public func getTokens(_ start: Int, _ stop: Int, _ types: Set?) throws -> [Token]? { try lazyInit() - if start < 0 || stop >= tokens.count || - stop < 0 || start >= tokens.count { - throw ANTLRError.indexOutOfBounds(msg: "start \(start) or stop \(stop) not in 0..\(tokens.count - 1)") + if start < 0 || start >= tokens.count || + stop < 0 || stop >= tokens.count { + throw ANTLRError.indexOutOfBounds(msg: "start \(start) or stop \(stop) not in 0...\(tokens.count - 1)") } if start > stop { return nil } - - var filteredTokens: Array = Array() + var filteredTokens = [Token]() for i in start...stop { - let t: Token = tokens[i] - if let types = types , !types.contains(t.getType()) { - }else { + let t = tokens[i] + if let types = types, !types.contains(t.getType()) { + } + else { filteredTokens.append(t) } - } if filteredTokens.isEmpty { return nil - //filteredTokens = nil; } return filteredTokens } - public func getTokens(_ start: Int, _ stop: Int, _ ttype: Int) throws -> Array? { - //TODO Set initialCapacity - var s: Set = Set() + public func getTokens(_ start: Int, _ stop: Int, _ ttype: Int) throws -> [Token]? { + var s = Set() s.insert(ttype) - //s.append(ttype); - return try getTokens(start, stop, s) + return try getTokens(start, stop, s) } /// @@ -464,7 +459,7 @@ public class BufferedTokenStream: TokenStream { } } } - if hidden.count == 0 { + if hidden.isEmpty { return nil } return hidden diff --git a/runtime/Swift/Sources/Antlr4/CharStream.swift b/runtime/Swift/Sources/Antlr4/CharStream.swift index 38e87e109..f21aabe3d 100644 --- a/runtime/Swift/Sources/Antlr4/CharStream.swift +++ b/runtime/Swift/Sources/Antlr4/CharStream.swift @@ -25,5 +25,5 @@ public protocol CharStream: IntStream { /// - throws: _ANTLRError.unsupportedOperation_ if the stream does not support /// getting the text of the specified interval /// - func getText(_ interval: Interval) -> String + func getText(_ interval: Interval) throws -> String } diff --git a/runtime/Swift/Sources/Antlr4/CommonToken.swift b/runtime/Swift/Sources/Antlr4/CommonToken.swift index 0fec7679d..cef3973c0 100644 --- a/runtime/Swift/Sources/Antlr4/CommonToken.swift +++ b/runtime/Swift/Sources/Antlr4/CommonToken.swift @@ -7,12 +7,6 @@ public class CommonToken: WritableToken { - /// - /// An empty _org.antlr.v4.runtime.misc.Pair_ which is used as the default value of - /// _#source_ for tokens that do not have a source. - /// - internal static let EMPTY_SOURCE: (TokenSource?, CharStream?) = (nil, nil) - /// /// This is the backing field for _#getType_ and _#setType_. /// @@ -21,20 +15,20 @@ public class CommonToken: WritableToken { /// /// This is the backing field for _#getLine_ and _#setLine_. /// - internal var line: Int = 0 + internal var line = 0 /// /// This is the backing field for _#getCharPositionInLine_ and /// _#setCharPositionInLine_. /// - internal var charPositionInLine: Int = -1 + internal var charPositionInLine = -1 // set to invalid position /// /// This is the backing field for _#getChannel_ and /// _#setChannel_. /// - internal var channel: Int = DEFAULT_CHANNEL + internal var channel = DEFAULT_CHANNEL /// /// This is the backing field for _#getTokenSource_ and @@ -47,7 +41,7 @@ public class CommonToken: WritableToken { /// _org.antlr.v4.runtime.misc.Pair_ containing these values. /// - internal var source: (TokenSource?, CharStream?) + internal let source: TokenSourceAndStream /// /// This is the backing field for _#getText_ when the token text is @@ -61,19 +55,19 @@ public class CommonToken: WritableToken { /// This is the backing field for _#getTokenIndex_ and /// _#setTokenIndex_. /// - internal var index: Int = -1 + internal var index = -1 /// /// This is the backing field for _#getStartIndex_ and /// _#setStartIndex_. /// - internal var start: Int = 0 + internal var start = 0 /// /// This is the backing field for _#getStopIndex_ and /// _#setStopIndex_. /// - internal var stop: Int = 0 + internal var stop = 0 /// /// Constructs a new _org.antlr.v4.runtime.CommonToken_ with the specified token type. @@ -85,16 +79,16 @@ public class CommonToken: WritableToken { public init(_ type: Int) { self.type = type - self.source = CommonToken.EMPTY_SOURCE + self.source = TokenSourceAndStream.EMPTY } - public init(_ source: (TokenSource?, CharStream?), _ type: Int, _ channel: Int, _ start: Int, _ stop: Int) { + public init(_ source: TokenSourceAndStream, _ type: Int, _ channel: Int, _ start: Int, _ stop: Int) { self.source = source self.type = type self.channel = channel self.start = start self.stop = stop - if let tsource = source.0 { + if let tsource = source.tokenSource { self.line = tsource.getLine() self.charPositionInLine = tsource.getCharPositionInLine() } @@ -111,20 +105,12 @@ public class CommonToken: WritableToken { self.type = type self.channel = CommonToken.DEFAULT_CHANNEL self.text = text - self.source = CommonToken.EMPTY_SOURCE + self.source = TokenSourceAndStream.EMPTY } /// /// Constructs a new _org.antlr.v4.runtime.CommonToken_ as a copy of another _org.antlr.v4.runtime.Token_. - /// - /// - /// If `oldToken` is also a _org.antlr.v4.runtime.CommonToken_ instance, the newly - /// constructed token will share a reference to the _#text_ field and - /// the _org.antlr.v4.runtime.misc.Pair_ stored in _#source_. Otherwise, _#text_ will - /// be assigned the result of calling _#getText_, and _#source_ - /// will be constructed from the result of _org.antlr.v4.runtime.Token#getTokenSource_ and - /// _org.antlr.v4.runtime.Token#getInputStream_. - /// + /// /// - parameter oldToken: The token to copy. /// public init(_ oldToken: Token) { @@ -135,14 +121,8 @@ public class CommonToken: WritableToken { channel = oldToken.getChannel() start = oldToken.getStartIndex() stop = oldToken.getStopIndex() - - if oldToken is CommonToken { - text = (oldToken as! CommonToken).text - source = (oldToken as! CommonToken).source - } else { - text = oldToken.getText() - source = (oldToken.getTokenSource(), oldToken.getInputStream()) - } + text = oldToken.getText() + source = oldToken.getTokenSourceAndStream() } @@ -157,14 +137,19 @@ public class CommonToken: WritableToken { public func getText() -> String? { - if text != nil { - return text! + if let text = text { + return text } if let input = getInputStream() { - let n: Int = input.size() + let n = input.size() if start < n && stop < n { - return input.getText(Interval.of(start, stop)) + do { + return try input.getText(Interval.of(start, stop)) + } + catch { + return nil + } } else { return "" } @@ -247,12 +232,16 @@ public class CommonToken: WritableToken { public func getTokenSource() -> TokenSource? { - return source.0 + return source.tokenSource } public func getInputStream() -> CharStream? { - return source.1 + return source.stream + } + + public func getTokenSourceAndStream() -> TokenSourceAndStream { + return source } public var description: String { @@ -260,10 +249,8 @@ public class CommonToken: WritableToken { } public func toString(_ r: Recognizer?) -> String { - var channelStr: String = "" - if channel > 0 { - channelStr = ",channel=\(channel)" - } + let channelStr = (channel > 0 ? ",channel=\(channel)" : "") + var txt: String if let tokenText = getText() { txt = tokenText.replacingOccurrences(of: "\n", with: "\\n") @@ -272,12 +259,16 @@ public class CommonToken: WritableToken { } else { txt = "" } - var typeString = "\(type)" + let typeString: String if let r = r { - typeString = r.getVocabulary().getDisplayName(type); + typeString = r.getVocabulary().getDisplayName(type) + } + else { + typeString = "\(type)" } return "[@\(getTokenIndex()),\(start):\(stop)='\(txt)',<\(typeString)>\(channelStr),\(line):\(getCharPositionInLine())]" } + public var visited: Bool { get { return _visited diff --git a/runtime/Swift/Sources/Antlr4/CommonTokenFactory.swift b/runtime/Swift/Sources/Antlr4/CommonTokenFactory.swift index 2f39b413f..d7922802f 100644 --- a/runtime/Swift/Sources/Antlr4/CommonTokenFactory.swift +++ b/runtime/Swift/Sources/Antlr4/CommonTokenFactory.swift @@ -65,18 +65,17 @@ public class CommonTokenFactory: TokenFactory { } - public func create(_ source: (TokenSource?, CharStream?), _ type: Int, _ text: String?, + public func create(_ source: TokenSourceAndStream, _ type: Int, _ text: String?, _ channel: Int, _ start: Int, _ stop: Int, _ line: Int, _ charPositionInLine: Int) -> Token { - let t: CommonToken = CommonToken(source, type, channel, start, stop) + let t = CommonToken(source, type, channel, start, stop) t.setLine(line) t.setCharPositionInLine(charPositionInLine) - if text != nil { - t.setText(text!) - } else { - if let cStream = source.1 , copyText { - t.setText(cStream.getText(Interval.of(start, stop))) - } + if let text = text { + t.setText(text) + } + else if let cStream = source.stream, copyText { + t.setText(try! cStream.getText(Interval.of(start, stop))) } return t diff --git a/runtime/Swift/Sources/Antlr4/CommonTokenStream.swift b/runtime/Swift/Sources/Antlr4/CommonTokenStream.swift index 265841583..8abaac82d 100644 --- a/runtime/Swift/Sources/Antlr4/CommonTokenStream.swift +++ b/runtime/Swift/Sources/Antlr4/CommonTokenStream.swift @@ -39,7 +39,7 @@ public class CommonTokenStream: BufferedTokenStream { /// The default value is _org.antlr.v4.runtime.Token#DEFAULT_CHANNEL_, which matches the /// default channel assigned to tokens created by the lexer. /// - internal var channel: Int = CommonToken.DEFAULT_CHANNEL + internal var channel = CommonToken.DEFAULT_CHANNEL /// /// Constructs a new _org.antlr.v4.runtime.CommonTokenStream_ using the specified token @@ -77,8 +77,8 @@ public class CommonTokenStream: BufferedTokenStream { return nil } - var i: Int = p - var n: Int = 1 + var i = p + var n = 1 // find k good tokens looking backwards while n <= k { // skip off-channel tokens @@ -101,8 +101,8 @@ public class CommonTokenStream: BufferedTokenStream { if k < 0 { return try LB(-k) } - var i: Int = p - var n: Int = 1 // we know tokens[p] is a good one + var i = p + var n = 1 // we know tokens[p] is a good one // find k good tokens while n < k { // skip off-channel tokens, but make sure to not look past EOF @@ -119,11 +119,11 @@ public class CommonTokenStream: BufferedTokenStream { /// Count EOF just once. /// public func getNumberOfOnChannelTokens() throws -> Int { - var n: Int = 0 + var n = 0 try fill() let length = tokens.count for i in 0..) - recognizer.notifyErrorListeners(re.getOffendingToken(), re.message ?? "", e); - } - } + if let nvae = e as? NoViableAltException { + reportNoViableAlternative(recognizer, nvae) + } + else if let ime = e as? InputMismatchException { + reportInputMismatch(recognizer, ime) + } + else if let fpe = e as? FailedPredicateException { + reportFailedPredicate(recognizer, fpe) + } + else { + errPrint("unknown recognition error type: " + String(describing: type(of: e))) + recognizer.notifyErrorListeners(e.getOffendingToken(), e.message ?? "", e) } } @@ -120,7 +118,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// until we find one in the resynchronization set--loosely the set of tokens /// that can follow the current rule. /// - public func recover(_ recognizer: Parser, _ e: AnyObject) throws { + public func recover(_ recognizer: Parser, _ e: RecognitionException) throws { // print("recover in "+recognizer.getRuleInvocationStack()+ // " index="+getTokenStream(recognizer).index()+ // ", lastErrorIndex="+ @@ -140,10 +138,10 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { } lastErrorIndex = getTokenStream(recognizer).index() if lastErrorStates == nil { - lastErrorStates = try IntervalSet() + lastErrorStates = IntervalSet() } try lastErrorStates!.add(recognizer.getState()) - let followSet: IntervalSet = try getErrorRecoverySet(recognizer) + let followSet = getErrorRecoverySet(recognizer) try consumeUntil(recognizer, followSet) } @@ -195,24 +193,19 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// public func sync(_ recognizer: Parser) throws { - let s: ATNState = recognizer.getInterpreter().atn.states[recognizer.getState()]! + let s = recognizer.getInterpreter().atn.states[recognizer.getState()]! // errPrint("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName()); // If already recovering, don't try to sync if inErrorRecoveryMode(recognizer) { return } - let tokens: TokenStream = getTokenStream(recognizer) - let la: Int = try tokens.LA(1) + let tokens = getTokenStream(recognizer) + let la = try tokens.LA(1) // try cheaper subset first; might get lucky. seems to shave a wee bit off - //let set : IntervalSet = recognizer.getATN().nextTokens(s) - - if try recognizer.getATN().nextTokens(s).contains(CommonToken.EPSILON) { - return - } - - if try recognizer.getATN().nextTokens(s).contains(la) { + let nextToks = recognizer.getATN().nextTokens(s) + if nextToks.contains(CommonToken.EPSILON) || nextToks.contains(la) { return } @@ -225,15 +218,14 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { if try singleTokenDeletion(recognizer) != nil { return } - throw try ANTLRException.recognition(e: InputMismatchException(recognizer)) + throw ANTLRException.recognition(e: InputMismatchException(recognizer)) case ATNState.PLUS_LOOP_BACK: fallthrough case ATNState.STAR_LOOP_BACK: // errPrint("at loop back: "+s.getClass().getSimpleName()); - try reportUnwantedToken(recognizer) - let expecting: IntervalSet = try recognizer.getExpectedTokens() - let whatFollowsLoopIterationOrRule: IntervalSet = - try expecting.or(try getErrorRecoverySet(recognizer)) as! IntervalSet + reportUnwantedToken(recognizer) + let expecting = try recognizer.getExpectedTokens() + let whatFollowsLoopIterationOrRule = expecting.or(getErrorRecoverySet(recognizer)) as! IntervalSet try consumeUntil(recognizer, whatFollowsLoopIterationOrRule) break @@ -253,19 +245,21 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// - parameter e: the recognition exception /// internal func reportNoViableAlternative(_ recognizer: Parser, - _ e: NoViableAltException) throws { - let tokens: TokenStream? = getTokenStream(recognizer) + _ e: NoViableAltException) { + let tokens = getTokenStream(recognizer) var input: String - if let tokens = tokens { - if e.getStartToken().getType() == CommonToken.EOF { - input = "" - } else { + if e.getStartToken().getType() == CommonToken.EOF { + input = "" + } + else { + do { input = try tokens.getText(e.getStartToken(), e.getOffendingToken()) } - } else { - input = "" + catch { + input = "" + } } - let msg: String = "no viable alternative at input " + escapeWSAndQuote(input) + let msg = "no viable alternative at input " + escapeWSAndQuote(input) recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e) } @@ -280,7 +274,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// internal func reportInputMismatch(_ recognizer: Parser, _ e: InputMismatchException) { - let msg: String = "mismatched input " + getTokenErrorDisplay(e.getOffendingToken()) + + let msg = "mismatched input " + getTokenErrorDisplay(e.getOffendingToken()) + " expecting " + e.getExpectedTokens()!.toString(recognizer.getVocabulary()) recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e) } @@ -296,8 +290,8 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// internal func reportFailedPredicate(_ recognizer: Parser, _ e: FailedPredicateException) { - let ruleName: String = recognizer.getRuleNames()[recognizer._ctx!.getRuleIndex()] - let msg: String = "rule " + ruleName + " " + e.message! // e.getMessage() + let ruleName = recognizer.getRuleNames()[recognizer._ctx!.getRuleIndex()] + let msg = "rule \(ruleName) \(e.message!)" recognizer.notifyErrorListeners(e.getOffendingToken(), msg, e) } @@ -319,18 +313,17 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// /// - parameter recognizer: the parser instance /// - internal func reportUnwantedToken(_ recognizer: Parser) throws { + internal func reportUnwantedToken(_ recognizer: Parser) { if inErrorRecoveryMode(recognizer) { return } beginErrorCondition(recognizer) - let t: Token = try recognizer.getCurrentToken() - let tokenName: String = getTokenErrorDisplay(t) - let expecting: IntervalSet = try getExpectedTokens(recognizer) - let msg: String = "extraneous input " + tokenName + " expecting " + - expecting.toString(recognizer.getVocabulary()) + let t = try? recognizer.getCurrentToken() + let tokenName = getTokenErrorDisplay(t) + let expecting = (try? getExpectedTokens(recognizer)) ?? IntervalSet.EMPTY_SET + let msg = "extraneous input \(tokenName) expecting \(expecting.toString(recognizer.getVocabulary()))" recognizer.notifyErrorListeners(t, msg, nil) } @@ -351,17 +344,16 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// /// - parameter recognizer: the parser instance /// - internal func reportMissingToken(_ recognizer: Parser) throws { + internal func reportMissingToken(_ recognizer: Parser) { if inErrorRecoveryMode(recognizer) { return } beginErrorCondition(recognizer) - let t: Token = try recognizer.getCurrentToken() - let expecting: IntervalSet = try getExpectedTokens(recognizer) - let msg: String = "missing " + expecting.toString(recognizer.getVocabulary()) + - " at " + getTokenErrorDisplay(t) + let t = try? recognizer.getCurrentToken() + let expecting = (try? getExpectedTokens(recognizer)) ?? IntervalSet.EMPTY_SET + let msg = "missing \(expecting.toString(recognizer.getVocabulary())) at \(getTokenErrorDisplay(t))" recognizer.notifyErrorListeners(t, msg, nil) } @@ -419,23 +411,20 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { public func recoverInline(_ recognizer: Parser) throws -> Token { // SINGLE TOKEN DELETION - let matchedSymbol: Token? = try singleTokenDeletion(recognizer) - if matchedSymbol != nil { + let matchedSymbol = try singleTokenDeletion(recognizer) + if let matchedSymbol = matchedSymbol { // we have deleted the extra token. // now, move past ttype token as if all were ok try recognizer.consume() - return matchedSymbol! + return matchedSymbol } // SINGLE TOKEN INSERTION if try singleTokenInsertion(recognizer) { return try getMissingSymbol(recognizer) } - throw try ANTLRException.recognition(e: InputMismatchException(recognizer)) - // throw try ANTLRException.InputMismatch(e: InputMismatchException(recognizer) ) - //RuntimeException("InputMismatchException") // even that didn't work; must throw the exception - //throwException() /* throw InputMismatchException(recognizer); */ + throw ANTLRException.recognition(e: InputMismatchException(recognizer)) } /// @@ -456,17 +445,17 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// strategy for the current mismatched input, otherwise `false` /// internal func singleTokenInsertion(_ recognizer: Parser) throws -> Bool { - let currentSymbolType: Int = try getTokenStream(recognizer).LA(1) + let currentSymbolType = try getTokenStream(recognizer).LA(1) // if current token is consistent with what could come after current // ATN state, then we know we're missing a token; error recovery // is free to conjure up and insert the missing token - let currentState: ATNState = recognizer.getInterpreter().atn.states[recognizer.getState()]! - let next: ATNState = currentState.transition(0).target - let atn: ATN = recognizer.getInterpreter().atn - let expectingAtLL2: IntervalSet = try atn.nextTokens(next, recognizer._ctx) + let currentState = recognizer.getInterpreter().atn.states[recognizer.getState()]! + let next = currentState.transition(0).target + let atn = recognizer.getInterpreter().atn + let expectingAtLL2 = atn.nextTokens(next, recognizer._ctx) // print("LT(2) set="+expectingAtLL2.toString(recognizer.getTokenNames())); if expectingAtLL2.contains(currentSymbolType) { - try reportMissingToken(recognizer) + reportMissingToken(recognizer) return true } return false @@ -492,10 +481,10 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// `null` /// internal func singleTokenDeletion(_ recognizer: Parser) throws -> Token? { - let nextTokenType: Int = try getTokenStream(recognizer).LA(2) - let expecting: IntervalSet = try getExpectedTokens(recognizer) + let nextTokenType = try getTokenStream(recognizer).LA(2) + let expecting = try getExpectedTokens(recognizer) if expecting.contains(nextTokenType) { - try reportUnwantedToken(recognizer) + reportUnwantedToken(recognizer) /// /// errPrint("recoverFromMismatchedToken deleting "+ /// ((TokenStream)getTokenStream(recognizer)).LT(1)+ @@ -504,7 +493,7 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// try recognizer.consume() // simply delete extra token // we want to return the token we're actually matching - let matchedSymbol: Token = try recognizer.getCurrentToken() + let matchedSymbol = try recognizer.getCurrentToken() reportMatch(recognizer) // we know current token is correct return matchedSymbol } @@ -536,25 +525,27 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { } internal func getMissingSymbol(_ recognizer: Parser) throws -> Token { - let currentSymbol: Token = try recognizer.getCurrentToken() - let expecting: IntervalSet = try getExpectedTokens(recognizer) - let expectedTokenType: Int = expecting.getMinElement() // get any element + let currentSymbol = try recognizer.getCurrentToken() + let expecting = try getExpectedTokens(recognizer) + let expectedTokenType = expecting.getMinElement() // get any element var tokenText: String if expectedTokenType == CommonToken.EOF { tokenText = "" } else { tokenText = "" } - var current: Token = currentSymbol - let lookback: Token? = try getTokenStream(recognizer).LT(-1) + var current = currentSymbol + let lookback = try getTokenStream(recognizer).LT(-1) if current.getType() == CommonToken.EOF && lookback != nil { current = lookback! } - let token = recognizer.getTokenFactory().create((current.getTokenSource(), current.getTokenSource()!.getInputStream()), expectedTokenType, tokenText, - CommonToken.DEFAULT_CHANNEL, - -1, -1, - current.getLine(), current.getCharPositionInLine()) + let token = recognizer.getTokenFactory().create( + current.getTokenSourceAndStream(), + expectedTokenType, tokenText, + CommonToken.DEFAULT_CHANNEL, + -1, -1, + current.getLine(), current.getCharPositionInLine()) return token } @@ -574,22 +565,22 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// so that it creates a new Java type. /// internal func getTokenErrorDisplay(_ t: Token?) -> String { - if t == nil { + guard let t = t else { return "" } - var s: String? = getSymbolText(t!) + var s = getSymbolText(t) if s == nil { - if getSymbolType(t!) == CommonToken.EOF { + if getSymbolType(t) == CommonToken.EOF { s = "" } else { - s = "<\(getSymbolType(t!))>" + s = "<\(getSymbolType(t))>" } } return escapeWSAndQuote(s!) } - internal func getSymbolText(_ symbol: Token) -> String { - return symbol.getText()! + internal func getSymbolText(_ symbol: Token) -> String? { + return symbol.getText() } internal func getSymbolType(_ symbol: Token) -> Int { @@ -698,19 +689,19 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// Like Grosch I implement context-sensitive FOLLOW sets that are combined /// at run-time upon error to avoid overhead during parsing. /// - internal func getErrorRecoverySet(_ recognizer: Parser) throws -> IntervalSet { - let atn: ATN = recognizer.getInterpreter().atn + internal func getErrorRecoverySet(_ recognizer: Parser) -> IntervalSet { + let atn = recognizer.getInterpreter().atn var ctx: RuleContext? = recognizer._ctx - let recoverSet: IntervalSet = try IntervalSet() - while let ctxWrap = ctx , ctxWrap.invokingState >= 0 { + let recoverSet = IntervalSet() + while let ctxWrap = ctx, ctxWrap.invokingState >= 0 { // compute what follows who invoked us - let invokingState: ATNState = atn.states[ctxWrap.invokingState]! - let rt: RuleTransition = invokingState.transition(0) as! RuleTransition - let follow: IntervalSet = try atn.nextTokens(rt.followState) - try recoverSet.addAll(follow) + let invokingState = atn.states[ctxWrap.invokingState]! + let rt = invokingState.transition(0) as! RuleTransition + let follow = atn.nextTokens(rt.followState) + try! recoverSet.addAll(follow) ctx = ctxWrap.parent } - try recoverSet.remove(CommonToken.EPSILON) + try! recoverSet.remove(CommonToken.EPSILON) // print("recover set "+recoverSet.toString(recognizer.getTokenNames())); return recoverSet } @@ -720,10 +711,9 @@ public class DefaultErrorStrategy: ANTLRErrorStrategy { /// internal func consumeUntil(_ recognizer: Parser, _ set: IntervalSet) throws { // errPrint("consumeUntil("+set.toString(recognizer.getTokenNames())+")"); - var ttype: Int = try getTokenStream(recognizer).LA(1) + var ttype = try getTokenStream(recognizer).LA(1) while ttype != CommonToken.EOF && !set.contains(ttype) { //print("consume during recover LA(1)="+getTokenNames()[input.LA(1)]); -// getTokenStream(recognizer).consume(); try recognizer.consume() ttype = try getTokenStream(recognizer).LA(1) } diff --git a/runtime/Swift/Sources/Antlr4/DiagnosticErrorListener.swift b/runtime/Swift/Sources/Antlr4/DiagnosticErrorListener.swift index 46a74cab2..4109f672b 100644 --- a/runtime/Swift/Sources/Antlr4/DiagnosticErrorListener.swift +++ b/runtime/Swift/Sources/Antlr4/DiagnosticErrorListener.swift @@ -59,16 +59,16 @@ public class DiagnosticErrorListener: BaseErrorListener { _ stopIndex: Int, _ exact: Bool, _ ambigAlts: BitSet, - _ configs: ATNConfigSet) throws { + _ configs: ATNConfigSet) { if exactOnly && !exact { return } let decision = getDecisionDescription(recognizer, dfa) - let conflictingAlts = try getConflictingAlts(ambigAlts, configs) - let text = try recognizer.getTokenStream()!.getText(Interval.of(startIndex, stopIndex)) + let conflictingAlts = getConflictingAlts(ambigAlts, configs) + let text = getTextInInterval(recognizer, startIndex, stopIndex) let message = "reportAmbiguity d=\(decision): ambigAlts=\(conflictingAlts), input='\(text)'" - try recognizer.notifyErrorListeners(message) + recognizer.notifyErrorListeners(message) } override @@ -77,11 +77,11 @@ public class DiagnosticErrorListener: BaseErrorListener { _ startIndex: Int, _ stopIndex: Int, _ conflictingAlts: BitSet?, - _ configs: ATNConfigSet) throws { + _ configs: ATNConfigSet) { let decision = getDecisionDescription(recognizer, dfa) - let text = try recognizer.getTokenStream()!.getText(Interval.of(startIndex, stopIndex)) + let text = getTextInInterval(recognizer, startIndex, stopIndex) let message = "reportAttemptingFullContext d=\(decision), input='\(text)'" - try recognizer.notifyErrorListeners(message) + recognizer.notifyErrorListeners(message) } override @@ -90,11 +90,11 @@ public class DiagnosticErrorListener: BaseErrorListener { _ startIndex: Int, _ stopIndex: Int, _ prediction: Int, - _ configs: ATNConfigSet) throws { + _ configs: ATNConfigSet) { let decision = getDecisionDescription(recognizer, dfa) - let text = try recognizer.getTokenStream()!.getText(Interval.of(startIndex, stopIndex)) + let text = getTextInInterval(recognizer, startIndex, stopIndex) let message = "reportContextSensitivity d=\(decision), input='\(text)'" - try recognizer.notifyErrorListeners(message) + recognizer.notifyErrorListeners(message) } internal func getDecisionDescription(_ recognizer: Parser, _ dfa: DFA) -> String { @@ -125,12 +125,17 @@ public class DiagnosticErrorListener: BaseErrorListener { /// - returns: Returns `reportedAlts` if it is not `null`, otherwise /// returns the set of alternatives represented in `configs`. /// - internal func getConflictingAlts(_ reportedAlts: BitSet?, _ configs: ATNConfigSet) throws -> BitSet { - if reportedAlts != nil { - return reportedAlts! - } - let result = try configs.getAltBitSet() - return result + internal func getConflictingAlts(_ reportedAlts: BitSet?, _ configs: ATNConfigSet) -> BitSet { + return reportedAlts ?? configs.getAltBitSet() + } +} + + +fileprivate func getTextInInterval(_ recognizer: Parser, _ startIndex: Int, _ stopIndex: Int) -> String { + do { + return try recognizer.getTokenStream()?.getText(Interval.of(startIndex, stopIndex)) ?? "" + } + catch { + return "" } - } diff --git a/runtime/Swift/Sources/Antlr4/FailedPredicateException.swift b/runtime/Swift/Sources/Antlr4/FailedPredicateException.swift index 5df39b506..c4e2bd310 100644 --- a/runtime/Swift/Sources/Antlr4/FailedPredicateException.swift +++ b/runtime/Swift/Sources/Antlr4/FailedPredicateException.swift @@ -11,30 +11,18 @@ /// Disambiguating predicate evaluation occurs when we test a predicate during /// prediction. /// -public class FailedPredicateException: RecognitionException { +public class FailedPredicateException: RecognitionException { private final var ruleIndex: Int private final var predicateIndex: Int private final var predicate: String? - public convenience init(_ recognizer: Parser) throws { - try self.init(recognizer, nil) - } + public init(_ recognizer: Parser, _ predicate: String? = nil, _ message: String? = nil) { + let s = recognizer.getInterpreter().atn.states[recognizer.getState()]! - public convenience init(_ recognizer: Parser, _ predicate: String?)throws { - try self.init(recognizer, predicate, nil) - } - - public init(_ recognizer: Parser, - _ predicate: String?, - _ message: String?) throws - { - - let s: ATNState = recognizer.getInterpreter().atn.states[recognizer.getState()]! - - let trans: AbstractPredicateTransition = s.transition(0) as! AbstractPredicateTransition - if trans is PredicateTransition { - self.ruleIndex = (trans as! PredicateTransition).ruleIndex - self.predicateIndex = (trans as! PredicateTransition).predIndex + let trans = s.transition(0) as! AbstractPredicateTransition + if let predex = trans as? PredicateTransition { + self.ruleIndex = predex.ruleIndex + self.predicateIndex = predex.predIndex } else { self.ruleIndex = 0 @@ -43,9 +31,10 @@ public class FailedPredicateException: RecognitionException self.predicate = predicate - super.init(FailedPredicateException.formatMessage(predicate!, message), recognizer , recognizer.getInputStream()!, recognizer._ctx) - - try self.setOffendingToken(recognizer.getCurrentToken()) + super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx, FailedPredicateException.formatMessage(predicate, message)) + if let token = try? recognizer.getCurrentToken() { + setOffendingToken(token) + } } public func getRuleIndex() -> Int { @@ -56,17 +45,17 @@ public class FailedPredicateException: RecognitionException return predicateIndex } - public func getPredicate() -> String? { return predicate } - private static func formatMessage(_ predicate: String, _ message: String?) -> String { + private static func formatMessage(_ predicate: String?, _ message: String?) -> String { if message != nil { return message! } - return "failed predicate: {predicate}?" //String.format(Locale.getDefault(), "failed predicate: {%s}?", predicate); + let predstr = predicate ?? "" + return "failed predicate: {\(predstr)}?" } } diff --git a/runtime/Swift/Sources/Antlr4/InputMismatchException.swift b/runtime/Swift/Sources/Antlr4/InputMismatchException.swift index 07797d6fd..8af781702 100644 --- a/runtime/Swift/Sources/Antlr4/InputMismatchException.swift +++ b/runtime/Swift/Sources/Antlr4/InputMismatchException.swift @@ -10,9 +10,11 @@ /// when the current input does not match the expected token. /// -public class InputMismatchException: RecognitionException { - public init(_ recognizer: Parser) throws { +public class InputMismatchException: RecognitionException { + public init(_ recognizer: Parser) { super.init(recognizer, recognizer.getInputStream()!, recognizer._ctx) - self.setOffendingToken(try recognizer.getCurrentToken()) + if let token = try? recognizer.getCurrentToken() { + setOffendingToken(token) + } } } diff --git a/runtime/Swift/Sources/Antlr4/Lexer.swift b/runtime/Swift/Sources/Antlr4/Lexer.swift index a324d321b..453d92aac 100644 --- a/runtime/Swift/Sources/Antlr4/Lexer.swift +++ b/runtime/Swift/Sources/Antlr4/Lexer.swift @@ -14,27 +14,24 @@ import Foundation -//public class Lexer : Recognizer +open class Lexer: Recognizer, TokenSource { + public static let EOF = -1 + public static let DEFAULT_MODE = 0 + public static let MORE = -2 + public static let SKIP = -3 -open class Lexer: Recognizer - , TokenSource { - public static let EOF: Int = -1 - public static let DEFAULT_MODE: Int = 0 - public static let MORE: Int = -2 - public static let SKIP: Int = -3 - - public static let DEFAULT_TOKEN_CHANNEL: Int = CommonToken.DEFAULT_CHANNEL - public static let HIDDEN: Int = CommonToken.HIDDEN_CHANNEL - public static let MIN_CHAR_VALUE: Int = Character.MIN_VALUE; - public static let MAX_CHAR_VALUE: Int = Character.MAX_VALUE; + public static let DEFAULT_TOKEN_CHANNEL = CommonToken.DEFAULT_CHANNEL + public static let HIDDEN = CommonToken.HIDDEN_CHANNEL + public static let MIN_CHAR_VALUE = Character.MIN_VALUE; + public static let MAX_CHAR_VALUE = Character.MAX_VALUE; public var _input: CharStream? - internal var _tokenFactorySourcePair: (TokenSource?, CharStream?) + internal var _tokenFactorySourcePair: TokenSourceAndStream /// /// How to create token objects /// - internal var _factory: TokenFactory = CommonTokenFactory.DEFAULT + internal var _factory = CommonTokenFactory.DEFAULT /// /// The goal of all lexer rules/methods is to create a token object. @@ -52,36 +49,36 @@ open class Lexer: Recognizer /// Needed, for example, to get the text for current token. Set at /// the start of nextToken. /// - public var _tokenStartCharIndex: Int = -1 + public var _tokenStartCharIndex = -1 /// /// The line on which the first character of the token resides /// - public var _tokenStartLine: Int = 0 + public var _tokenStartLine = 0 /// /// The character position of first character within the line /// - public var _tokenStartCharPositionInLine: Int = 0 + public var _tokenStartCharPositionInLine = 0 /// /// Once we see EOF on char stream, next token will be EOF. /// If you have DONE : EOF ; then you see DONE EOF. /// - public var _hitEOF: Bool = false + public var _hitEOF = false /// /// The channel number for the current token /// - public var _channel: Int = 0 + public var _channel = 0 /// /// The token type for the current token /// - public var _type: Int = 0 + public var _type = 0 - public final var _modeStack: Stack = Stack() - public var _mode: Int = Lexer.DEFAULT_MODE + public final var _modeStack = Stack() + public var _mode = Lexer.DEFAULT_MODE /// /// You can set the text for the current token to override what is in @@ -90,13 +87,17 @@ open class Lexer: Recognizer public var _text: String? public override init() { + self._tokenFactorySourcePair = TokenSourceAndStream() + super.init() + self._tokenFactorySourcePair.tokenSource = self } - public init(_ input: CharStream) { - - super.init() + public required init(_ input: CharStream) { self._input = input - self._tokenFactorySourcePair = (self, input) + self._tokenFactorySourcePair = TokenSourceAndStream() + super.init() + self._tokenFactorySourcePair.tokenSource = self + self._tokenFactorySourcePair.stream = input } open func reset() throws { @@ -131,7 +132,7 @@ open class Lexer: Recognizer // Mark start location in char stream so unbuffered streams are // guaranteed at least have text of current token - var tokenStartMarker: Int = _input.mark() + var tokenStartMarker = _input.mark() defer { // make sure we release marker after match or // unbuffered char stream will keep buffering @@ -237,10 +238,10 @@ open class Lexer: Recognizer open override func setInputStream(_ input: IntStream) throws { self._input = nil - self._tokenFactorySourcePair = (self, _input!) + self._tokenFactorySourcePair = makeTokenSourceAndStream() try reset() self._input = input as? CharStream - self._tokenFactorySourcePair = (self, _input!) + self._tokenFactorySourcePair = makeTokenSourceAndStream() } @@ -273,24 +274,25 @@ open class Lexer: Recognizer /// @discardableResult open func emit() -> Token { - let t: Token = _factory.create(_tokenFactorySourcePair, _type, _text, _channel, _tokenStartCharIndex, getCharIndex() - 1, - _tokenStartLine, _tokenStartCharPositionInLine) + let t = _factory.create(_tokenFactorySourcePair, _type, _text, _channel, _tokenStartCharIndex, getCharIndex() - 1, _tokenStartLine, _tokenStartCharPositionInLine) emit(t) return t } + @discardableResult open func emitEOF() -> Token { - let cpos: Int = getCharPositionInLine() - let line: Int = getLine() - let eof: Token = _factory.create( - _tokenFactorySourcePair, - CommonToken.EOF, - nil, - CommonToken.DEFAULT_CHANNEL, - _input!.index(), - _input!.index() - 1, - line, - cpos) + let cpos = getCharPositionInLine() + let line = getLine() + let idx = _input!.index() + let eof = _factory.create( + _tokenFactorySourcePair, + CommonToken.EOF, + nil, + CommonToken.DEFAULT_CHANNEL, + idx, + idx - 1, + line, + cpos) emit(eof) return eof } @@ -374,23 +376,13 @@ open class Lexer: Recognizer return nil } - /// - /// Used to print out token names like ID during debugging and - /// error reporting. The generated parsers implement a method - /// that overrides this to point to their String[] tokenNames. - /// - override - open func getTokenNames() -> [String?]? { - return nil - } - /// /// Return a list of all Token objects in input char stream. /// Forces load of all tokens. Does not include EOF token. /// - open func getAllTokens() throws -> Array { - var tokens: Array = Array() - var t: Token = try nextToken() + open func getAllTokens() throws -> [Token] { + var tokens = [Token]() + var t = try nextToken() while t.getType() != CommonToken.EOF { tokens.append(t) t = try nextToken() @@ -407,23 +399,29 @@ open class Lexer: Recognizer open func notifyListeners(_ e: LexerNoViableAltException, recognizer: Recognizer) { - let text: String = _input!.getText(Interval.of(_tokenStartCharIndex, _input!.index())) - let msg: String = "token recognition error at: '\(getErrorDisplay(text))'" + let text: String + do { + text = try _input!.getText(Interval.of(_tokenStartCharIndex, _input!.index())) + } + catch { + text = "" + } + let msg = "token recognition error at: '\(getErrorDisplay(text))'" - let listener: ANTLRErrorListener = getErrorListenerDispatch() + let listener = getErrorListenerDispatch() listener.syntaxError(recognizer, nil, _tokenStartLine, _tokenStartCharPositionInLine, msg, e) } open func getErrorDisplay(_ s: String) -> String { - let buf: StringBuilder = StringBuilder() - for c: Character in s.characters { + let buf = StringBuilder() + for c in s.characters { buf.append(getErrorDisplay(c)) } return buf.toString() } open func getErrorDisplay(_ c: Character) -> String { - var s: String = String(c) // String.valueOf(c as Character); + var s = String(c) if c.integerValue == CommonToken.EOF { s = "" } @@ -455,4 +453,8 @@ open class Lexer: Recognizer // TODO: Do we lose character or line position information? try _input!.consume() } + + internal func makeTokenSourceAndStream() -> TokenSourceAndStream { + return TokenSourceAndStream(self, _input) + } } diff --git a/runtime/Swift/Sources/Antlr4/LexerInterpreter.swift b/runtime/Swift/Sources/Antlr4/LexerInterpreter.swift index 77ddf74df..815ee5c3a 100644 --- a/runtime/Swift/Sources/Antlr4/LexerInterpreter.swift +++ b/runtime/Swift/Sources/Antlr4/LexerInterpreter.swift @@ -9,44 +9,19 @@ public class LexerInterpreter: Lexer { internal final var grammarFileName: String internal final var atn: ATN - /// - /// /@Deprecated - /// - internal final var tokenNames: [String?]? internal final var ruleNames: [String] internal final var channelNames: [String] internal final var modeNames: [String] - private final var vocabulary: Vocabulary? internal final var _decisionToDFA: [DFA] - internal final var _sharedContextCache: PredictionContextCache = - PredictionContextCache() -// public override init() { -// super.init()} - -// public convenience init(_ input : CharStream) { -// self.init() -// self._input = input; -// self._tokenFactorySourcePair = (self, input); -// } - //@Deprecated - public convenience init(_ grammarFileName: String, _ tokenNames: Array?, _ ruleNames: Array, _ channelNames: Array, _ modeNames: Array, _ atn: ATN, _ input: CharStream) throws { - try self.init(grammarFileName, Vocabulary.fromTokenNames(tokenNames), ruleNames, channelNames, modeNames, atn, input) - } + internal final var _sharedContextCache = PredictionContextCache() public init(_ grammarFileName: String, _ vocabulary: Vocabulary, _ ruleNames: Array, _ channelNames: Array, _ modeNames: Array, _ atn: ATN, _ input: CharStream) throws { self.grammarFileName = grammarFileName self.atn = atn - self.tokenNames = [String?]() - //new String[atn.maxTokenType]; - let length = tokenNames!.count - for i in 0.. ATN { return atn @@ -78,14 +55,6 @@ public class LexerInterpreter: Lexer { return grammarFileName } - override - /// - /// /@Deprecated - /// - public func getTokenNames() -> [String?]? { - return tokenNames - } - override public func getRuleNames() -> [String] { return ruleNames diff --git a/runtime/Swift/Sources/Antlr4/LexerNoViableAltException.swift b/runtime/Swift/Sources/Antlr4/LexerNoViableAltException.swift index 2edd79a7e..9f560c6c6 100644 --- a/runtime/Swift/Sources/Antlr4/LexerNoViableAltException.swift +++ b/runtime/Swift/Sources/Antlr4/LexerNoViableAltException.swift @@ -5,7 +5,7 @@ /// -public class LexerNoViableAltException: RecognitionException, CustomStringConvertible { +public class LexerNoViableAltException: RecognitionException, CustomStringConvertible { /// /// Matching attempted at what input index? /// @@ -31,23 +31,15 @@ public class LexerNoViableAltException: RecognitionException, return startIndex } - public func getDeadEndConfigs() -> ATNConfigSet { return deadEndConfigs } - //override -// public func getInputStream() -> CharStream { -// return super.getInputStream() as! CharStream; -// } - - public var description: String { - var symbol: String = "" - if startIndex >= 0 && startIndex < getInputStream().size() { - let charStream: CharStream = getInputStream() as! CharStream - let interval: Interval = Interval.of(startIndex, startIndex) - symbol = charStream.getText(interval) + var symbol = "" + if let charStream = getInputStream() as? CharStream, startIndex >= 0 && startIndex < charStream.size() { + let interval = Interval.of(startIndex, startIndex) + symbol = try! charStream.getText(interval) symbol = Utils.escapeWhitespace(symbol, false) } diff --git a/runtime/Swift/Sources/Antlr4/ListTokenSource.swift b/runtime/Swift/Sources/Antlr4/ListTokenSource.swift index 691cebd65..0863e16ee 100644 --- a/runtime/Swift/Sources/Antlr4/ListTokenSource.swift +++ b/runtime/Swift/Sources/Antlr4/ListTokenSource.swift @@ -17,7 +17,7 @@ public class ListTokenSource: TokenSource { /// /// The wrapped collection of _org.antlr.v4.runtime.Token_ objects to return. /// - internal final var tokens: Array + internal final var tokens: [Token] /// /// The name of the input source. If this value is `null`, a call to @@ -32,7 +32,7 @@ public class ListTokenSource: TokenSource { /// _#nextToken_. The end of the input is indicated by this value /// being greater than or equal to the number of items in _#tokens_. /// - internal var i: Int = 0 + internal var i = 0 /// /// This field caches the EOF token for the token source. @@ -43,7 +43,7 @@ public class ListTokenSource: TokenSource { /// This is the backing field for _#getTokenFactory_ and /// _setTokenFactory_. /// - private var _factory: TokenFactory = CommonTokenFactory.DEFAULT + private var _factory = CommonTokenFactory.DEFAULT /// /// Constructs a new _org.antlr.v4.runtime.ListTokenSource_ instance from the specified @@ -52,7 +52,7 @@ public class ListTokenSource: TokenSource { /// - parameter tokens: The collection of _org.antlr.v4.runtime.Token_ objects to provide as a /// _org.antlr.v4.runtime.TokenSource_. /// - public convenience init(_ tokens: Array) { + public convenience init(_ tokens: [Token]) { self.init(tokens, nil) } @@ -67,8 +67,7 @@ public class ListTokenSource: TokenSource { /// the next _org.antlr.v4.runtime.Token_ (or the previous token if the end of the input has /// been reached). /// - public init(_ tokens: Array, _ sourceName: String?) { - + public init(_ tokens: [Token], _ sourceName: String?) { self.tokens = tokens self.sourceName = sourceName } @@ -76,28 +75,24 @@ public class ListTokenSource: TokenSource { public func getCharPositionInLine() -> Int { if i < tokens.count { return tokens[i].getCharPositionInLine() - } else { - if let eofToken = eofToken { - return eofToken.getCharPositionInLine() - } else { - if tokens.count > 0 { - // have to calculate the result from the line/column of the previous - // token, along with the text of the token. - let lastToken: Token = tokens[tokens.count - 1] + } + else if let eofToken = eofToken { + return eofToken.getCharPositionInLine() + } + else if tokens.count > 0 { + // have to calculate the result from the line/column of the previous + // token, along with the text of the token. + let lastToken = tokens[tokens.count - 1] - if let tokenText = lastToken.getText() { - let lastNewLine: Int = tokenText.lastIndexOf("\n") - if lastNewLine >= 0 { - return tokenText.length - lastNewLine - 1 - } - } - var position = lastToken.getCharPositionInLine() - position += lastToken.getStopIndex() - position -= lastToken.getStartIndex() - position += 1 - return position + if let tokenText = lastToken.getText() { + let lastNewLine = tokenText.lastIndexOf("\n") + if lastNewLine >= 0 { + return tokenText.length - lastNewLine - 1 } } + return (lastToken.getCharPositionInLine() + + lastToken.getStopIndex() - + lastToken.getStartIndex() + 1) } // only reach this if tokens is empty, meaning EOF occurs at the first @@ -108,22 +103,23 @@ public class ListTokenSource: TokenSource { public func nextToken() -> Token { if i >= tokens.count { if eofToken == nil { - var start: Int = -1 + var start = -1 if tokens.count > 0 { - let previousStop: Int = tokens[tokens.count - 1].getStopIndex() + let previousStop = tokens[tokens.count - 1].getStopIndex() if previousStop != -1 { start = previousStop + 1 } } - let stop: Int = max(-1, start - 1) - eofToken = _factory.create((self, getInputStream()!), CommonToken.EOF, "EOF", CommonToken.DEFAULT_CHANNEL, start, stop, getLine(), getCharPositionInLine()) + let stop = max(-1, start - 1) + let source = TokenSourceAndStream(self, getInputStream()) + eofToken = _factory.create(source, CommonToken.EOF, "EOF", CommonToken.DEFAULT_CHANNEL, start, stop, getLine(), getCharPositionInLine()) } return eofToken! } - let t: Token = tokens[i] + let t = tokens[i] if i == tokens.count - 1 && t.getType() == CommonToken.EOF { eofToken = t } @@ -142,8 +138,8 @@ public class ListTokenSource: TokenSource { if tokens.count > 0 { // have to calculate the result from the line/column of the previous // token, along with the text of the token. - let lastToken: Token = tokens[tokens.count - 1] - var line: Int = lastToken.getLine() + let lastToken = tokens[tokens.count - 1] + var line = lastToken.getLine() if let tokenText = lastToken.getText() { let length = tokenText.length @@ -168,14 +164,12 @@ public class ListTokenSource: TokenSource { public func getInputStream() -> CharStream? { if i < tokens.count { return tokens[i].getInputStream() - } else { - if let eofToken = eofToken{ - return eofToken.getInputStream() - } else { - if tokens.count > 0 { - return tokens[tokens.count - 1].getInputStream() - } - } + } + else if let eofToken = eofToken { + return eofToken.getInputStream() + } + else if tokens.count > 0 { + return tokens[tokens.count - 1].getInputStream() } // no input stream information is available @@ -183,8 +177,8 @@ public class ListTokenSource: TokenSource { } public func getSourceName() -> String { - if sourceName != nil { - return sourceName! + if let sourceName = sourceName { + return sourceName } if let inputStream = getInputStream() { diff --git a/runtime/Swift/Sources/Antlr4/NoViableAltException.swift b/runtime/Swift/Sources/Antlr4/NoViableAltException.swift index 5158d0675..bf3ab415f 100644 --- a/runtime/Swift/Sources/Antlr4/NoViableAltException.swift +++ b/runtime/Swift/Sources/Antlr4/NoViableAltException.swift @@ -10,7 +10,7 @@ /// in the various paths when the error. Reported by reportNoViableAlternative() /// -public class NoViableAltException: RecognitionException { +public class NoViableAltException: RecognitionException { /// Which configurations did we try at input.index() that couldn't match input.LT(1)? private final var deadEndConfigs: ATNConfigSet? @@ -22,29 +22,31 @@ public class NoViableAltException: RecognitionException { /// private final var startToken: Token - public convenience init(_ recognizer: Parser?) throws { + public convenience init(_ recognizer: Parser) { // LL(1) error + let token = try! recognizer.getCurrentToken() self.init(recognizer, - recognizer!.getInputStream()!, - try recognizer!.getCurrentToken(), - try recognizer!.getCurrentToken(), + recognizer.getInputStream()!, + token, + token, nil, - recognizer!._ctx) + recognizer._ctx) } public init(_ recognizer: Parser?, _ input: IntStream, _ startToken: Token, - _ offendingToken: Token, + _ offendingToken: Token?, _ deadEndConfigs: ATNConfigSet?, _ ctx: ParserRuleContext?) { self.deadEndConfigs = deadEndConfigs self.startToken = startToken - // as? Recognizer super.init(recognizer, input, ctx) - self.setOffendingToken(offendingToken) + if let offendingToken = offendingToken { + setOffendingToken(offendingToken) + } } diff --git a/runtime/Swift/Sources/Antlr4/Parser.swift b/runtime/Swift/Sources/Antlr4/Parser.swift index 5a4c9257e..a031aaf88 100644 --- a/runtime/Swift/Sources/Antlr4/Parser.swift +++ b/runtime/Swift/Sources/Antlr4/Parser.swift @@ -12,7 +12,7 @@ import Foundation /// This is all the parsing support code essentially; most of it is error recovery stuff. /// open class Parser: Recognizer { - public static let EOF: Int = -1 + public static let EOF = -1 public static var ConsoleError = true public class TraceListener: ParseTreeListener { @@ -27,16 +27,13 @@ open class Parser: Recognizer { print("enter \(ruleName), LT(1)=\(lt1)") } - public func visitTerminal(_ node: TerminalNode) { print("consume \(String(describing: node.getSymbol())) rule \(host.getRuleNames()[host._ctx!.getRuleIndex()])") } - public func visitErrorNode(_ node: ErrorNode) { } - public func exitEveryRule(_ ctx: ParserRuleContext) throws { let ruleName = host.getRuleNames()[ctx.getRuleIndex()] let lt1 = try host._input.LT(1)!.getText()! @@ -45,23 +42,17 @@ open class Parser: Recognizer { } public class TrimToSizeListener: ParseTreeListener { - - - public static let INSTANCE: TrimToSizeListener = TrimToSizeListener() - + public static let INSTANCE = TrimToSizeListener() public func enterEveryRule(_ ctx: ParserRuleContext) { } - public func visitTerminal(_ node: TerminalNode) { } - public func visitErrorNode(_ node: ErrorNode) { } - public func exitEveryRule(_ ctx: ParserRuleContext) { // TODO: Print exit info. } @@ -193,7 +184,7 @@ open class Parser: Recognizer { /// @discardableResult public func match(_ ttype: Int) throws -> Token { - var t: Token = try getCurrentToken() + var t = try getCurrentToken() if t.getType() == ttype { _errHandler.reportMatch(self) try consume() @@ -228,7 +219,7 @@ open class Parser: Recognizer { /// @discardableResult public func matchWildcard() throws -> Token { - var t: Token = try getCurrentToken() + var t = try getCurrentToken() if t.getType() > 0 { _errHandler.reportMatch(self) try consume() @@ -297,18 +288,11 @@ open class Parser: Recognizer { /// using the default _org.antlr.v4.runtime.Parser.TrimToSizeListener_ during the parse process. /// public func getTrimParseTree() -> Bool { - return !getParseListeners().filter({ $0 === TrimToSizeListener.INSTANCE }).isEmpty } - - public func getParseListeners() -> Array { - let listeners: Array? = _parseListeners - if listeners == nil { - return Array() - } - - return listeners! + public func getParseListeners() -> [ParseTreeListener] { + return _parseListeners ?? [ParseTreeListener]() } /// @@ -338,10 +322,10 @@ open class Parser: Recognizer { /// public func addParseListener(_ listener: ParseTreeListener) { if _parseListeners == nil { - _parseListeners = Array() + _parseListeners = [ParseTreeListener]() } - self._parseListeners!.append(listener) + _parseListeners!.append(listener) } /// @@ -399,11 +383,11 @@ open class Parser: Recognizer { public func triggerExitRuleEvent() throws { // reverse order walk of listeners if let _parseListeners = _parseListeners, let _ctx = _ctx { - var i: Int = _parseListeners.count - 1 + var i = _parseListeners.count - 1 while i >= 0 { - let listener: ParseTreeListener = _parseListeners[i] + let listener = _parseListeners[i] _ctx.exitRule(listener) - try listener.exitEveryRule(_ctx) + try listener.exitEveryRule(_ctx) i -= 1 } } @@ -421,14 +405,12 @@ open class Parser: Recognizer { override open func getTokenFactory() -> TokenFactory { - // return _input.getTokenSource().getTokenFactory() } /// Tell our token source and error strategy about a new way to create tokens. override open func setTokenFactory(_ factory: TokenFactory) { - // _input.getTokenSource().setTokenFactory(factory) } @@ -439,15 +421,13 @@ open class Parser: Recognizer { /// - Throws: _ANTLRError.unsupportedOperation_ if the current parser does not /// implement the _#getSerializedATN()_ method. /// - public func getATNWithBypassAlts() -> ATN { - let serializedAtn: String = getSerializedATN() + let serializedAtn = getSerializedATN() - var result: ATN? = bypassAltsAtnCache[serializedAtn] - bypassAltsAtnCacheMutex.synchronized { - [unowned self] in + var result = bypassAltsAtnCache[serializedAtn] + bypassAltsAtnCacheMutex.synchronized { [unowned self] in if result == nil { - let deserializationOptions: ATNDeserializationOptions = ATNDeserializationOptions() + let deserializationOptions = ATNDeserializationOptions() try! deserializationOptions.setGenerateRuleBypassTransitions(true) result = try! ATNDeserializer(deserializationOptions).deserialize(Array(serializedAtn.characters)) self.bypassAltsAtnCache[serializedAtn] = result! @@ -469,14 +449,12 @@ open class Parser: Recognizer { /// public func compileParseTreePattern(_ pattern: String, _ patternRuleIndex: Int) throws -> ParseTreePattern { if let tokenStream = getTokenStream() { - let tokenSource: TokenSource = tokenStream.getTokenSource() - if tokenSource is Lexer { - let lexer: Lexer = tokenSource as! Lexer + let tokenSource = tokenStream.getTokenSource() + if let lexer = tokenSource as? Lexer { return try compileParseTreePattern(pattern, patternRuleIndex, lexer) } } throw ANTLRError.unsupportedOperation(msg: "Parser can't discover a lexer to use") - } /// @@ -485,7 +463,7 @@ open class Parser: Recognizer { /// public func compileParseTreePattern(_ pattern: String, _ patternRuleIndex: Int, _ lexer: Lexer) throws -> ParseTreePattern { - let m: ParseTreePatternMatcher = ParseTreePatternMatcher(lexer, self) + let m = ParseTreePatternMatcher(lexer, self) return try m.compile(pattern, patternRuleIndex) } @@ -528,19 +506,21 @@ open class Parser: Recognizer { return try _input.LT(1)! } - public final func notifyErrorListeners(_ msg: String) throws { - try notifyErrorListeners(getCurrentToken(), msg, nil) + public final func notifyErrorListeners(_ msg: String) { + let token = try? getCurrentToken() + notifyErrorListeners(token, msg, nil) } - public func notifyErrorListeners(_ offendingToken: Token, _ msg: String, - _ e: AnyObject?) { + public func notifyErrorListeners(_ offendingToken: Token?, _ msg: String, _ e: AnyObject?) { _syntaxErrors += 1 - var line: Int = -1 - var charPositionInLine: Int = -1 - line = offendingToken.getLine() - charPositionInLine = offendingToken.getCharPositionInLine() + var line = -1 + var charPositionInLine = -1 + if let offendingToken = offendingToken { + line = offendingToken.getLine() + charPositionInLine = offendingToken.getCharPositionInLine() + } - let listener: ANTLRErrorListener = getErrorListenerDispatch() + let listener = getErrorListenerDispatch() listener.syntaxError(self, offendingToken, line, charPositionInLine, msg, e) } @@ -567,27 +547,27 @@ open class Parser: Recognizer { /// @discardableResult public func consume() throws -> Token { - let o: Token = try getCurrentToken() + let o = try getCurrentToken() if o.getType() != Parser.EOF { try getInputStream()!.consume() } guard let _ctx = _ctx else { return o } - let hasListener: Bool = _parseListeners != nil && !_parseListeners!.isEmpty + let hasListener = _parseListeners != nil && !_parseListeners!.isEmpty if _buildParseTrees || hasListener { if _errHandler.inErrorRecoveryMode(self) { - let node: ErrorNode = _ctx.addErrorNode(createErrorNode(parent: _ctx, t: o)) + let node = _ctx.addErrorNode(createErrorNode(parent: _ctx, t: o)) if let _parseListeners = _parseListeners { - for listener: ParseTreeListener in _parseListeners { + for listener in _parseListeners { listener.visitErrorNode(node) } } } else { - let node: TerminalNode = _ctx.addChild(createTerminalNode(parent: _ctx, t: o)) + let node = _ctx.addChild(createTerminalNode(parent: _ctx, t: o)) if let _parseListeners = _parseListeners { - for listener: ParseTreeListener in _parseListeners { + for listener in _parseListeners { listener.visitTerminal(node) } } @@ -703,7 +683,7 @@ open class Parser: Recognizer { /// Make the current context the child of the incoming localctx. /// public func pushNewRecursionContext(_ localctx: ParserRuleContext, _ state: Int, _ ruleIndex: Int) throws { - let previous: ParserRuleContext = _ctx! + let previous = _ctx! previous.parent = localctx previous.invokingState = state previous.stop = try _input.LT(-1) @@ -722,12 +702,12 @@ open class Parser: Recognizer { public func unrollRecursionContexts(_ _parentctx: ParserRuleContext?) throws { _precedenceStack.pop() _ctx!.stop = try _input.LT(-1) - let retctx: ParserRuleContext = _ctx! // save current ctx (return value) + let retctx = _ctx! // save current ctx (return value) // unroll so _ctx is as it was before call to recursive method if _parseListeners != nil { - while let ctxWrap = _ctx , ctxWrap !== _parentctx { - try triggerExitRuleEvent() + while let ctxWrap = _ctx, ctxWrap !== _parentctx { + try triggerExitRuleEvent() _ctx = ctxWrap.parent as? ParserRuleContext } } else { @@ -744,7 +724,7 @@ open class Parser: Recognizer { } public func getInvokingContext(_ ruleIndex: Int) -> ParserRuleContext? { - var p: ParserRuleContext? = _ctx + var p = _ctx while let pWrap = p { if pWrap.getRuleIndex() == ruleIndex { return pWrap @@ -857,7 +837,7 @@ open class Parser: Recognizer { // parser.getInterpreter()!.setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION); // // // get ambig trees -// var alt : Int = ambiguityInfo.ambigAlts.nextSetBit(0); +// var alt : Int = ambiguityInfo.ambigAlts.firstSetBit(); // while alt>=0 { // // re-parse entire input for all ambiguous alternatives // // (don't have to do first as it's been parsed, but do again for simplicity @@ -895,12 +875,11 @@ open class Parser: Recognizer { /// - Returns: `true` if `symbol` can follow the current state in /// the ATN, otherwise `false`. /// - public func isExpectedToken(_ symbol: Int) throws -> Bool { -// return getInterpreter().atn.nextTokens(_ctx); - let atn: ATN = getInterpreter().atn + public func isExpectedToken(_ symbol: Int) -> Bool { + let atn = getInterpreter().atn var ctx: ParserRuleContext? = _ctx - let s: ATNState = atn.states[getState()]! - var following: IntervalSet = try atn.nextTokens(s) + let s = atn.states[getState()]! + var following = atn.nextTokens(s) if following.contains(symbol) { return true } @@ -909,10 +888,10 @@ open class Parser: Recognizer { return false } - while let ctxWrap = ctx , ctxWrap.invokingState >= 0 && following.contains(CommonToken.EPSILON) { - let invokingState: ATNState = atn.states[ctxWrap.invokingState]! - let rt: RuleTransition = invokingState.transition(0) as! RuleTransition - following = try atn.nextTokens(rt.followState) + while let ctxWrap = ctx, ctxWrap.invokingState >= 0 && following.contains(CommonToken.EPSILON) { + let invokingState = atn.states[ctxWrap.invokingState]! + let rt = invokingState.transition(0) as! RuleTransition + following = atn.nextTokens(rt.followState) if following.contains(symbol) { return true } @@ -939,19 +918,15 @@ open class Parser: Recognizer { } - public func getExpectedTokensWithinCurrentRule() throws -> IntervalSet { - let atn: ATN = getInterpreter().atn - let s: ATNState = atn.states[getState()]! - return try atn.nextTokens(s) + public func getExpectedTokensWithinCurrentRule() -> IntervalSet { + let atn = getInterpreter().atn + let s = atn.states[getState()]! + return atn.nextTokens(s) } /// Get a rule's index (i.e., `RULE_ruleName` field) or -1 if not found. public func getRuleIndex(_ ruleName: String) -> Int { - let ruleIndex: Int? = getRuleIndexMap()[ruleName] - if ruleIndex != nil { - return ruleIndex! - } - return -1 + return getRuleIndexMap()[ruleName] ?? -1 } public func getRuleContext() -> ParserRuleContext? { @@ -965,17 +940,17 @@ open class Parser: Recognizer { /// /// This is very useful for error messages. /// - public func getRuleInvocationStack() -> Array { + public func getRuleInvocationStack() -> [String] { return getRuleInvocationStack(_ctx) } - public func getRuleInvocationStack(_ p: RuleContext?) -> Array { + public func getRuleInvocationStack(_ p: RuleContext?) -> [String] { var p = p - var ruleNames: [String] = getRuleNames() - var stack: Array = Array() + var ruleNames = getRuleNames() + var stack = [String]() while let pWrap = p { // compute what follows who invoked us - let ruleIndex: Int = pWrap.getRuleIndex() + let ruleIndex = pWrap.getRuleIndex() if ruleIndex < 0 { stack.append("n/a") } else { @@ -987,16 +962,14 @@ open class Parser: Recognizer { } /// For debugging and other purposes. - public func getDFAStrings() -> Array { - var s: Array = Array() + public func getDFAStrings() -> [String] { + var s = [String]() guard let _interp = _interp else { return s } - decisionToDFAMutex.synchronized { - [unowned self] in - + decisionToDFAMutex.synchronized { [unowned self] in for d in 0..<_interp.decisionToDFA.count { - let dfa: DFA = _interp.decisionToDFA[d] + let dfa = _interp.decisionToDFA[d] s.append(dfa.toString(self.getVocabulary())) } @@ -1006,15 +979,13 @@ open class Parser: Recognizer { /// For debugging and other purposes. public func dumpDFA() { - guard let _interp = _interp else { + guard let _interp = _interp else { return } - decisionToDFAMutex.synchronized { - [unowned self] in - var seenOne: Bool = false + decisionToDFAMutex.synchronized { [unowned self] in + var seenOne = false - for d in 0..<_interp.decisionToDFA.count { - let dfa: DFA = _interp.decisionToDFA[d] + for dfa in _interp.decisionToDFA { if !dfa.states.isEmpty { if seenOne { print("") @@ -1034,9 +1005,9 @@ open class Parser: Recognizer { override open func getParseInfo() -> ParseInfo? { - let interp: ParserATNSimulator? = getInterpreter() - if interp is ProfilingATNSimulator { - return ParseInfo(interp as! ProfilingATNSimulator) + let interp = getInterpreter() + if let interp = interp as? ProfilingATNSimulator { + return ParseInfo(interp) } return nil } @@ -1045,16 +1016,15 @@ open class Parser: Recognizer { /// - Since: 4.3 /// public func setProfile(_ profile: Bool) { - let interp: ParserATNSimulator = getInterpreter() - let saveMode: PredictionMode = interp.getPredictionMode() + let interp = getInterpreter() + let saveMode = interp.getPredictionMode() if profile { if !(interp is ProfilingATNSimulator) { setInterpreter(ProfilingATNSimulator(self)) } } else { if interp is ProfilingATNSimulator { - let sim: ParserATNSimulator = - ParserATNSimulator(self, getATN(), interp.decisionToDFA, interp.getSharedContextCache()!) + let sim = ParserATNSimulator(self, getATN(), interp.decisionToDFA, interp.getSharedContextCache()!) setInterpreter(sim) } } diff --git a/runtime/Swift/Sources/Antlr4/ParserInterpreter.swift b/runtime/Swift/Sources/Antlr4/ParserInterpreter.swift index 100d86359..1e760fc84 100644 --- a/runtime/Swift/Sources/Antlr4/ParserInterpreter.swift +++ b/runtime/Swift/Sources/Antlr4/ParserInterpreter.swift @@ -32,10 +32,6 @@ public class ParserInterpreter: Parser { internal final var sharedContextCache: PredictionContextCache = PredictionContextCache() - /// - /// /@Deprecated - /// - internal final var tokenNames: [String] internal final var ruleNames: [String] private final var vocabulary: Vocabulary @@ -64,7 +60,6 @@ public class ParserInterpreter: Parser { self.grammarFileName = old.grammarFileName self.statesNeedingLeftRecursionContext = old.statesNeedingLeftRecursionContext self.decisionToDFA = old.decisionToDFA - self.tokenNames = old.tokenNames self.ruleNames = old.ruleNames self.vocabulary = old.vocabulary try super.init(old.getTokenStream()!) @@ -73,26 +68,11 @@ public class ParserInterpreter: Parser { sharedContextCache)) } - /// - /// Use _#ParserInterpreter(String, org.antlr.v4.runtime.Vocabulary, java.util.Collection, org.antlr.v4.runtime.atn.ATN, org.antlr.v4.runtime.TokenStream)_ instead. - /// - //@Deprecated - public convenience init(_ grammarFileName: String, _ tokenNames: Array?, - _ ruleNames: Array, _ atn: ATN, _ input: TokenStream) throws { - try self.init(grammarFileName, Vocabulary.fromTokenNames(tokenNames), ruleNames, atn, input) - } - public init(_ grammarFileName: String, _ vocabulary: Vocabulary, _ ruleNames: Array, _ atn: ATN, _ input: TokenStream) throws { self.grammarFileName = grammarFileName self.atn = atn - self.tokenNames = [String]()// new String[atn.maxTokenType]; - let length = tokenNames.count - for i in 0.. [String] { - return tokenNames - } - override public func getVocabulary() -> Vocabulary { return vocabulary @@ -148,17 +120,17 @@ public class ParserInterpreter: Parser { /// Begin parsing at startRuleIndex public func parse(_ startRuleIndex: Int) throws -> ParserRuleContext { - let startRuleStartState: RuleStartState = atn.ruleToStartState[startRuleIndex] + let startRuleStartState = atn.ruleToStartState[startRuleIndex] - let rootContext: InterpreterRuleContext = InterpreterRuleContext(nil, ATNState.INVALID_STATE_NUMBER, startRuleIndex) + let rootContext = InterpreterRuleContext(nil, ATNState.INVALID_STATE_NUMBER, startRuleIndex) if startRuleStartState.isPrecedenceRule { - try enterRecursionRule(rootContext, startRuleStartState.stateNumber, startRuleIndex, 0) + try enterRecursionRule(rootContext, startRuleStartState.stateNumber, startRuleIndex, 0) } else { try enterRule(rootContext, startRuleStartState.stateNumber, startRuleIndex) } while true { - let p: ATNState = getATNState()! + let p = getATNState()! switch p.getStateType() { case ATNState.RULE_STOP: // pop; return from rule @@ -208,7 +180,7 @@ public class ParserInterpreter: Parser { var altNum: Int if p.getNumberOfTransitions() > 1 { try getErrorHandler().sync(self) - let decision: Int = (p as! DecisionState).decision + let decision = (p as! DecisionState).decision if decision == overrideDecision && _input.index() == overrideDecisionInputIndex { altNum = overrideDecisionAlt } else { @@ -218,7 +190,7 @@ public class ParserInterpreter: Parser { altNum = 1 } - let transition: Transition = p.transition(altNum - 1) + let transition = p.transition(altNum - 1) switch transition.getSerializationType() { case Transition.EPSILON: if try statesNeedingLeftRecursionContext.get(p.stateNumber) && @@ -252,9 +224,9 @@ public class ParserInterpreter: Parser { break case Transition.RULE: - let ruleStartState: RuleStartState = transition.target as! RuleStartState - let ruleIndex: Int = ruleStartState.ruleIndex! - let ctx: InterpreterRuleContext = InterpreterRuleContext(_ctx, p.stateNumber, ruleIndex) + let ruleStartState = transition.target as! RuleStartState + let ruleIndex = ruleStartState.ruleIndex! + let ctx = InterpreterRuleContext(_ctx, p.stateNumber, ruleIndex) if ruleStartState.isPrecedenceRule { try enterRecursionRule(ctx, ruleStartState.stateNumber, ruleIndex, (transition as! RuleTransition).precedence) } else { @@ -263,25 +235,20 @@ public class ParserInterpreter: Parser { break case Transition.PREDICATE: - let predicateTransition: PredicateTransition = transition as! PredicateTransition + let predicateTransition = transition as! PredicateTransition if try !sempred(_ctx!, predicateTransition.ruleIndex, predicateTransition.predIndex) { - - throw try ANTLRException.recognition(e: FailedPredicateException(self)) - + throw ANTLRException.recognition(e: FailedPredicateException(self)) } - break case Transition.ACTION: - let actionTransition: ActionTransition = transition as! ActionTransition + let actionTransition = transition as! ActionTransition try action(_ctx, actionTransition.ruleIndex, actionTransition.actionIndex) break case Transition.PRECEDENCE: if !precpred(_ctx!, (transition as! PrecedencePredicateTransition).precedence) { - - throw try ANTLRException.recognition(e: FailedPredicateException(self, "precpred(_ctx,\((transition as! PrecedencePredicateTransition).precedence))")) - + throw ANTLRException.recognition(e: FailedPredicateException(self, "precpred(_ctx,\((transition as! PrecedencePredicateTransition).precedence))")) } break @@ -294,16 +261,16 @@ public class ParserInterpreter: Parser { } internal func visitRuleStopState(_ p: ATNState) throws { - let ruleStartState: RuleStartState = atn.ruleToStartState[p.ruleIndex!] + let ruleStartState = atn.ruleToStartState[p.ruleIndex!] if ruleStartState.isPrecedenceRule { - let parentContext: (ParserRuleContext?, Int) = _parentContextStack.pop() - try unrollRecursionContexts(parentContext.0!) - setState(parentContext.1) + let (parentContext, parentState) = _parentContextStack.pop() + try unrollRecursionContexts(parentContext!) + setState(parentState) } else { try exitRule() } - let ruleTransition: RuleTransition = atn.states[getState()]!.transition(0) as! RuleTransition + let ruleTransition = atn.states[getState()]!.transition(0) as! RuleTransition setState(ruleTransition.followState.stateNumber) } diff --git a/runtime/Swift/Sources/Antlr4/ProxyErrorListener.swift b/runtime/Swift/Sources/Antlr4/ProxyErrorListener.swift index 5d1d7646c..17d6b21b7 100644 --- a/runtime/Swift/Sources/Antlr4/ProxyErrorListener.swift +++ b/runtime/Swift/Sources/Antlr4/ProxyErrorListener.swift @@ -13,10 +13,9 @@ /// public class ProxyErrorListener: ANTLRErrorListener { - private final var delegates: Array - - public init(_ delegates: Array) { + private final var delegates: [ANTLRErrorListener] + public init(_ delegates: [ANTLRErrorListener]) { self.delegates = delegates } @@ -27,7 +26,7 @@ public class ProxyErrorListener: ANTLRErrorListener { _ msg: String, _ e: AnyObject?) { - for listener: ANTLRErrorListener in delegates { + for listener in delegates { listener.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) } } @@ -39,9 +38,9 @@ public class ProxyErrorListener: ANTLRErrorListener { _ stopIndex: Int, _ exact: Bool, _ ambigAlts: BitSet, - _ configs: ATNConfigSet) throws { - for listener: ANTLRErrorListener in delegates { - try listener.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) + _ configs: ATNConfigSet) { + for listener in delegates { + listener.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs) } } @@ -51,9 +50,9 @@ public class ProxyErrorListener: ANTLRErrorListener { _ startIndex: Int, _ stopIndex: Int, _ conflictingAlts: BitSet?, - _ configs: ATNConfigSet) throws { - for listener: ANTLRErrorListener in delegates { - try listener.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) + _ configs: ATNConfigSet) { + for listener in delegates { + listener.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs) } } @@ -63,9 +62,9 @@ public class ProxyErrorListener: ANTLRErrorListener { _ startIndex: Int, _ stopIndex: Int, _ prediction: Int, - _ configs: ATNConfigSet) throws { - for listener: ANTLRErrorListener in delegates { - try listener.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) + _ configs: ATNConfigSet) { + for listener in delegates { + listener.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs) } } } diff --git a/runtime/Swift/Sources/Antlr4/RecognitionException.swift b/runtime/Swift/Sources/Antlr4/RecognitionException.swift index e3bfac022..49a8807f9 100644 --- a/runtime/Swift/Sources/Antlr4/RecognitionException.swift +++ b/runtime/Swift/Sources/Antlr4/RecognitionException.swift @@ -11,16 +11,15 @@ /// and what kind of problem occurred. /// -public class RecognitionException { +public class RecognitionException { /// /// The _org.antlr.v4.runtime.Recognizer_ where this exception originated. /// - private final var recognizer: Recognizer? - //Recognizer? ; + private final var recognizer: RecognizerProtocol? - private final var ctx: RuleContext? + private final weak var ctx: RuleContext? - private final var input: IntStream + private final var input: IntStream? /// /// The current _org.antlr.v4.runtime.Token_ when an error occurred. Since not all streams @@ -29,28 +28,18 @@ public class RecognitionException { /// private var offendingToken: Token! - private var offendingState: Int = -1 + private var offendingState = -1 public var message: String? - public init(_ recognizer: Recognizer?, - _ input: IntStream, - _ ctx: ParserRuleContext?) { - self.recognizer = recognizer - self.input = input - self.ctx = ctx - if let recognizer = recognizer { - self.offendingState = recognizer.getState() - } - } - public init(_ message: String, - _ recognizer: Recognizer?, + public init(_ recognizer: RecognizerProtocol?, _ input: IntStream, - _ ctx: ParserRuleContext?) { - self.message = message + _ ctx: ParserRuleContext? = nil, + _ message: String? = nil) { self.recognizer = recognizer self.input = input self.ctx = ctx + self.message = message if let recognizer = recognizer { self.offendingState = recognizer.getState() } @@ -87,7 +76,6 @@ public class RecognitionException { if let recognizer = recognizer { return try? recognizer.getATN().getExpectedTokens(offendingState, ctx!) } - return nil } @@ -113,10 +101,13 @@ public class RecognitionException { /// where this exception was thrown, or `null` if the stream is not /// available. /// - public func getInputStream() -> IntStream { + public func getInputStream() -> IntStream? { return input } + public func clearInputStream() { + input = nil + } public func getOffendingToken() -> Token { return offendingToken @@ -134,7 +125,11 @@ public class RecognitionException { /// - Returns: The recognizer where this exception occurred, or `null` if /// the recognizer is not available. /// - public func getRecognizer() -> Recognizer? { + public func getRecognizer() -> RecognizerProtocol? { return recognizer } + + public func clearRecognizer() { + self.recognizer = nil + } } diff --git a/runtime/Swift/Sources/Antlr4/Recognizer.swift b/runtime/Swift/Sources/Antlr4/Recognizer.swift index 6133bbeea..6b3c60088 100644 --- a/runtime/Swift/Sources/Antlr4/Recognizer.swift +++ b/runtime/Swift/Sources/Antlr4/Recognizer.swift @@ -5,60 +5,53 @@ import Foundation -open class Recognizer { - //public static let EOF: Int = -1 + +public protocol RecognizerProtocol { + func getATN() -> ATN + func getGrammarFileName() -> String + func getParseInfo() -> ParseInfo? + func getRuleNames() -> [String] + func getSerializedATN() -> String + func getState() -> Int + func getTokenType(_ tokenName: String) -> Int + func getVocabulary() -> Vocabulary +} + + +open class Recognizer: RecognizerProtocol { //TODO: WeakKeyDictionary NSMapTable Dictionary MapTable> - private let tokenTypeMapCache = HashMap>() + private let tokenTypeMapCache = HashMap() - private let ruleIndexMapCache = HashMap,Dictionary>() - - - private var _listeners: Array = [ConsoleErrorListener.INSTANCE] + private let ruleIndexMapCache = HashMap, [String : Int]>() + private var _listeners: [ANTLRErrorListener] = [ConsoleErrorListener.INSTANCE] public var _interp: ATNInterpreter! - private var _stateNumber: Int = -1 + private var _stateNumber = -1 /// /// mutex for tokenTypeMapCache updates /// - private var tokenTypeMapCacheMutex = Mutex() + private let tokenTypeMapCacheMutex = Mutex() /// /// mutex for ruleIndexMapCacheMutex updates /// - private var ruleIndexMapCacheMutex = Mutex() - - /// Used to print out token names like ID during debugging and - /// error reporting. The generated parsers implement a method - /// that overrides this to point to their String[] tokenNames. - /// - /// Use _#getVocabulary()_ instead. - /// - /// - /// /@Deprecated - /// - open func getTokenNames() -> [String?]? { - RuntimeException(#function + " must be overridden") - return [] - } + private let ruleIndexMapCacheMutex = Mutex() open func getRuleNames() -> [String] { - RuntimeException(#function + " must be overridden") - return [] + fatalError(#function + " must be overridden") } - - /// + /// /// Get the vocabulary used by the recognizer. /// /// - Returns: A _org.antlr.v4.runtime.Vocabulary_ instance providing information about the /// vocabulary used by the grammar. /// - open func getVocabulary() -> Vocabulary { - return Vocabulary.fromTokenNames(getTokenNames()) + fatalError(#function + " must be overridden") } /// @@ -66,35 +59,29 @@ open class Recognizer { /// /// Used for XPath and tree pattern compilation. /// - public func getTokenTypeMap() -> Dictionary { - let vocabulary: Vocabulary = getVocabulary() - var result: Dictionary? = self.tokenTypeMapCache[vocabulary] - tokenTypeMapCacheMutex.synchronized { - [unowned self] in + public func getTokenTypeMap() -> [String : Int] { + let vocabulary = getVocabulary() + var result = tokenTypeMapCache[vocabulary] + tokenTypeMapCacheMutex.synchronized { [unowned self] in if result == nil { - result = Dictionary() + result = [String : Int]() let length = self.getATN().maxTokenType for i in 0...length { - let literalName: String? = vocabulary.getLiteralName(i) - if literalName != nil { - result![literalName!] = i + if let literalName = vocabulary.getLiteralName(i) { + result![literalName] = i } - let symbolicName: String? = vocabulary.getSymbolicName(i) - if symbolicName != nil { - result![symbolicName!] = i + if let symbolicName = vocabulary.getSymbolicName(i) { + result![symbolicName] = i } } result!["EOF"] = CommonToken.EOF - //TODO Result Collections.unmodifiableMap - self.tokenTypeMapCache[vocabulary] = result! } } return result! - } /// @@ -102,26 +89,20 @@ open class Recognizer { /// /// Used for XPath and tree pattern compilation. /// - public func getRuleIndexMap() -> Dictionary { - let ruleNames: [String] = getRuleNames() + public func getRuleIndexMap() -> [String : Int] { + let ruleNames = getRuleNames() - let result: Dictionary? = self.ruleIndexMapCache[ArrayWrapper(ruleNames)] - ruleIndexMapCacheMutex.synchronized { - [unowned self] in + let result = ruleIndexMapCache[ArrayWrapper(ruleNames)] + ruleIndexMapCacheMutex.synchronized { [unowned self] in if result == nil { self.ruleIndexMapCache[ArrayWrapper(ruleNames)] = Utils.toMap(ruleNames) } } return result! - } public func getTokenType(_ tokenName: String) -> Int { - let ttype: Int? = getTokenTypeMap()[tokenName] - if ttype != nil { - return ttype! - } - return CommonToken.INVALID_TYPE + return getTokenTypeMap()[tokenName] ?? CommonToken.INVALID_TYPE } /// @@ -132,16 +113,14 @@ open class Recognizer { /// created the interpreter from it. /// open func getSerializedATN() -> String { - RuntimeException("there is no serialized ATN") - fatalError() + fatalError("there is no serialized ATN") } /// For debugging and other purposes, might want the grammar name. /// Have ANTLR generate an implementation for this method. /// open func getGrammarFileName() -> String { - RuntimeException(#function + " must be overridden") - return "" + fatalError(#function + " must be overridden") } /// @@ -150,8 +129,7 @@ open class Recognizer { /// - Returns: The _org.antlr.v4.runtime.atn.ATN_ used by the recognizer for prediction. /// open func getATN() -> ATN { - RuntimeException(#function + " must be overridden") - fatalError() + fatalError(#function + " must be overridden") } /// @@ -185,51 +163,14 @@ open class Recognizer { /// /// What is the error header, normally line/character position information? /// - open func getErrorHeader(_ e: AnyObject) -> String { - let line: Int = (e as! RecognitionException).getOffendingToken().getLine() - let charPositionInLine: Int = (e as! RecognitionException).getOffendingToken().getCharPositionInLine() - return "line " + String(line) + ":" + String(charPositionInLine) - } - - /// How should a token be displayed in an error message? The default - /// is to display just the text, but during development you might - /// want to have a lot of information spit out. Override in that case - /// to use t.toString() (which, for CommonToken, dumps everything about - /// the token). This is better than forcing you to override a method in - /// your token objects because you don't have to go modify your lexer - /// so that it creates a new Java type. - /// - /// This method is not called by the ANTLR 4 Runtime. Specific - /// implementations of _org.antlr.v4.runtime.ANTLRErrorStrategy_ may provide a similar - /// feature when necessary. For example, see - /// _org.antlr.v4.runtime.DefaultErrorStrategy#getTokenErrorDisplay_. - /// - /// - /// /@Deprecated - /// - open func getTokenErrorDisplay(_ t: Token?) -> String { - guard let t = t else { - return "" - } - var s: String - - if let text = t.getText() { - s = text - } else { - if t.getType() == CommonToken.EOF { - s = "" - } else { - s = "<\(t.getType())>" - } - } - s = s.replacingOccurrences(of: "\n", with: "\\n") - s = s.replacingOccurrences(of: "\r", with: "\\r") - s = s.replacingOccurrences(of: "\t", with: "\\t") - return "\(s)" + open func getErrorHeader(_ e: RecognitionException) -> String { + let offending = e.getOffendingToken() + let line = offending.getLine() + let charPositionInLine = offending.getCharPositionInLine() + return "line \(line):\(charPositionInLine)" } open func addErrorListener(_ listener: ANTLRErrorListener) { - _listeners.append(listener) } @@ -237,16 +178,13 @@ open class Recognizer { _listeners = _listeners.filter() { $0 !== listener } - - // _listeners.removeObject(listener); } open func removeErrorListeners() { _listeners.removeAll() } - - open func getErrorListeners() -> Array { + open func getErrorListeners() -> [ANTLRErrorListener] { return _listeners } @@ -260,7 +198,7 @@ open class Recognizer { return true } - open func precpred(_ localctx: RuleContext?, _ precedence: Int) throws -> Bool { + open func precpred(_ localctx: RuleContext?, _ precedence: Int) -> Bool { return true } @@ -285,22 +223,18 @@ open class Recognizer { } open func getInputStream() -> IntStream? { - RuntimeException(#function + "Must be overridden") - fatalError() + fatalError(#function + " must be overridden") } open func setInputStream(_ input: IntStream) throws { - RuntimeException(#function + "Must be overridden") - + fatalError(#function + " must be overridden") } open func getTokenFactory() -> TokenFactory { - RuntimeException(#function + "Must be overridden") - fatalError() + fatalError(#function + " must be overridden") } open func setTokenFactory(_ input: TokenFactory) { - RuntimeException(#function + "Must be overridden") - + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/RuleContext.swift b/runtime/Swift/Sources/Antlr4/RuleContext.swift index a05b43257..a44ce5373 100644 --- a/runtime/Swift/Sources/Antlr4/RuleContext.swift +++ b/runtime/Swift/Sources/Antlr4/RuleContext.swift @@ -56,17 +56,18 @@ /// open class RuleContext: RuleNode { - public static let EMPTY: ParserRuleContext = ParserRuleContext() + public static let EMPTY = ParserRuleContext() /// What context invoked this rule? - public var parent: RuleContext? + public weak var parent: RuleContext? /// What state invoked the rule associated with this context? /// The "return address" is the followState of invokingState /// If parent is null, this should be -1 this context object represents /// the start rule. /// - public var invokingState: Int = -1 + public var invokingState = -1 + override public init() { super.init() @@ -79,7 +80,7 @@ open class RuleContext: RuleNode { } open func depth() -> Int { - var n: Int = 0 + var n = 0 var p: RuleContext? = self while let pWrap = p { p = pWrap.parent @@ -131,7 +132,7 @@ open class RuleContext: RuleNode { return "" } - let builder: StringBuilder = StringBuilder() + let builder = StringBuilder() for i in 0.. Future { -// var ruleNames : Array = parser != nil ? Arrays.asList(parser.getRuleNames()) : null; -// return inspect(ruleNames); -// } -// -// public func inspect(ruleNames : Array) -> Future { -// var viewer : TreeViewer = TreeViewer(ruleNames, self); -// return viewer.open(); -// } -// -// /// Save this tree in a postscript file -// public func save(parser : Parser, _ fileName : String) -// throws; IOException, PrintException -// { -// var ruleNames : Array = parser != nil ? Arrays.asList(parser.getRuleNames()) : null; -// save(ruleNames, fileName); -// } -// -// /// Save this tree in a postscript file using a particular font name and size -// public func save(parser : Parser, _ fileName : String, -// _ fontName : String, _ fontSize : Int) -// throws; IOException -// { -// var ruleNames : Array = parser != nil ? Arrays.asList(parser.getRuleNames()) : null; -// save(ruleNames, fileName, fontName, fontSize); -// } -// -// /// Save this tree in a postscript file -// public func save(ruleNames : Array, _ fileName : String) -// throws; IOException, PrintException -// { -// Trees.writePS(self, ruleNames, fileName); -// } -// -// /// Save this tree in a postscript file using a particular font name and size -// public func save(ruleNames : Array, _ fileName : String, -// _ fontName : String, _ fontSize : Int) -// throws; IOException -// { -// Trees.writePS(self, ruleNames, fileName, fontName, fontSize); -// } - /// Print out a whole tree, not just a node, in LISP format /// (root child1 .. childN). Print just a node if this is a leaf. /// We have to know the recognizer so we can get rule names. - /// - + /// open override func toStringTree(_ recog: Parser) -> String { return Trees.toStringTree(self, recog) } @@ -214,19 +171,16 @@ 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: Array?) -> String { + public func toStringTree(_ ruleNames: [String]?) -> String { return Trees.toStringTree(self, ruleNames) } - open override func toStringTree() -> String { - let info: Array? = nil - return toStringTree(info) + return toStringTree(nil) } + open override var description: String { - let p1: Array? = nil - let p2: RuleContext? = nil - return toString(p1, p2) + return toString(nil, nil) } open override var debugDescription: String { @@ -237,31 +191,31 @@ open class RuleContext: RuleNode { return toString(recog, ParserRuleContext.EMPTY) } - public final func toString(_ ruleNames: Array) -> String { + public final func toString(_ ruleNames: [String]) -> String { return toString(ruleNames, nil) } // recog null unless ParserRuleContext, in which case we use subclass toString(...) open func toString(_ recog: Recognizer?, _ stop: RuleContext) -> String { - let ruleNames: [String]? = recog != nil ? recog!.getRuleNames() : nil - let ruleNamesList: Array? = ruleNames ?? nil - return toString(ruleNamesList, stop) + let ruleNames = recog?.getRuleNames() + return toString(ruleNames, stop) } - open func toString(_ ruleNames: Array?, _ stop: RuleContext?) -> String { - let buf: StringBuilder = StringBuilder() + open func toString(_ ruleNames: [String]?, _ stop: RuleContext?) -> String { + let buf = StringBuilder() var p: RuleContext? = self buf.append("[") - while let pWrap = p , pWrap !== stop { - if ruleNames == nil { + while let pWrap = p, pWrap !== stop { + if let ruleNames = ruleNames { + let ruleIndex = pWrap.getRuleIndex() + let ruleIndexInRange = (ruleIndex >= 0 && ruleIndex < ruleNames.count) + let ruleName = (ruleIndexInRange ? ruleNames[ruleIndex] : String(ruleIndex)) + buf.append(ruleName) + } + else { if !pWrap.isEmpty() { buf.append(pWrap.invokingState) } - } else { - let ruleIndex: Int = pWrap.getRuleIndex() - let ruleIndexInRange: Bool = ruleIndex >= 0 && ruleIndex < ruleNames!.count - let ruleName: String = ruleIndexInRange ? ruleNames![ruleIndex] : String(ruleIndex) - buf.append(ruleName) } if pWrap.parent != nil && (ruleNames != nil || !pWrap.parent!.isEmpty()) { diff --git a/runtime/Swift/Sources/Antlr4/Token.swift b/runtime/Swift/Sources/Antlr4/Token.swift index a249adc2a..264318ddd 100644 --- a/runtime/Swift/Sources/Antlr4/Token.swift +++ b/runtime/Swift/Sources/Antlr4/Token.swift @@ -98,5 +98,7 @@ public protocol Token: class, CustomStringConvertible { /// func getInputStream() -> CharStream? + func getTokenSourceAndStream() -> TokenSourceAndStream + var visited: Bool { get set } } diff --git a/runtime/Swift/Sources/Antlr4/TokenFactory.swift b/runtime/Swift/Sources/Antlr4/TokenFactory.swift index c7ce67cee..63fa74b3c 100644 --- a/runtime/Swift/Sources/Antlr4/TokenFactory.swift +++ b/runtime/Swift/Sources/Antlr4/TokenFactory.swift @@ -8,7 +8,6 @@ /// the error handling strategy (to create missing tokens). Notifying the parser /// of a new factory means that it notifies it's token source and error strategy. /// - public protocol TokenFactory { //typealias Symbol @@ -16,10 +15,33 @@ public protocol TokenFactory { /// error handling strategy. If text!=null, than the start and stop positions /// are wiped to -1 in the text override is set in the CommonToken. /// - func create(_ source: (TokenSource?, CharStream?), _ type: Int, _ text: String?, + func create(_ source: TokenSourceAndStream, _ type: Int, _ text: String?, _ channel: Int, _ start: Int, _ stop: Int, _ line: Int, _ charPositionInLine: Int) -> Token /// Generically useful func create(_ type: Int, _ text: String) -> Token } + + +/** + Holds the references to the TokenSource and CharStream used to create a Token. + These are together to reduce memory footprint by having one instance of + TokenSourceAndStream shared across many tokens. The references here are weak + to avoid retain cycles. + */ +public class TokenSourceAndStream { + /// + /// An empty TokenSourceAndStream which is used as the default value of + /// _#source_ for tokens that do not have a source. + /// + public static let EMPTY = TokenSourceAndStream() + + public weak var tokenSource: TokenSource? + public weak var stream: CharStream? + + public init(_ tokenSource: TokenSource? = nil, _ stream: CharStream? = nil) { + self.tokenSource = tokenSource + self.stream = stream + } +} diff --git a/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift b/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift new file mode 100644 index 000000000..7ef18facb --- /dev/null +++ b/runtime/Swift/Sources/Antlr4/UnbufferedCharStream.swift @@ -0,0 +1,389 @@ +/* + * 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 + + +/** Do not buffer up the entire char stream. It does keep a small buffer + * for efficiency and also buffers while a mark exists (set by the + * lookahead prediction in parser). "Unbuffered" here refers to fact + * that it doesn't buffer all data, not that's it's on demand loading of char. + * + * Before 4.7, this class used the default environment encoding to convert + * bytes to UTF-16, and held the UTF-16 bytes in the buffer as chars. + * + * As of 4.7, the class uses UTF-8 by default, and the buffer holds Unicode + * code points in the buffer as ints. + */ +open class UnbufferedCharStream: CharStream { + private let bufferSize: Int + + /** + * A moving window buffer of the data being scanned. While there's a marker, + * we keep adding to buffer. Otherwise, {@link #consume consume()} resets so + * we start filling at index 0 again. + */ + internal var data: [Int] + + /** + * The number of characters currently in {@link #data data}. + * + *

This is not the buffer capacity, that's {@code data.length}.

+ */ + internal var n = 0 + + /** + * 0..n-1 index into {@link #data data} of next character. + * + *

The {@code LA(1)} character is {@code data[p]}. If {@code p == n}, we are + * out of buffered characters.

+ */ + internal var p = 0 + + /** + * Count up with {@link #mark mark()} and down with + * {@link #release release()}. When we {@code release()} the last mark, + * {@code numMarkers} reaches 0 and we reset the buffer. Copy + * {@code data[p]..data[n-1]} to {@code data[0]..data[(n-1)-p]}. + */ + internal var numMarkers = 0 + + /** + * This is the {@code LA(-1)} character for the current position. + */ + internal var lastChar = -1 + + /** + * When {@code numMarkers > 0}, this is the {@code LA(-1)} character for the + * first character in {@link #data data}. Otherwise, this is unspecified. + */ + internal var lastCharBufferStart = 0 + + /** + * Absolute character index. It's the index of the character about to be + * read via {@code LA(1)}. Goes from 0 to the number of characters in the + * entire stream, although the stream size is unknown before the end is + * reached. + */ + internal var currentCharIndex = 0 + + internal let input: InputStream + private var unicodeIterator: UnicodeScalarStreamIterator + + + /** The name or source of this char stream. */ + public var name: String = "" + + public init(_ input: InputStream, _ bufferSize: Int = 256) { + self.input = input + self.bufferSize = bufferSize + self.data = [Int](repeating: 0, count: bufferSize) + let si = UInt8StreamIterator(input) + self.unicodeIterator = UnicodeScalarStreamIterator(si) + } + + public func consume() throws { + if try LA(1) == CommonToken.EOF { + throw ANTLRError.illegalState(msg: "cannot consume EOF") + } + + // buf always has at least data[p==0] in this method due to ctor + lastChar = data[p] // track last char for LA(-1) + + if p == n - 1 && numMarkers == 0 { + n = 0 + p = -1 // p++ will leave this at 0 + lastCharBufferStart = lastChar + } + + p += 1 + currentCharIndex += 1 + sync(1) + } + + /** + * Make sure we have 'need' elements from current position {@link #p p}. + * Last valid {@code p} index is {@code data.length-1}. {@code p+need-1} is + * the char index 'need' elements ahead. If we need 1 element, + * {@code (p+1-1)==p} must be less than {@code data.length}. + */ + internal func sync(_ want: Int) { + let need = (p + want - 1) - n + 1 // how many more elements we need? + if need > 0 { + fill(need) + } + } + + /** + * Add {@code n} characters to the buffer. Returns the number of characters + * actually added to the buffer. If the return value is less than {@code n}, + * then EOF was reached before {@code n} characters could be added. + */ + @discardableResult internal func fill(_ toAdd: Int) -> Int { + for i in 0 ..< toAdd { + if n > 0 && data[n - 1] == CommonToken.EOF { + return i + } + + guard let c = nextChar() else { + return i + } + add(c) + } + + return n + } + + /** + * Override to provide different source of characters than + * {@link #input input}. + */ + internal func nextChar() -> Int? { + if let next = unicodeIterator.next() { + return Int(next.value) + } + else if unicodeIterator.hasErrorOccurred { + return nil + } + else { + return nil + } + } + + internal func add(_ c: Int) { + if n >= data.count { + data += [Int](repeating: 0, count: data.count) + } + data[n] = c + n += 1 + } + + public func LA(_ i: Int) throws -> Int { + if i == -1 { + return lastChar // special case + } + sync(i) + let index = p + i - 1 + if index < 0 { + throw ANTLRError.indexOutOfBounds(msg: "") + } + if index >= n { + return CommonToken.EOF + } + return data[index] + } + + /** + * Return a marker that we can release later. + * + *

The specific marker value used for this class allows for some level of + * protection against misuse where {@code seek()} is called on a mark or + * {@code release()} is called in the wrong order.

+ */ + public func mark() -> Int { + if numMarkers == 0 { + lastCharBufferStart = lastChar + } + + let mark = -numMarkers - 1 + numMarkers += 1 + return mark + } + + /** Decrement number of markers, resetting buffer if we hit 0. + * @param marker + */ + public func release(_ marker: Int) throws { + let expectedMark = -numMarkers + if marker != expectedMark { + preconditionFailure("release() called with an invalid marker.") + } + + numMarkers -= 1 + if numMarkers == 0 && p > 0 { + // release buffer when we can, but don't do unnecessary work + + // Copy data[p]..data[n-1] to data[0]..data[(n-1)-p], reset ptrs + // p is last valid char; move nothing if p==n as we have no valid char + if p == n { + if data.count != bufferSize { + data = [Int](repeating: 0, count: bufferSize) + } + n = 0 + } + else { + data = Array(data[p ..< n]) + n -= p + } + p = 0 + lastCharBufferStart = lastChar + } + } + + public func index() -> Int { + return currentCharIndex + } + + /** Seek to absolute character index, which might not be in the current + * sliding window. Move {@code p} to {@code index-bufferStartIndex}. + */ + public func seek(_ index_: Int) throws { + var index = index_ + + if index == currentCharIndex { + return + } + + if index > currentCharIndex { + sync(index - currentCharIndex) + index = min(index, getBufferStartIndex() + n - 1) + } + + // index == to bufferStartIndex should set p to 0 + let i = index - getBufferStartIndex() + if i < 0 { + throw ANTLRError.illegalArgument(msg: "cannot seek to negative index \(index)") + } + else if i >= n { + let si = getBufferStartIndex() + let ei = si + n + let msg = "seek to index outside buffer: \(index) not in \(si)..\(ei)" + throw ANTLRError.unsupportedOperation(msg: msg) + } + + p = i + currentCharIndex = index + if p == 0 { + lastChar = lastCharBufferStart + } + else { + lastChar = data[p - 1] + } + } + + public func size() -> Int { + preconditionFailure("Unbuffered stream cannot know its size") + } + + public func getSourceName() -> String { + return name + } + + public func getText(_ interval: Interval) throws -> String { + if interval.a < 0 || interval.b < interval.a - 1 { + throw ANTLRError.illegalArgument(msg: "invalid interval") + } + + let bufferStartIndex = getBufferStartIndex() + if n > 0 && + data[n - 1] == CommonToken.EOF && + interval.a + interval.length() > bufferStartIndex + n { + throw ANTLRError.illegalArgument(msg: "the interval extends past the end of the stream") + } + + if interval.a < bufferStartIndex || interval.b >= bufferStartIndex + n { + let msg = "interval \(interval) outside buffer: \(bufferStartIndex)...\(bufferStartIndex + n - 1)" + throw ANTLRError.unsupportedOperation(msg: msg) + } + + if interval.b < interval.a { + // The EOF token. + return "" + } + + // convert from absolute to local index + let i = interval.a - bufferStartIndex + let j = interval.b - bufferStartIndex + + // Convert from Int codepoints to a String. + let codepoints = data[i ... j].map { Character(Unicode.Scalar($0)!) } + return String(codepoints) + } + + internal func getBufferStartIndex() -> Int { + return currentCharIndex - p + } +} + + +fileprivate struct UInt8StreamIterator: IteratorProtocol { + private static let bufferSize = 1024 + + private let stream: InputStream + private var buffer = [UInt8](repeating: 0, count: UInt8StreamIterator.bufferSize) + private var buffGen: IndexingIterator> + + var hasErrorOccurred = false + + + init(_ stream: InputStream) { + self.stream = stream + self.buffGen = buffer[0..<0].makeIterator() + } + + mutating func next() -> UInt8? { + if let result = buffGen.next() { + return result + } + + if hasErrorOccurred { + return nil + } + + switch stream.streamStatus { + 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) + if count < 0 { + hasErrorOccurred = true + return nil + } + else if count == 0 { + return nil + } + + buffGen = buffer.prefix(count).makeIterator() + return buffGen.next() + } +} + + +fileprivate struct UnicodeScalarStreamIterator: IteratorProtocol { + private var streamIterator: UInt8StreamIterator + private var codec = Unicode.UTF8() + + var hasErrorOccurred = false + + init(_ streamIterator: UInt8StreamIterator) { + self.streamIterator = streamIterator + } + + mutating func next() -> Unicode.Scalar? { + if streamIterator.hasErrorOccurred { + hasErrorOccurred = true + return nil + } + + switch codec.decode(&streamIterator) { + case .scalarValue(let scalar): + return scalar + case .emptyInput: + return nil + case .error: + hasErrorOccurred = true + return nil + } + } +} diff --git a/runtime/Swift/Sources/Antlr4/UnbufferedTokenStream.swift b/runtime/Swift/Sources/Antlr4/UnbufferedTokenStream.swift index f9622e404..da1c8476a 100644 --- a/runtime/Swift/Sources/Antlr4/UnbufferedTokenStream.swift +++ b/runtime/Swift/Sources/Antlr4/UnbufferedTokenStream.swift @@ -4,7 +4,7 @@ */ -public class UnbufferedTokenStream: TokenStream { +public class UnbufferedTokenStream: TokenStream { internal var tokenSource: TokenSource /// @@ -274,10 +274,7 @@ public class UnbufferedTokenStream: TokenStream { public func size() -> Int { - - RuntimeException("Unbuffered stream cannot know its size") - fatalError() - + fatalError("Unbuffered stream cannot know its size") } diff --git a/runtime/Swift/Sources/Antlr4/atn/ATN.swift b/runtime/Swift/Sources/Antlr4/atn/ATN.swift index 0ed7971d5..bdfc938cd 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATN.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATN.swift @@ -73,9 +73,9 @@ public class ATN { /// the rule surrounding `s`. In other words, the set will be /// restricted to tokens reachable staying within `s`'s rule. /// - public func nextTokens(_ s: ATNState, _ ctx: RuleContext?)throws -> IntervalSet { - let anal: LL1Analyzer = LL1Analyzer(self) - let next: IntervalSet = try anal.LOOK(s, ctx) + public func nextTokens(_ s: ATNState, _ ctx: RuleContext?) -> IntervalSet { + let anal = LL1Analyzer(self) + let next = anal.LOOK(s, ctx) return next } @@ -84,14 +84,14 @@ public class ATN { /// staying in same rule. _org.antlr.v4.runtime.Token#EPSILON_ is in set if we reach end of /// rule. /// - public func nextTokens(_ s: ATNState) throws -> IntervalSet { + public func nextTokens(_ s: ATNState) -> IntervalSet { if let nextTokenWithinRule = s.nextTokenWithinRule { return nextTokenWithinRule } - let intervalSet = try nextTokens(s, nil) + let intervalSet = nextTokens(s, nil) s.nextTokenWithinRule = intervalSet - try intervalSet.setReadonly(true) + try! intervalSet.setReadonly(true) return intervalSet } @@ -151,27 +151,27 @@ public class ATN { } var ctx: RuleContext? = context - let s: ATNState = states[stateNumber]! - var following: IntervalSet = try nextTokens(s) + let s = states[stateNumber]! + var following = nextTokens(s) if !following.contains(CommonToken.EPSILON) { return following } - let expected: IntervalSet = try IntervalSet() - try expected.addAll(following) - try expected.remove(CommonToken.EPSILON) + let expected = IntervalSet() + try! expected.addAll(following) + try! expected.remove(CommonToken.EPSILON) - while let ctxWrap = ctx , ctxWrap.invokingState >= 0 && following.contains(CommonToken.EPSILON) { - let invokingState: ATNState = states[ctxWrap.invokingState]! - let rt: RuleTransition = invokingState.transition(0) as! RuleTransition - following = try nextTokens(rt.followState) - try expected.addAll(following) - try expected.remove(CommonToken.EPSILON) + while let ctxWrap = ctx, ctxWrap.invokingState >= 0 && following.contains(CommonToken.EPSILON) { + let invokingState = states[ctxWrap.invokingState]! + let rt = invokingState.transition(0) as! RuleTransition + following = nextTokens(rt.followState) + try! expected.addAll(following) + try! expected.remove(CommonToken.EPSILON) ctx = ctxWrap.parent } if following.contains(CommonToken.EPSILON) { - try expected.add(CommonToken.EOF) + try! expected.add(CommonToken.EOF) } return expected diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift b/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift index 75bff30e4..f91854531 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNConfig.swift @@ -150,13 +150,12 @@ public class ATNConfig: Hashable, CustomStringConvertible { /// public var hashValue: Int { - var hashCode: Int = MurmurHash.initialize(7) + var hashCode = MurmurHash.initialize(7) hashCode = MurmurHash.update(hashCode, state.stateNumber) hashCode = MurmurHash.update(hashCode, alt) hashCode = MurmurHash.update(hashCode, context) hashCode = MurmurHash.update(hashCode, semanticContext) - hashCode = MurmurHash.finish(hashCode, 4) - return hashCode + return MurmurHash.finish(hashCode, 4) } diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift b/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift index 803d9c369..3c52bcd14 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNConfigSet.swift @@ -27,7 +27,7 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// fields; in particular, conflictingAlts is set after /// we've made this readonly. /// - internal final var readonly: Bool = false + internal final var readonly = false /// /// All configs but hashed by (s, i, _, pi) not including context. Wiped out @@ -38,11 +38,11 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// /// Track the elements as they are added to the set; supports get(i) /// - public final var configs: Array = Array() + public final 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 final var uniqueAlt: Int = 0 + public final var uniqueAlt = 0 //TODO no default /// /// Currently this is only used when we detect SLL conflict; this does @@ -54,9 +54,9 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { // Used in parser and lexer. In lexer, it indicates we hit a pred // while computing a closure operation. Don't make a DFA state from this. - public final var hasSemanticContext: Bool = false + public final var hasSemanticContext = false //TODO no default - public final var dipsIntoOuterContext: Bool = false + public final var dipsIntoOuterContext = false //TODO no default /// @@ -66,7 +66,7 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// public final var fullCtx: Bool - private var cachedHashCode: Int = -1 + private var cachedHashCode = -1 public init(_ fullCtx: Bool) { configLookup = LookupDictionary() @@ -76,9 +76,9 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { self.init(true) } - public convenience init(_ old: ATNConfigSet) throws { + public convenience init(_ old: ATNConfigSet) { self.init(old.fullCtx) - try addAll(old) + try! addAll(old) self.uniqueAlt = old.uniqueAlt self.conflictingAlts = old.conflictingAlts self.hasSemanticContext = old.hasSemanticContext @@ -108,7 +108,6 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { _ mergeCache: inout DoubleKeyMap?) throws -> Bool { if readonly { throw ANTLRError.illegalState(msg: "This set is readonly") - } if config.semanticContext != SemanticContext.NONE { @@ -125,10 +124,9 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { return true } // a previous (s,i,pi,_), merge with it and save result - let rootIsWildcard: Bool = !fullCtx + let rootIsWildcard = !fullCtx - let merged: PredictionContext = - PredictionContext.merge(existing.context!, config.context!, rootIsWildcard, &mergeCache) + let merged = PredictionContext.merge(existing.context!, config.context!, rootIsWildcard, &mergeCache) // no need to check for existing.context, config.context in cache // since only way to create new graphs is "call rule" and here. We @@ -154,16 +152,14 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// /// Return a List holding list of configs /// - public final func elements() -> Array { + public final func elements() -> [ATNConfig] { return configs } public final func getStates() -> Set { - - let length = configs.count - var states: Set = Set(minimumCapacity: length) - for i in 0..(minimumCapacity: configs.count) + for config in configs { + states.insert(config.state) } return states } @@ -176,21 +172,19 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// /// - since: 4.3 /// - public final func getAlts() throws -> BitSet { - let alts: BitSet = BitSet() - let length = configs.count - for i in 0.. BitSet { + let alts = BitSet() + for config in configs { + try! alts.set(config.alt) } return alts } - public final func getPredicates() -> Array { - var preds: Array = Array() - let length = configs.count - for i in 0.. [SemanticContext] { + var preds = [SemanticContext]() + for config in configs { + if config.semanticContext != SemanticContext.NONE { + preds.append(config.semanticContext) } } return preds @@ -203,22 +197,20 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { public final func optimizeConfigs(_ interpreter: ATNSimulator) throws { if readonly { throw ANTLRError.illegalState(msg: "This set is readonly") - } if configLookup.isEmpty { return } - let length = configs.count - for i in 0.. Bool { - for c: ATNConfig in coll.configs { - try add(c) + for c in coll.configs { + try add(c) } return false } @@ -266,7 +258,6 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { public final func clear() throws { if readonly { throw ANTLRError.illegalState(msg: "This set is readonly") - } configs.removeAll() cachedHashCode = -1 @@ -284,7 +275,7 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { } public var description: String { - let buf: StringBuilder = StringBuilder() + let buf = StringBuilder() buf.append(elements().map({ $0.description })) if hasSemanticContext { buf.append(",hasSemanticContext=") @@ -313,18 +304,15 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// return configLookup.toArray(a); /// private final func configHash(_ stateNumber: Int,_ context: PredictionContext?) -> Int{ - - var hashCode: Int = MurmurHash.initialize(7) + var hashCode = MurmurHash.initialize(7) hashCode = MurmurHash.update(hashCode, stateNumber) hashCode = MurmurHash.update(hashCode, context) - hashCode = MurmurHash.finish(hashCode, 2) - - return hashCode - + return MurmurHash.finish(hashCode, 2) } - public final func getConflictingAltSubsets() throws -> Array { + + public final func getConflictingAltSubsets() -> [BitSet] { let length = configs.count - let configToAlts: HashMap = HashMap(count: length) + let configToAlts = HashMap(count: length) for i in 0.. HashMap { + + public final func getStateToAltMap() -> HashMap { let length = configs.count - let m: HashMap = HashMap(count: length) //minimumCapacity: length) + let m = HashMap(count: length) for i in 0.. Set? { - var alts: Set = Set() - let length = configs.count - for i in 0..() + for config in configs { + alts.insert(config.alt) + } return alts } //for DiagnosticErrorListener - public final func getAltBitSet() throws -> BitSet { - let result: BitSet = BitSet() - let length = configs.count - for i in 0.. BitSet { + let result = BitSet() + for config in configs { + try! result.set(config.alt) } - return result } //LexerATNSimulator - public final var firstConfigWithRuleStopState: ATNConfig? { - let length = configs.count - for i in 0.. Int { - var alt: Int = ATN.INVALID_ALT_NUMBER - let length = configs.count - for i in 0.. Int { + var alt = ATN.INVALID_ALT_NUMBER + for config in configs { if alt == ATN.INVALID_ALT_NUMBER { - alt = configs[i].alt // found first alt - } else { - if configs[i].alt != alt { - return ATN.INVALID_ALT_NUMBER - } + alt = config.alt // found first alt + } else if config.alt != alt { + return ATN.INVALID_ALT_NUMBER } } return alt } - public final func removeAllConfigsNotInRuleStopState(_ mergeCache: inout DoubleKeyMap?,_ lookToEndOfRule: Bool,_ atn: ATN) throws -> ATNConfigSet { + + public final func removeAllConfigsNotInRuleStopState(_ mergeCache: inout DoubleKeyMap?,_ lookToEndOfRule: Bool,_ atn: ATN) -> ATNConfigSet { if PredictionMode.allConfigsInRuleStopStates(self) { return self } - let result: ATNConfigSet = ATNConfigSet(fullCtx) - let length = configs.count - for i in 0..?,_ parser: Parser,_ _outerContext: ParserRuleContext!) throws -> ATNConfigSet { - let configSet: ATNConfigSet = ATNConfigSet(fullCtx) - let length = configs.count - let statesFromAlt1: HashMap = HashMap(count: length) - for i in 0..(count: configs.count) + for config in configs { // handle alt 1 first - if configs[i].alt != 1 { + if config.alt != 1 { continue } - let updatedContext: SemanticContext? = try configs[i].semanticContext.evalPrecedence(parser, _outerContext) + let updatedContext = try config.semanticContext.evalPrecedence(parser, _outerContext) if updatedContext == nil { // the configuration was eliminated continue } - statesFromAlt1[configs[i].state.stateNumber] = configs[i].context - if updatedContext != configs[i].semanticContext { - try configSet.add(ATNConfig(configs[i], updatedContext!), &mergeCache) + statesFromAlt1[config.state.stateNumber] = config.context + if updatedContext != config.semanticContext { + try! configSet.add(ATNConfig(config, updatedContext!), &mergeCache) } else { - try configSet.add(configs[i],&mergeCache) + try! configSet.add(config, &mergeCache) } } - for i in 0..1 /// (basically a graph subtraction algorithm). /// - let context: PredictionContext? = statesFromAlt1[configs[i].state.stateNumber] - if context != nil && context == configs[i].context { + let context = statesFromAlt1[config.state.stateNumber] + if context != nil && context == config.context { // eliminated continue } } - try configSet.add(configs[i], &mergeCache) + try! configSet.add(config, &mergeCache) } return configSet } - internal func getPredsForAmbigAlts(_ ambigAlts: BitSet, - _ nalts: Int) throws -> [SemanticContext?]? { - var altToPred: [SemanticContext?]? = [SemanticContext?](repeating: nil, count: nalts + 1) //new SemanticContext[nalts + 1]; - let length = configs.count - for i in 0.. [SemanticContext?]? { + var altToPred = [SemanticContext?](repeating: nil, count: nalts + 1) + for config in configs { + if try! ambigAlts.get(config.alt) { + altToPred[config.alt] = SemanticContext.or(altToPred[config.alt], config.semanticContext) } - var nPredAlts: Int = 0 - for i in 1...nalts { - if altToPred![i] == nil { - altToPred![i] = SemanticContext.NONE - } else { - if altToPred![i] != SemanticContext.NONE { - nPredAlts += 1 - } - } + } + var nPredAlts = 0 + for i in 1...nalts { + if altToPred[i] == nil { + altToPred[i] = SemanticContext.NONE } - - // // Optimize away p||p and p&&p TODO: optimize() was a no-op - // for (int i = 0; i < altToPred.length; i++) { - // altToPred[i] = altToPred[i].optimize(); - // } - - // nonambig alts are null in altToPred - if nPredAlts == 0 { - altToPred = nil + else if altToPred[i] != SemanticContext.NONE { + nPredAlts += 1 } + } - return altToPred + // // Optimize away p||p and p&&p TODO: optimize() was a no-op + // for (int i = 0; i < altToPred.length; i++) { + // altToPred[i] = altToPred[i].optimize(); + // } + // nonambig alts are null in altToPred + return (nPredAlts == 0 ? nil : altToPred) } - public final func getAltThatFinishedDecisionEntryRule() throws -> Int { - let alts: IntervalSet = try IntervalSet() - let length = configs.count - for i in 0.. 0 || - (configs[i].state is RuleStopState && - configs[i].context!.hasEmptyPath()) { - try alts.add(configs[i].alt) + + public final func getAltThatFinishedDecisionEntryRule() -> Int { + let alts = IntervalSet() + for config in configs { + if config.getOuterContextDepth() > 0 || + (config.state is RuleStopState && + config.context!.hasEmptyPath()) { + try! alts.add(config.alt) } } if alts.size() == 0 { @@ -548,39 +520,36 @@ public class ATNConfigSet: Hashable, CustomStringConvertible { /// public final func splitAccordingToSemanticValidity( _ outerContext: ParserRuleContext, - _ evalSemanticContext:( SemanticContext,ParserRuleContext,Int,Bool) throws -> Bool) throws -> (ATNConfigSet, ATNConfigSet) { - let succeeded: ATNConfigSet = ATNConfigSet(fullCtx) - let failed: ATNConfigSet = ATNConfigSet(fullCtx) - let length = configs.count - for i in 0.. Bool) rethrows -> (ATNConfigSet, ATNConfigSet) { + let succeeded = ATNConfigSet(fullCtx) + let failed = ATNConfigSet(fullCtx) + for config in configs { + if config.semanticContext != SemanticContext.NONE { + let predicateEvaluationResult = try evalSemanticContext(config.semanticContext, outerContext, config.alt,fullCtx) + if predicateEvaluationResult { + try! succeeded.add(config) } else { - try succeeded.add(configs[i]) + try! failed.add(config) } + } else { + try! succeeded.add(config) } - return (succeeded, failed) + } + return (succeeded, failed) } - //public enum PredictionMode - public final func dupConfigsWithoutSemanticPredicates() throws -> ATNConfigSet { - let dup: ATNConfigSet = ATNConfigSet() - let length = configs.count - for i in 0.. ATNConfigSet { + let dup = ATNConfigSet() + for config in configs { + let c = ATNConfig(config, SemanticContext.NONE) + try! dup.add(c) } return dup } + public final var hasConfigInRuleStopState: Bool { - let length = configs.count - for i in 0.. = Array<(LoopEndState, Int)>() - var endStateNumbers: Array<(BlockStartState, Int)> = Array<(BlockStartState, Int)>() - let nstates: Int = toInt(data[p]) + var loopBackStateNumbers = [(LoopEndState, Int)]() + var endStateNumbers = [(BlockStartState, Int)]() + let nstates = toInt(data[p]) p += 1 for _ in 0.. = Array() // First, deserialize sets with 16-bit arguments <= U+FFFF. - try readSets(data, &p, &sets, readUnicodeInt) + readSets(data, &p, &sets, readUnicodeInt) // Next, if the ATN was serialized with the Unicode SMP feature, // deserialize sets with 32-bit arguments <= U+10FFFF. if isFeatureSupported(ATNDeserializer.ADDED_UNICODE_SMP, uuid) { - try readSets(data, &p, &sets, readUnicodeInt32) + readSets(data, &p, &sets, readUnicodeInt32) } // @@ -548,23 +544,23 @@ public class ATNDeserializer { return result } - private func readSets(_ data: [Character], _ p: inout Int, _ sets: inout Array, _ readUnicode: ([Character], inout Int) -> Int) throws { - let nsets: Int = toInt(data[p]) + private func readSets(_ data: [Character], _ p: inout Int, _ sets: inout Array, _ readUnicode: ([Character], inout Int) -> Int) { + let nsets = toInt(data[p]) p += 1 for _ in 0.. = Array() - let nsets: Int = dict["nsets"] as! Int + var sets = [IntervalSet]() + let nsets = dict["nsets"] as! Int let intervalSet = dict["IntervalSet"] as! [Dictionary] for i in 0..] + let intervalsBuilder = setBuilder["Intervals"] as! [[String : Any]] for j in 0..] + let lexerActionsBuilder = dict["lexerActions"] as! [[String : Any]] if supportsLexerActions { - atn.lexerActions = [LexerAction](repeating: LexerAction(), count: lexerActionsBuilder.count) //[toInt(data[p++])]; + atn.lexerActions = [LexerAction](repeating: LexerAction(), count: lexerActionsBuilder.count) let length = atn.lexerActions.count for i in 0.. = Array() - for state: ATNState? in atn.states { + var legacyLexerActions = [LexerAction]() + for state in atn.states { if let state = state { let length = state.getNumberOfTransitions() for i in 0.. 0 { - let transition: Transition = atn.ruleToStartState[i].removeTransition(atn.ruleToStartState[i].getNumberOfTransitions() - 1) + let transition = atn.ruleToStartState[i].removeTransition(atn.ruleToStartState[i].getNumberOfTransitions() - 1) bypassStart.addTransition(transition) } @@ -987,7 +973,7 @@ public class ATNDeserializer { atn.ruleToStartState[i].addTransition(EpsilonTransition(bypassStart)) bypassStop.addTransition(EpsilonTransition(endState!)) - let matchState: ATNState = BasicState() + let matchState = BasicState() atn.addState(matchState) matchState.addTransition(AtomTransition(bypassStop, atn.ruleToTokenType[i])) bypassStart.addTransition(EpsilonTransition(matchState)) @@ -1011,7 +997,7 @@ public class ATNDeserializer { /// - parameter atn: The ATN. /// internal func markPrecedenceDecisions(_ atn: ATN) { - for state: ATNState? in atn.states { + for state in atn.states { if let state = state as? StarLoopEntryState { /// @@ -1021,7 +1007,7 @@ public class ATNDeserializer { /// if let stateRuleIndex = state.ruleIndex { if atn.ruleToStartState[stateRuleIndex].isPrecedenceRule { - let maybeLoopEndState: ATNState = state.transition(state.getNumberOfTransitions() - 1).target + let maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target if maybeLoopEndState is LoopEndState { if maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target is RuleStopState { state.precedenceRuleDecision = true @@ -1035,7 +1021,7 @@ public class ATNDeserializer { internal func verifyATN(_ atn: ATN) throws { // verify assumptions - for state: ATNState? in atn.states { + for state in atn.states { guard let state = state else { continue } @@ -1084,8 +1070,7 @@ public class ATNDeserializer { try checkCondition((state as! BlockEndState).startState != nil) } - if state is DecisionState { - let decisionState: DecisionState = state as! DecisionState + if let decisionState = state as? DecisionState { try checkCondition(decisionState.getNumberOfTransitions() <= 1 || decisionState.decision >= 0) } else { try checkCondition(state.getNumberOfTransitions() <= 1 || state is RuleStopState) @@ -1109,7 +1094,7 @@ public class ATNDeserializer { _ type: Int, _ src: Int, _ trg: Int, _ arg1: Int, _ arg2: Int, _ arg3: Int, _ sets: Array) throws -> Transition { - let target: ATNState = atn.states[trg]! + let target = atn.states[trg]! switch type { case Transition.EPSILON: return EpsilonTransition(target) case Transition.RANGE: @@ -1119,10 +1104,10 @@ public class ATNDeserializer { return RangeTransition(target, arg1, arg2) } case Transition.RULE: - let rt: RuleTransition = RuleTransition(atn.states[arg1] as! RuleStartState, arg2, arg3, target) + let rt = RuleTransition(atn.states[arg1] as! RuleStartState, arg2, arg3, target) return rt case Transition.PREDICATE: - let pt: PredicateTransition = PredicateTransition(target, arg1, arg2, arg3 != 0) + let pt = PredicateTransition(target, arg1, arg2, arg3 != 0) return pt case Transition.PRECEDENCE: return PrecedencePredicateTransition(target, arg1) @@ -1133,17 +1118,14 @@ public class ATNDeserializer { return AtomTransition(target, arg1) } case Transition.ACTION: - let a: ActionTransition = ActionTransition(target, arg1, arg2, arg3 != 0) - return a + return ActionTransition(target, arg1, arg2, arg3 != 0) + case Transition.SET: return SetTransition(target, sets[arg1]) case Transition.NOT_SET: return NotSetTransition(target, sets[arg1]) case Transition.WILDCARD: return WildcardTransition(target) default: throw ANTLRError.illegalState(msg: "The specified transition type is not valid.") - - } - } internal func stateFactory(_ type: Int, _ ruleIndex: Int) throws -> ATNState? { @@ -1197,12 +1179,6 @@ public class ATNDeserializer { case .type: return LexerTypeAction(data1) - - //default: - } - // let message : String = "The specified lexer action type \(type) is not valid." - // RuntimeException(message) - } } diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNSimulator.swift b/runtime/Swift/Sources/Antlr4/atn/ATNSimulator.swift index 036236938..39631229b 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNSimulator.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNSimulator.swift @@ -8,24 +8,7 @@ import Foundation open class ATNSimulator { - /// - /// - Use _org.antlr.v4.runtime.atn.ATNDeserializer#SERIALIZED_VERSION_ instead. - /// - public static let SERIALIZED_VERSION: Int = { - return ATNDeserializer.SERIALIZED_VERSION - }() - - - /// - /// This is the current serialized UUID. - /// - Use _org.antlr.v4.runtime.atn.ATNDeserializer#checkCondition(boolean)_ instead. - /// - public static let SERIALIZED_UUID: UUID = { - return (ATNDeserializer.SERIALIZED_UUID as UUID) - }() - - - /// + /// /// Must distinguish between missing edge and edge we know leads nowhere /// public static let ERROR: DFAState = { @@ -34,7 +17,7 @@ open class ATNSimulator { return error }() - public var atn: ATN + public let atn: ATN /// /// The context cache maps all PredictionContext objects that are equals() @@ -67,7 +50,7 @@ open class ATNSimulator { } open func reset() { - RuntimeException(" must overriden ") + fatalError(#function + " must be overridden") } /// @@ -96,55 +79,11 @@ open class ATNSimulator { //TODO: synced (sharedContextCache!) //synced (sharedContextCache!) { - let visited: HashMap = - HashMap() + let visited = HashMap() return PredictionContext.getCachedContext(context, sharedContextCache!, visited) - //} - } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#deserialize_ instead. - /// - public static func deserialize(_ data: [Character]) throws -> ATN { - return try ATNDeserializer().deserialize(data) - } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#checkCondition(boolean)_ instead. - /// - public static func checkCondition(_ condition: Bool) throws { - try ATNDeserializer().checkCondition(condition) - } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#checkCondition(boolean, String)_ instead. - /// - public static func checkCondition(_ condition: Bool, _ message: String) throws { - try ATNDeserializer().checkCondition(condition, message) - } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#toInt_ instead. - /// - public func toInt(_ c: Character) -> Int { - return toInt(c) - } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#toInt32_ instead. - /// - public func toInt32(_ data: [Character], _ offset: Int) -> Int { - return toInt32(data, offset) - } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#toLong_ instead. - /// - public func toLong(_ data: [Character], _ offset: Int) -> Int64 { - return toLong(data, offset) } public static func edgeFactory(_ atn: ATN, @@ -153,12 +92,4 @@ open class ATNSimulator { _ sets: Array) throws -> Transition { return try ATNDeserializer().edgeFactory(atn, type, src, trg, arg1, arg2, arg3, sets) } - - /// - /// - note: Use _org.antlr.v4.runtime.atn.ATNDeserializer#stateFactory_ instead. - /// - public static func stateFactory(_ type: Int, _ ruleIndex: Int) throws -> ATNState { - return try ATNDeserializer().stateFactory(type, ruleIndex)! - } - } diff --git a/runtime/Swift/Sources/Antlr4/atn/ATNState.swift b/runtime/Swift/Sources/Antlr4/atn/ATNState.swift index b26b7278e..88cf1a183 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ATNState.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ATNState.swift @@ -183,8 +183,7 @@ public class ATNState: Hashable, CustomStringConvertible { } public func getStateType() -> Int { - RuntimeException(#function + " must be overridden") - return 0 + fatalError(#function + " must be overridden") } public final func onlyHasEpsilonTransitions() -> Bool { diff --git a/runtime/Swift/Sources/Antlr4/atn/AtomTransition.swift b/runtime/Swift/Sources/Antlr4/atn/AtomTransition.swift index b1a689f9a..b51c7147e 100644 --- a/runtime/Swift/Sources/Antlr4/atn/AtomTransition.swift +++ b/runtime/Swift/Sources/Antlr4/atn/AtomTransition.swift @@ -27,8 +27,8 @@ public final class AtomTransition: Transition, CustomStringConvertible { } override - public func labelIntervalSet() throws -> IntervalSet? { - return try IntervalSet.of(label) + public func labelIntervalSet() -> IntervalSet? { + return IntervalSet(label) } override diff --git a/runtime/Swift/Sources/Antlr4/atn/LL1Analyzer.swift b/runtime/Swift/Sources/Antlr4/atn/LL1Analyzer.swift index d7bf695f2..3f594f234 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LL1Analyzer.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LL1Analyzer.swift @@ -28,18 +28,18 @@ public class LL1Analyzer { /// - parameter s: the ATN state /// - returns: the expected symbols for each outgoing transition of `s`. /// - public func getDecisionLookahead(_ s: ATNState?) throws -> [IntervalSet?]? { + public func getDecisionLookahead(_ s: ATNState?) -> [IntervalSet?]? { guard let s = s else { return nil } let length = s.getNumberOfTransitions() - var look: [IntervalSet?] = [IntervalSet?](repeating: nil, count: length) + var look = [IntervalSet?](repeating: nil, count: length) for alt in 0.. = Set() - let seeThruPreds: Bool = false // fail to get lookahead upon pred - try _LOOK(s.transition(alt).target, nil, PredictionContext.EMPTY, + look[alt] = IntervalSet() + var lookBusy = Set() + let seeThruPreds = false // fail to get lookahead upon pred + _LOOK(s.transition(alt).target, nil, PredictionContext.EMPTY, look[alt]!, &lookBusy, BitSet(), seeThruPreds, false) // Wipe out lookahead for this alternative if we found nothing // or we had a predicate when we !seeThruPreds @@ -66,8 +66,8 @@ public class LL1Analyzer { /// - returns: The set of tokens that can follow `s` in the ATN in the /// specified `ctx`. /// - public func LOOK(_ s: ATNState, _ ctx: RuleContext?) throws -> IntervalSet { - return try LOOK(s, nil, ctx) + public func LOOK(_ s: ATNState, _ ctx: RuleContext?) -> IntervalSet { + return LOOK(s, nil, ctx) } /// @@ -89,13 +89,12 @@ public class LL1Analyzer { /// specified `ctx`. /// - public func LOOK(_ s: ATNState, _ stopState: ATNState?, _ ctx: RuleContext?) throws -> IntervalSet { - let r: IntervalSet = try IntervalSet() - let seeThruPreds: Bool = true // ignore preds; get all lookahead - let lookContext: PredictionContext? = ctx != nil ? PredictionContext.fromRuleContext(s.atn!, ctx) : nil + public func LOOK(_ s: ATNState, _ stopState: ATNState?, _ ctx: RuleContext?) -> IntervalSet { + let r = IntervalSet() + let seeThruPreds = true // ignore preds; get all lookahead + let lookContext = ctx != nil ? PredictionContext.fromRuleContext(s.atn!, ctx) : nil var config = Set() - try _LOOK(s, stopState, lookContext, - r, &config, BitSet(), seeThruPreds, true) + _LOOK(s, stopState, lookContext, r, &config, BitSet(), seeThruPreds, true) return r } @@ -135,13 +134,10 @@ public class LL1Analyzer { _ look: IntervalSet, _ lookBusy: inout Set, _ calledRuleStack: BitSet, - _ seeThruPreds: Bool, _ addEOF: Bool) throws { + _ seeThruPreds: Bool, + _ addEOF: Bool) { // print ("_LOOK(\(s.stateNumber), ctx=\(ctx)"); - //TODO var c : ATNConfig = ATNConfig(s, 0, ctx); - if s.description == "273" { - var s = 0 - } - var c: ATNConfig = ATNConfig(s, 0, ctx) + let c = ATNConfig(s, 0, ctx) if lookBusy.contains(c) { return } else { @@ -150,12 +146,12 @@ public class LL1Analyzer { if s == stopState { guard let ctx = ctx else { - try look.add(CommonToken.EPSILON) + try! look.add(CommonToken.EPSILON) return } if ctx.isEmpty() && addEOF { - try look.add(CommonToken.EOF) + try! look.add(CommonToken.EOF) return } @@ -163,75 +159,64 @@ public class LL1Analyzer { if s is RuleStopState { guard let ctx = ctx else { - try look.add(CommonToken.EPSILON) + try! look.add(CommonToken.EPSILON) return } if ctx.isEmpty() && addEOF { - try look.add(CommonToken.EOF) + try! look.add(CommonToken.EOF) return } - if ctx != PredictionContext.EMPTY { // run thru all possible stack tops in ctx let length = ctx.size() for i in 0.. Int { LexerATNSimulator.match_calls += 1 self.mode = mode - var mark: Int = input.mark() + var mark = input.mark() do { self.startIndex = input.index() self.prevAccept.reset() - var dfa: DFA = decisionToDFA[mode] + var dfa = decisionToDFA[mode] defer { try! input.release(mark) } @@ -146,31 +146,30 @@ open class LexerATNSimulator: ATNSimulator { override open func clearDFA() { - for d in 0.. Int { - let startState: ATNState = atn.modeToStartState[mode] + let startState = atn.modeToStartState[mode] if LexerATNSimulator.debug { print("matchATN mode \(mode) start: \(startState)\n") } - let old_mode: Int = mode + let old_mode = mode - let s0_closure: ATNConfigSet = try computeStartState(input, startState) - let suppressEdge: Bool = s0_closure.hasSemanticContext + let s0_closure = try computeStartState(input, startState) + let suppressEdge = s0_closure.hasSemanticContext s0_closure.hasSemanticContext = false - let next: DFAState = addDFAState(s0_closure) + let next = addDFAState(s0_closure) if !suppressEdge { decisionToDFA[mode].s0 = next } - let predict: Int = try execATN(input, next) + let predict = try execATN(input, next) if LexerATNSimulator.debug { print("DFA after matchATN: \(decisionToDFA[old_mode].toLexerString())") @@ -190,14 +189,13 @@ open class LexerATNSimulator: ATNSimulator { captureSimState(prevAccept, input, ds0) } - var t: Int = try input.LA(1) + var t = try input.LA(1) - var s: DFAState = ds0 // s is current/from DFA state + var s = ds0 // s is current/from DFA state while true { // while more work if LexerATNSimulator.debug { - print("execATN loop starting closure: \(s.configs)\n") } @@ -268,7 +266,7 @@ open class LexerATNSimulator: ATNSimulator { return nil } - let target: DFAState? = s.edges[t - LexerATNSimulator.MIN_DFA_EDGE] + let target = s.edges[t - LexerATNSimulator.MIN_DFA_EDGE] if LexerATNSimulator.debug && target != nil { print("reuse state \(s.stateNumber) edge to \(target!.stateNumber)") } @@ -290,7 +288,7 @@ open class LexerATNSimulator: ATNSimulator { /// internal func computeTargetState(_ input: CharStream, _ s: DFAState, _ t: Int) throws -> DFAState { - let reach: ATNConfigSet = OrderedATNConfigSet() + let reach = OrderedATNConfigSet() // if we don't find an existing DFA state // Fill reach starting from closure, following t transitions @@ -316,7 +314,7 @@ open class LexerATNSimulator: ATNSimulator { internal func failOrAccept(_ prevAccept: SimState, _ input: CharStream, _ reach: ATNConfigSet, _ t: Int) throws -> Int { if let dfaState = prevAccept.dfaState { - let lexerActionExecutor: LexerActionExecutor? = dfaState.lexerActionExecutor + let lexerActionExecutor = dfaState.lexerActionExecutor try accept(input, lexerActionExecutor, startIndex, prevAccept.index, prevAccept.line, prevAccept.charPos) return dfaState.prediction @@ -325,8 +323,7 @@ open class LexerATNSimulator: ATNSimulator { if t == BufferedTokenStream.EOF && input.index() == startIndex { return CommonToken.EOF } - throw ANTLRException.recognition(e: LexerNoViableAltException(recog, input, startIndex, reach)) - + throw ANTLRException.recognition(e: LexerNoViableAltException(recog, input, startIndex, reach)) } } @@ -338,12 +335,12 @@ open class LexerATNSimulator: ATNSimulator { internal func getReachableConfigSet(_ input: CharStream, _ closureConfig: ATNConfigSet, _ reach: ATNConfigSet, _ t: Int) throws { // this is used to skip processing for configs which have a lower priority // than a config that already reached an accept state for the same rule - var skipAlt: Int = ATN.INVALID_ALT_NUMBER - for c: ATNConfig in closureConfig.configs { + var skipAlt = ATN.INVALID_ALT_NUMBER + for c in closureConfig.configs { guard let c = c as? LexerATNConfig else { continue } - let currentAltReachedAcceptState: Bool = c.alt == skipAlt + let currentAltReachedAcceptState = (c.alt == skipAlt) if currentAltReachedAcceptState && c.hasPassedThroughNonGreedyDecision() { continue } @@ -353,17 +350,17 @@ open class LexerATNSimulator: ATNSimulator { } - let n: Int = c.state.getNumberOfTransitions() + let n = c.state.getNumberOfTransitions() for ti in 0.. ATNConfigSet { - let initialContext: PredictionContext = PredictionContext.EMPTY - let configs: ATNConfigSet = OrderedATNConfigSet() + let initialContext = PredictionContext.EMPTY + let configs = OrderedATNConfigSet() let length = p.getNumberOfTransitions() for i in 0.. String { // index is first lookahead char, don't include. - return input.getText(Interval.of(startIndex, input.index() - 1)) + return try! input.getText(Interval.of(startIndex, input.index() - 1)) } public func getLine() -> Int { @@ -767,7 +756,7 @@ open class LexerATNSimulator: ATNSimulator { } public func consume(_ input: CharStream) throws { - let curChar: Int = try input.LA(1) + let curChar = try input.LA(1) if String(Character(integerLiteral: curChar)) == "\n" { line += 1 charPositionInLine = 0 diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerAction.swift index 1e619bd4b..99d604da5 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerAction.swift @@ -22,8 +22,7 @@ public class LexerAction: Hashable { /// - returns: The serialization type of the lexer action. /// public func getActionType() -> LexerActionType { - RuntimeException(" must overriden ") - fatalError() + fatalError(#function + " must be overridden") } @@ -42,8 +41,7 @@ public class LexerAction: Hashable { /// otherwise, `false`. /// public func isPositionDependent() -> Bool { - RuntimeException(" must overriden ") - fatalError() + fatalError(#function + " must be overridden") } /// @@ -55,12 +53,11 @@ public class LexerAction: Hashable { /// - parameter lexer: The lexer instance. /// public func execute(_ lexer: Lexer) throws { - RuntimeException(" must overriden ") + fatalError(#function + " must be overridden") } public var hashValue: Int { - RuntimeException(" must overriden ") - fatalError() + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerActionExecutor.swift b/runtime/Swift/Sources/Antlr4/atn/LexerActionExecutor.swift index 5079df2d7..e33e92e9b 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerActionExecutor.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerActionExecutor.swift @@ -36,7 +36,7 @@ public class LexerActionExecutor: Hashable { public init(_ lexerActions: [LexerAction]) { self.lexerActions = lexerActions - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() for lexerAction: LexerAction in lexerActions { hash = MurmurHash.update(hash, lexerAction) } diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerChannelAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerChannelAction.swift index 22cde7cf7..4d099f28c 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerChannelAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerChannelAction.swift @@ -65,7 +65,7 @@ public final class LexerChannelAction: LexerAction, CustomStringConvertible { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) hash = MurmurHash.update(hash, channel) return MurmurHash.finish(hash, 2) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerCustomAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerCustomAction.swift index 35e6afed0..3fe954236 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerCustomAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerCustomAction.swift @@ -94,7 +94,7 @@ public final class LexerCustomAction: LexerAction { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) hash = MurmurHash.update(hash, ruleIndex) hash = MurmurHash.update(hash, actionIndex) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerIndexedCustomAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerIndexedCustomAction.swift index 91bb6a50c..501b2e637 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerIndexedCustomAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerIndexedCustomAction.swift @@ -97,7 +97,7 @@ public final class LexerIndexedCustomAction: LexerAction { public override var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, offset) hash = MurmurHash.update(hash, action) return MurmurHash.finish(hash, 2) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerModeAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerModeAction.swift index 81d89c285..7bab1e713 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerModeAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerModeAction.swift @@ -64,7 +64,7 @@ public final class LexerModeAction: LexerAction, CustomStringConvertible { } override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) hash = MurmurHash.update(hash, mode) return MurmurHash.finish(hash, 2) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerMoreAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerMoreAction.swift index f393d224f..bb9f197f3 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerMoreAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerMoreAction.swift @@ -58,7 +58,7 @@ public final class LexerMoreAction: LexerAction, CustomStringConvertible { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) return MurmurHash.finish(hash, 1) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerPopModeAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerPopModeAction.swift index 33fa445b3..f35e78304 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerPopModeAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerPopModeAction.swift @@ -59,7 +59,7 @@ public final class LexerPopModeAction: LexerAction, CustomStringConvertible { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) return MurmurHash.finish(hash, 1) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerPushModeAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerPushModeAction.swift index adfd40994..33d5bf79b 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerPushModeAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerPushModeAction.swift @@ -66,7 +66,7 @@ public final class LexerPushModeAction: LexerAction, CustomStringConvertible { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) hash = MurmurHash.update(hash, mode) return MurmurHash.finish(hash, 2) diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerSkipAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerSkipAction.swift index 5c6907dc7..bbdd06d2f 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerSkipAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerSkipAction.swift @@ -58,7 +58,7 @@ public final class LexerSkipAction: LexerAction, CustomStringConvertible { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) return MurmurHash.finish(hash, 1) } diff --git a/runtime/Swift/Sources/Antlr4/atn/LexerTypeAction.swift b/runtime/Swift/Sources/Antlr4/atn/LexerTypeAction.swift index 33a116fc1..10b41698f 100644 --- a/runtime/Swift/Sources/Antlr4/atn/LexerTypeAction.swift +++ b/runtime/Swift/Sources/Antlr4/atn/LexerTypeAction.swift @@ -64,7 +64,7 @@ public class LexerTypeAction: LexerAction, CustomStringConvertible { override public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, getActionType().rawValue) hash = MurmurHash.update(hash, type) return MurmurHash.finish(hash, 2) diff --git a/runtime/Swift/Sources/Antlr4/atn/ParserATNSimulator.swift b/runtime/Swift/Sources/Antlr4/atn/ParserATNSimulator.swift index 735bc2869..530738b22 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ParserATNSimulator.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ParserATNSimulator.swift @@ -236,10 +236,11 @@ import Foundation open class ParserATNSimulator: ATNSimulator { - public let debug: Bool = false - public let debug_list_atn_decisions: Bool = false - public let dfa_debug: Bool = false - public let retry_debug: Bool = false + public let debug = false + public let debug_list_atn_decisions = false + public let dfa_debug = false + public let retry_debug = false + /// /// Just in case this optimization is bad, add an ENV variable to turn it off /// @@ -249,7 +250,8 @@ open class ParserATNSimulator: ATNSimulator { } return false }() - internal final var parser: Parser + + internal final unowned let parser: Parser public final var decisionToDFA: [DFA] @@ -257,7 +259,7 @@ open class ParserATNSimulator: ATNSimulator { /// SLL, LL, or LL + exact ambig detection? /// - private var mode: PredictionMode = PredictionMode.LL + private var mode = PredictionMode.LL /// /// Each prediction operation uses a cache for merge of prediction contexts. @@ -272,7 +274,7 @@ open class ParserATNSimulator: ATNSimulator { // LAME globals to avoid parameters!!!!! I need these down deep in predTransition internal var _input: TokenStream! - internal var _startIndex: Int = 0 + internal var _startIndex = 0 internal var _outerContext: ParserRuleContext! internal var _dfa: DFA? @@ -310,7 +312,6 @@ open class ParserATNSimulator: ATNSimulator { override open func clearDFA() { - //for var d: Int = 0; d < decisionToDFA.count; d++ { for d in 0.. Int { var outerContext = outerContext - if debug || debug_list_atn_decisions { - var debugInfo = "adaptivePredict decision \(decision) " - debugInfo += "exec LA(1)==\(try getLookaheadName(input)) " - debugInfo += "line \(try input.LT(1)!.getLine()):" - debugInfo += "\(try input.LT(1)!.getCharPositionInLine())" - print(debugInfo) + if debug || debug_list_atn_decisions { + var debugInfo = "adaptivePredict decision \(decision) " + debugInfo += "exec LA(1)==\(try getLookaheadName(input)) " + debugInfo += "line \(try input.LT(1)!.getLine()):" + debugInfo += "\(try input.LT(1)!.getCharPositionInLine())" + print(debugInfo) + } + + + _input = input + _startIndex = input.index() + _outerContext = outerContext + let dfa = decisionToDFA[decision] + _dfa = dfa + + let m = input.mark() + let index = _startIndex + + // Now we are certain to have a specific decision's DFA + // But, do we still need an initial state? + //TODO: exception handler + do { + var s0: DFAState? + if dfa.isPrecedenceDfa() { + // the start state for a precedence DFA depends on the current + // parser precedence, and is provided by a DFA method. + s0 = try dfa.getPrecedenceStartState(parser.getPrecedence()) + } else { + // the start state for a "regular" DFA is just s0 + s0 = dfa.s0 } + if s0 == nil { + //BIG BUG + if outerContext == nil { + outerContext = ParserRuleContext.EMPTY + } + if debug || debug_list_atn_decisions { + var debugInfo = "predictATN decision \(dfa.decision) " + debugInfo += "exec LA(1)==\(try getLookaheadName(input)), " + debugInfo += "outerContext=\(outerContext!.toString(parser))" + print(debugInfo) + } - _input = input - _startIndex = input.index() - _outerContext = outerContext - var dfa: DFA = decisionToDFA[decision] - _dfa = dfa + let fullCtx = false + var s0_closure = try computeStartState(dfa.atnStartState, ParserRuleContext.EMPTY, fullCtx) - var m: Int = input.mark() - var index: Int = _startIndex - - // Now we are certain to have a specific decision's DFA - // But, do we still need an initial state? - //TODO: exception handler - do { - var s0: DFAState? if dfa.isPrecedenceDfa() { - // the start state for a precedence DFA depends on the current - // parser precedence, and is provided by a DFA method. - s0 = try dfa.getPrecedenceStartState(parser.getPrecedence()) + /// + /// If this is a precedence DFA, we use applyPrecedenceFilter + /// to convert the computed start state to a precedence start + /// state. We then use DFA.setPrecedenceStartState to set the + /// appropriate start state for the precedence level rather + /// than simply setting DFA.s0. + /// + //added by janyou 20160224 + // dfa.s0!.configs = s0_closure // not used for prediction but useful to know start configs anyway + s0_closure = try applyPrecedenceFilter(s0_closure) + s0 = addDFAState(dfa, DFAState(s0_closure)) + try dfa.setPrecedenceStartState(parser.getPrecedence(), s0!) } else { - // the start state for a "regular" DFA is just s0 - s0 = dfa.s0 + s0 = addDFAState(dfa, DFAState(s0_closure)) + dfa.s0 = s0 } - - if s0 == nil { - //BIG BUG - if outerContext == nil { - outerContext = ParserRuleContext.EMPTY - } - if debug || debug_list_atn_decisions { - var debugInfo = "predictATN decision \(dfa.decision) " - debugInfo += "exec LA(1)==\(try getLookaheadName(input)), " - debugInfo += "outerContext=\(outerContext!.toString(parser))" - print(debugInfo) - } - - var fullCtx: Bool = false - var s0_closure: ATNConfigSet = try computeStartState(dfa.atnStartState, - ParserRuleContext.EMPTY, - fullCtx) - - if dfa.isPrecedenceDfa() { - /// - /// If this is a precedence DFA, we use applyPrecedenceFilter - /// to convert the computed start state to a precedence start - /// state. We then use DFA.setPrecedenceStartState to set the - /// appropriate start state for the precedence level rather - /// than simply setting DFA.s0. - /// - //added by janyou 20160224 - // dfa.s0!.configs = s0_closure // not used for prediction but useful to know start configs anyway - s0_closure = try applyPrecedenceFilter(s0_closure) - s0 = try addDFAState(dfa, DFAState(s0_closure)) - try dfa.setPrecedenceStartState(parser.getPrecedence(), s0!) - } else { - s0 = try addDFAState(dfa, DFAState(s0_closure)) - dfa.s0 = s0 - } - } - - var alt: Int = try execATN(dfa, s0!, input, index, outerContext!) - if debug { - print("DFA after predictATN: \(dfa.toString(parser.getVocabulary()))") - } - defer { - mergeCache = nil // wack cache after each prediction - _dfa = nil - try! input.seek(index) - try! input.release(m) - } - return alt } + let alt = try execATN(dfa, s0!, input, index, outerContext!) + if debug { + print("DFA after predictATN: \(dfa.toString(parser.getVocabulary()))") + } + mergeCache = nil // wack cache after each prediction + _dfa = nil + try! input.seek(index) + try! input.release(m) + return alt + } + } /// @@ -440,13 +437,13 @@ open class ParserATNSimulator: ATNSimulator { try print("execATN decision \(dfa.decision) exec LA(1)==\(getLookaheadName(input)) line \(input.LT(1)!.getLine()):\(input.LT(1)!.getCharPositionInLine())") } - var previousD: DFAState = s0 + var previousD = s0 if debug { print("s0 = \(s0)") } - var t: Int = try input.LA(1) + var t = try input.LA(1) while true { // while more work @@ -467,9 +464,9 @@ open class ParserATNSimulator: ATNSimulator { // ATN states in SLL implies LL will also get nowhere. // If conflict in states that dip out, choose min since we // will get error no matter what. - let e: NoViableAltException = try noViableAlt(input, outerContext, previousD.configs, startIndex) + let e = noViableAlt(input, outerContext, previousD.configs, startIndex) try input.seek(startIndex) - let alt: Int = try getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configs, outerContext) + let alt = try getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previousD.configs, outerContext) if alt != ATN.INVALID_ALT_NUMBER { return alt } @@ -480,12 +477,12 @@ open class ParserATNSimulator: ATNSimulator { if D.requiresFullContext && (mode != PredictionMode.SLL) { // IF PREDS, MIGHT RESOLVE TO SINGLE ALT => SLL (or syntax error) - var conflictingAlts: BitSet = D.configs.conflictingAlts! + var conflictingAlts = D.configs.conflictingAlts! if D.predicates != nil { if debug { print("DFA state has preds in DFA sim LL failover") } - let conflictIndex: Int = input.index() + let conflictIndex = input.index() if conflictIndex != startIndex { try input.seek(startIndex) } @@ -495,7 +492,7 @@ open class ParserATNSimulator: ATNSimulator { if debug { print("Full LL avoided") } - return try conflictingAlts.nextSetBit(0) + return conflictingAlts.firstSetBit() } if conflictIndex != startIndex { @@ -508,12 +505,10 @@ open class ParserATNSimulator: ATNSimulator { if dfa_debug { print("ctx sensitive state \(outerContext) in \(D)") } - let fullCtx: Bool = true - let s0_closure: ATNConfigSet = - try computeStartState(dfa.atnStartState, outerContext, - fullCtx) - try reportAttemptingFullContext(dfa, conflictingAlts, D.configs, startIndex, input.index()) - let alt: Int = try execATNWithFullContext(dfa, D, s0_closure, + let fullCtx = true + let s0_closure = try computeStartState(dfa.atnStartState, outerContext, fullCtx) + reportAttemptingFullContext(dfa, conflictingAlts, D.configs, startIndex, input.index()) + let alt = try execATNWithFullContext(dfa, D, s0_closure, input, startIndex, outerContext) return alt @@ -524,22 +519,22 @@ open class ParserATNSimulator: ATNSimulator { return D.prediction } - let stopIndex: Int = input.index() + let stopIndex = input.index() try input.seek(startIndex) - let alts: BitSet = try evalSemanticContext(D.predicates!, outerContext, true) + let alts = try evalSemanticContext(D.predicates!, outerContext, true) switch alts.cardinality() { case 0: - throw try ANTLRException.recognition(e: noViableAlt(input, outerContext, D.configs, startIndex)) + throw ANTLRException.recognition(e: noViableAlt(input, outerContext, D.configs, startIndex)) case 1: - return try alts.nextSetBit(0) + return alts.firstSetBit() default: // report ambiguity after predicate evaluation to make sure the correct // set of ambig alts is reported. - try reportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configs) - return try alts.nextSetBit(0) + reportAmbiguity(dfa, D, startIndex, stopIndex, false, alts, D.configs) + return alts.firstSetBit() } } @@ -564,7 +559,7 @@ open class ParserATNSimulator: ATNSimulator { /// already cached /// func getExistingTargetState(_ previousD: DFAState, _ t: Int) -> DFAState? { - var edges: [DFAState?]? = previousD.edges + var edges = previousD.edges if edges == nil || (t + 1) < 0 || (t + 1) >= (edges!.count) { return nil } @@ -586,9 +581,9 @@ open class ParserATNSimulator: ATNSimulator { /// func computeTargetState(_ dfa: DFA, _ previousD: DFAState, _ t: Int) throws -> DFAState { - let reach: ATNConfigSet? = try computeReachSet(previousD.configs, t, false) + let reach = try computeReachSet(previousD.configs, t, false) if reach == nil { - try addDFAEdge(dfa, previousD, t, ATNSimulator.ERROR) + addDFAEdge(dfa, previousD, t, ATNSimulator.ERROR) return ATNSimulator.ERROR } @@ -598,8 +593,8 @@ open class ParserATNSimulator: ATNSimulator { let predictedAlt: Int = ParserATNSimulator.getUniqueAlt(reach!) if debug { - let altSubSets: Array = try PredictionMode.getConflictingAltSubsets(reach!) - print("SLL altSubSets=\(altSubSets), configs=\(reach!), predict=\(predictedAlt), allSubsetsConflict=\(PredictionMode.allSubsetsConflict(altSubSets)), conflictingAlts=\(try! getConflictingAlts(reach!))") + let altSubSets = PredictionMode.getConflictingAltSubsets(reach!) + print("SLL altSubSets=\(altSubSets), configs=\(reach!), predict=\(predictedAlt), allSubsetsConflict=\(PredictionMode.allSubsetsConflict(altSubSets)), conflictingAlts=\(getConflictingAlts(reach!))") } if predictedAlt != ATN.INVALID_ALT_NUMBER { @@ -608,44 +603,43 @@ open class ParserATNSimulator: ATNSimulator { D.configs.uniqueAlt = predictedAlt D.prediction = predictedAlt } else { - if try PredictionMode.hasSLLConflictTerminatingPrediction(mode, reach!) { + if PredictionMode.hasSLLConflictTerminatingPrediction(mode, reach!) { // MORE THAN ONE VIABLE ALTERNATIVE - D.configs.conflictingAlts = try getConflictingAlts(reach!) + D.configs.conflictingAlts = getConflictingAlts(reach!) D.requiresFullContext = true // in SLL-only mode, we will stop at this state and return the minimum alt D.isAcceptState = true - D.prediction = try D.configs.conflictingAlts!.nextSetBit(0) + D.prediction = D.configs.conflictingAlts!.firstSetBit() } } if D.isAcceptState && D.configs.hasSemanticContext { - try predicateDFAState(D, atn.getDecisionState(dfa.decision)!) + predicateDFAState(D, atn.getDecisionState(dfa.decision)!) if D.predicates != nil { D.prediction = ATN.INVALID_ALT_NUMBER } } // all adds to dfa are done after we've created full D state - D = try addDFAEdge(dfa, previousD, t, D)! + D = addDFAEdge(dfa, previousD, t, D)! return D } - final func predicateDFAState(_ dfaState: DFAState, _ decisionState: DecisionState) throws { + final func predicateDFAState(_ dfaState: DFAState, _ decisionState: DecisionState) { // We need to test all predicates, even in DFA states that // uniquely predict alternative. - let nalts: Int = decisionState.getNumberOfTransitions() + let nalts = decisionState.getNumberOfTransitions() // Update DFA so reach becomes accept state with (predicate,alt) // pairs if preds found for conflicting alts - let altsToCollectPredsFrom: BitSet = try getConflictingAltsOrUniqueAlt(dfaState.configs) - let altToPred: [SemanticContext?]? = try getPredsForAmbigAlts(altsToCollectPredsFrom, dfaState.configs, nalts) - if altToPred != nil { - dfaState.predicates = try getPredicatePredictions(altsToCollectPredsFrom, altToPred!) + let altsToCollectPredsFrom = getConflictingAltsOrUniqueAlt(dfaState.configs) + if let altToPred = getPredsForAmbigAlts(altsToCollectPredsFrom, dfaState.configs, nalts) { + dfaState.predicates = getPredicatePredictions(altsToCollectPredsFrom, altToPred) dfaState.prediction = ATN.INVALID_ALT_NUMBER // make sure we use preds } else { // There are preds in configs but they might go away // when OR'd together like {p}? || NONE == NONE. If neither // alt has preds, resolve to min alt - dfaState.prediction = try altsToCollectPredsFrom.nextSetBit(0) + dfaState.prediction = altsToCollectPredsFrom.firstSetBit() } } @@ -658,13 +652,13 @@ open class ParserATNSimulator: ATNSimulator { if debug || debug_list_atn_decisions { print("execATNWithFullContext \(s0)") } - let fullCtx: Bool = true - var foundExactAmbig: Bool = false + let fullCtx = true + var foundExactAmbig = false var reach: ATNConfigSet? = nil - var previous: ATNConfigSet = s0 + var previous = s0 try input.seek(startIndex) - var t: Int = try input.LA(1) - var predictedAlt: Int = 0 + var t = try input.LA(1) + var predictedAlt = 0 while true { // while more work if let computeReach = try computeReachSet(previous, t, fullCtx) { @@ -679,9 +673,9 @@ open class ParserATNSimulator: ATNSimulator { // ATN states in SLL implies LL will also get nowhere. // If conflict in states that dip out, choose min since we // will get error no matter what. - let e: NoViableAltException = try noViableAlt(input, outerContext, previous, startIndex) + let e = noViableAlt(input, outerContext, previous, startIndex) try input.seek(startIndex) - let alt: Int = try getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext) + let alt = try getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(previous, outerContext) if alt != ATN.INVALID_ALT_NUMBER { return alt } @@ -689,9 +683,9 @@ open class ParserATNSimulator: ATNSimulator { } if let reach = reach { - let altSubSets: Array = try PredictionMode.getConflictingAltSubsets(reach) + let altSubSets = PredictionMode.getConflictingAltSubsets(reach) if debug { - print("LL altSubSets=\(altSubSets), predict=\(try PredictionMode.getUniqueAlt(altSubSets)), resolvesToJustOneViableAlt=\(try PredictionMode.resolvesToJustOneViableAlt(altSubSets))") + print("LL altSubSets=\(altSubSets), predict=\(PredictionMode.getUniqueAlt(altSubSets)), resolvesToJustOneViableAlt=\(PredictionMode.resolvesToJustOneViableAlt(altSubSets))") } @@ -702,7 +696,7 @@ open class ParserATNSimulator: ATNSimulator { break } if mode != PredictionMode.LL_EXACT_AMBIG_DETECTION { - predictedAlt = try PredictionMode.resolvesToJustOneViableAlt(altSubSets) + predictedAlt = PredictionMode.resolvesToJustOneViableAlt(altSubSets) if predictedAlt != ATN.INVALID_ALT_NUMBER { break } @@ -712,7 +706,7 @@ open class ParserATNSimulator: ATNSimulator { if PredictionMode.allSubsetsConflict(altSubSets) && PredictionMode.allSubsetsEqual(altSubSets) { foundExactAmbig = true - predictedAlt = try PredictionMode.getSingleViableAlt(altSubSets) + predictedAlt = PredictionMode.getSingleViableAlt(altSubSets) break } // else there are multiple non-conflicting subsets or @@ -732,7 +726,7 @@ open class ParserATNSimulator: ATNSimulator { // without conflict, then we know that it's a full LL decision // not SLL. if reach.uniqueAlt != ATN.INVALID_ALT_NUMBER { - try reportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.index()) + reportContextSensitivity(dfa, predictedAlt, reach, startIndex, input.index()) return predictedAlt } @@ -763,8 +757,8 @@ open class ParserATNSimulator: ATNSimulator { /// the fact that we should predict alternative 1. We just can't say for /// sure that there is an ambiguity without looking further. /// - try reportAmbiguity(dfa, D, startIndex, input.index(), foundExactAmbig, - reach.getAlts(), reach) + reportAmbiguity(dfa, D, startIndex, input.index(), foundExactAmbig, + reach.getAlts(), reach) } return predictedAlt } @@ -780,7 +774,7 @@ open class ParserATNSimulator: ATNSimulator { mergeCache = DoubleKeyMap() } - let intermediate: ATNConfigSet = ATNConfigSet(fullCtx) + let intermediate = ATNConfigSet(fullCtx) /// /// Configurations already in a rule stop state indicate reaching the end @@ -793,39 +787,33 @@ open class ParserATNSimulator: ATNSimulator { /// ensure that the alternative matching the longest overall sequence is /// chosen when multiple such configurations can match the input. /// - var skippedStopStates: Array? = nil + var skippedStopStates: [ATNConfig]? = nil // First figure out where we can reach on input t - let length = closureConfigSet.configs.count let configs = closureConfigSet.configs - for i in 0..() + skippedStopStates = [ATNConfig]() } - - skippedStopStates?.append(configs[i]) + skippedStopStates!.append(config) } continue } - let n: Int = configs[i].state.getNumberOfTransitions() + let n = config.state.getNumberOfTransitions() for ti in 0.. = Set() - let treatEofAsEpsilon: Bool = t == CommonToken.EOF - let configs = intermediate.configs - let length = configs.count - for i in 0..() + let treatEofAsEpsilon = (t == CommonToken.EOF) + for config in intermediate.configs { + try closure(config, reach!, &closureBusy, false, fullCtx, treatEofAsEpsilon) } } @@ -896,7 +880,7 @@ open class ParserATNSimulator: ATNSimulator { /// already guaranteed to meet this condition whether or not it's /// required. /// - reach = try removeAllConfigsNotInRuleStopState(reach!, reach! === intermediate) + reach = removeAllConfigsNotInRuleStopState(reach!, reach! === intermediate) } /// @@ -909,10 +893,10 @@ open class ParserATNSimulator: ATNSimulator { /// multiple alternatives are viable. /// if let reach = reach { - if skippedStopStates != nil && (!fullCtx || !PredictionMode.hasConfigInRuleStopState(reach)) { - assert(!skippedStopStates!.isEmpty, "Expected: !skippedStopStates.isEmpty()") - for c: ATNConfig in skippedStopStates! { - try reach.add(c, &mergeCache) + if let skippedStopStates = skippedStopStates, (!fullCtx || !PredictionMode.hasConfigInRuleStopState(reach)) { + assert(!skippedStopStates.isEmpty, "Expected: !skippedStopStates.isEmpty()") + for c in skippedStopStates { + try! reach.add(c, &mergeCache) } } @@ -943,29 +927,22 @@ open class ParserATNSimulator: ATNSimulator { /// 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) throws -> ATNConfigSet { - - let result = try configs.removeAllConfigsNotInRuleStopState(&mergeCache,lookToEndOfRule,atn) - return result + final func removeAllConfigsNotInRuleStopState(_ configs: ATNConfigSet, _ lookToEndOfRule: Bool) -> ATNConfigSet { + return configs.removeAllConfigsNotInRuleStopState(&mergeCache,lookToEndOfRule,atn) } - final func computeStartState(_ p: ATNState, - _ ctx: RuleContext, - _ fullCtx: Bool) throws -> ATNConfigSet { - - - let initialContext: PredictionContext = PredictionContext.fromRuleContext(atn, ctx) - let configs: ATNConfigSet = ATNConfigSet(fullCtx) + final func computeStartState(_ p: ATNState, _ ctx: RuleContext, _ fullCtx: Bool) throws -> ATNConfigSet { + let initialContext = PredictionContext.fromRuleContext(atn, ctx) + let configs = ATNConfigSet(fullCtx) let length = p.getNumberOfTransitions() for i in 0.. = Set() + let target = p.transition(i).target + let c = ATNConfig(target, i + 1, initialContext) + var closureBusy = Set() try closure(c, configs, &closureBusy, true, fullCtx, false) } - return configs } @@ -1127,10 +1104,8 @@ open class ParserATNSimulator: ATNSimulator { /// 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 { - - let configSet = try configs.applyPrecedenceFilter(&mergeCache,parser,_outerContext) - return configSet + final internal func applyPrecedenceFilter(_ configs: ATNConfigSet) throws -> ATNConfigSet { + return try configs.applyPrecedenceFilter(&mergeCache,parser,_outerContext) } final internal func getReachableTarget(_ trans: Transition, _ ttype: Int) -> ATNState? { @@ -1144,7 +1119,7 @@ open class ParserATNSimulator: ATNSimulator { final internal func getPredsForAmbigAlts(_ ambigAlts: BitSet, _ configs: ATNConfigSet, - _ nalts: Int) throws -> [SemanticContext?]? { + _ 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 @@ -1158,8 +1133,7 @@ open class ParserATNSimulator: ATNSimulator { /// /// From this, it is clear that NONE||anything==NONE. /// - let altToPred: [SemanticContext?]? = try configs.getPredsForAmbigAlts(ambigAlts,nalts) - + let altToPred = configs.getPredsForAmbigAlts(ambigAlts,nalts) if debug { print("getPredsForAmbigAlts result \(String(describing: altToPred))") } @@ -1167,17 +1141,17 @@ open class ParserATNSimulator: ATNSimulator { } final internal func getPredicatePredictions(_ ambigAlts: BitSet?, - _ altToPred: [SemanticContext?]) throws -> [DFAState.PredPrediction]? { - var pairs: Array = Array() - var containsPredicate: Bool = false + _ altToPred: [SemanticContext?]) -> [DFAState.PredPrediction]? { + var pairs = [DFAState.PredPrediction]() + var containsPredicate = false let length = altToPred.count for i in 1.. Int { - let sets: (ATNConfigSet, ATNConfigSet) = try - splitAccordingToSemanticValidity(configs, outerContext) - let semValidConfigs: ATNConfigSet = sets.0 - let semInvalidConfigs: ATNConfigSet = sets.1 - var alt: Int = try getAltThatFinishedDecisionEntryRule(semValidConfigs) + let (semValidConfigs, semInvalidConfigs) = try splitAccordingToSemanticValidity(configs, outerContext) + var alt = getAltThatFinishedDecisionEntryRule(semValidConfigs) if alt != ATN.INVALID_ALT_NUMBER { // semantically/syntactically viable path exists return alt } // Is there a syntactically valid path with a failed pred? if semInvalidConfigs.size() > 0 { - alt = try getAltThatFinishedDecisionEntryRule(semInvalidConfigs) + alt = getAltThatFinishedDecisionEntryRule(semInvalidConfigs) if alt != ATN.INVALID_ALT_NUMBER { // syntactically viable path exists return alt @@ -1254,9 +1225,9 @@ open class ParserATNSimulator: ATNSimulator { return ATN.INVALID_ALT_NUMBER } - final internal func getAltThatFinishedDecisionEntryRule(_ configs: ATNConfigSet) throws -> Int { + final internal func getAltThatFinishedDecisionEntryRule(_ configs: ATNConfigSet) -> Int { - return try configs.getAltThatFinishedDecisionEntryRule() + return configs.getAltThatFinishedDecisionEntryRule() } /// @@ -1273,7 +1244,7 @@ open class ParserATNSimulator: ATNSimulator { _ configs: ATNConfigSet, _ outerContext: ParserRuleContext) throws -> (ATNConfigSet, ATNConfigSet) { - return try configs.splitAccordingToSemanticValidity(outerContext,evalSemanticContext) + return try configs.splitAccordingToSemanticValidity(outerContext, evalSemanticContext) } /// @@ -1286,18 +1257,18 @@ open class ParserATNSimulator: ATNSimulator { final internal func evalSemanticContext(_ predPredictions: [DFAState.PredPrediction], _ outerContext: ParserRuleContext, _ complete: Bool) throws -> BitSet { - let predictions: BitSet = BitSet() - for pair: DFAState.PredPrediction in predPredictions { + let predictions = BitSet() + for pair in predPredictions { if pair.pred == SemanticContext.NONE { - try predictions.set(pair.alt) + try! predictions.set(pair.alt) if !complete { break } continue } - let fullCtx: Bool = false // in dfa - let predicateEvaluationResult: Bool = try evalSemanticContext(pair.pred, outerContext, pair.alt, fullCtx) + let fullCtx = false // in dfa + let predicateEvaluationResult = try evalSemanticContext(pair.pred, outerContext, pair.alt, fullCtx) if debug || dfa_debug { print("eval pred \(pair)= \(predicateEvaluationResult)") } @@ -1306,7 +1277,7 @@ open class ParserATNSimulator: ATNSimulator { if debug || dfa_debug { print("PREDICT \(pair.alt)") } - try predictions.set(pair.alt) + try! predictions.set(pair.alt) if !complete { break } @@ -1360,10 +1331,8 @@ open class ParserATNSimulator: ATNSimulator { _ collectPredicates: Bool, _ fullCtx: Bool, _ treatEofAsEpsilon: Bool) throws { - let initialDepth: Int = 0 - try closureCheckingStopState(config, configs, &closureBusy, collectPredicates, - fullCtx, - initialDepth, treatEofAsEpsilon) + let initialDepth = 0 + try closureCheckingStopState(config, configs, &closureBusy, collectPredicates, fullCtx, initialDepth, treatEofAsEpsilon) assert(!fullCtx || !configs.dipsIntoOuterContext, "Expected: !fullCtx||!configs.dipsIntoOuterContext") } @@ -1389,7 +1358,7 @@ open class ParserATNSimulator: ATNSimulator { for i in 0.. ATNConfig { - if debug { - print("PRED (collectPredicates=\(collectPredicates)) \(pt.precedence)>=_p, ctx dependent=true") - //if ( parser != nil ) { - print("context surrounding pred is \(parser.getRuleInvocationStack())") - // } - } + _ pt: PrecedencePredicateTransition, + _ collectPredicates: Bool, + _ inContext: Bool, + _ fullCtx: Bool) throws -> ATNConfig { + if debug { + print("PRED (collectPredicates=\(collectPredicates)) \(pt.precedence)>=_p, ctx dependent=true") + //if ( parser != nil ) { + print("context surrounding pred is \(parser.getRuleInvocationStack())") + // } + } - var c: ATNConfig? = nil - if collectPredicates && inContext { - if fullCtx { - // In full context mode, we can evaluate predicates on-the-fly - // during closure, which dramatically reduces the size of - // the config sets. It also obviates the need to test predicates - // later during conflict resolution. - let currentPosition: Int = _input.index() - try _input.seek(_startIndex) - let predSucceeds: Bool = try evalSemanticContext(pt.getPredicate(), _outerContext, config.alt, fullCtx) - try _input.seek(currentPosition) - if predSucceeds { - c = ATNConfig(config, pt.target) // no pred context - } - } else { - let newSemCtx: SemanticContext = - SemanticContext.and(config.semanticContext, pt.getPredicate()) - c = ATNConfig(config, pt.target, newSemCtx) + var c: ATNConfig? = nil + if collectPredicates && inContext { + if fullCtx { + // In full context mode, we can evaluate predicates on-the-fly + // during closure, which dramatically reduces the size of + // the config sets. It also obviates the need to test predicates + // later during conflict resolution. + let currentPosition = _input.index() + try _input.seek(_startIndex) + let predSucceeds = try evalSemanticContext(pt.getPredicate(), _outerContext, config.alt, fullCtx) + try _input.seek(currentPosition) + if predSucceeds { + c = ATNConfig(config, pt.target) // no pred context } - } else { - c = ATNConfig(config, pt.target) } + else { + let newSemCtx = SemanticContext.and(config.semanticContext, pt.getPredicate()) + c = ATNConfig(config, pt.target, newSemCtx) + } + } + else { + c = ATNConfig(config, pt.target) + } - if debug { - print("config from pred transition=\(String(describing: c))") - } - return c! + if debug { + print("config from pred transition=\(String(describing: c))") + } + return c! } final func predTransition(_ config: ATNConfig, - _ pt: PredicateTransition, - _ collectPredicates: Bool, - _ inContext: Bool, - _ fullCtx: Bool) throws -> ATNConfig? { - if debug { - print("PRED (collectPredicates=\(collectPredicates)) \(pt.ruleIndex):\(pt.predIndex), ctx dependent=\(pt.isCtxDependent)") - //if ( parser != nil ) { - print("context surrounding pred is \(parser.getRuleInvocationStack())") - //} - } + _ pt: PredicateTransition, + _ collectPredicates: Bool, + _ inContext: Bool, + _ fullCtx: Bool) throws -> ATNConfig? { + if debug { + print("PRED (collectPredicates=\(collectPredicates)) \(pt.ruleIndex):\(pt.predIndex), ctx dependent=\(pt.isCtxDependent)") + //if ( parser != nil ) { + print("context surrounding pred is \(parser.getRuleInvocationStack())") + //} + } - var c: ATNConfig? = nil - if collectPredicates && - (!pt.isCtxDependent || (pt.isCtxDependent && inContext)) { - if fullCtx { - // In full context mode, we can evaluate predicates on-the-fly - // during closure, which dramatically reduces the size of - // the config sets. It also obviates the need to test predicates - // later during conflict resolution. - let currentPosition: Int = _input.index() - try _input.seek(_startIndex) - let predSucceeds: Bool = try evalSemanticContext(pt.getPredicate(), _outerContext, config.alt, fullCtx) - try _input.seek(currentPosition) - if predSucceeds { - c = ATNConfig(config, pt.target) // no pred context - } - } else { - let newSemCtx: SemanticContext = - SemanticContext.and(config.semanticContext, pt.getPredicate()) - c = ATNConfig(config, pt.target, newSemCtx) - } + var c: ATNConfig? = nil + if collectPredicates && + (!pt.isCtxDependent || (pt.isCtxDependent && inContext)) { + if fullCtx { + // In full context mode, we can evaluate predicates on-the-fly + // during closure, which dramatically reduces the size of + // the config sets. It also obviates the need to test predicates + // later during conflict resolution. + let currentPosition = _input.index() + try _input.seek(_startIndex) + let predSucceeds = try evalSemanticContext(pt.getPredicate(), _outerContext, config.alt, fullCtx) + try _input.seek(currentPosition) + if predSucceeds { + c = ATNConfig(config, pt.target) // no pred context + } } else { - c = ATNConfig(config, pt.target) + let newSemCtx = SemanticContext.and(config.semanticContext, pt.getPredicate()) + c = ATNConfig(config, pt.target, newSemCtx) } + } else { + c = ATNConfig(config, pt.target) + } - if debug { - print("config from pred transition=\(String(describing: c))") - } - return c + if debug { + print("config from pred transition=\(String(describing: c))") + } + return c } @@ -1842,9 +1807,8 @@ open class ParserATNSimulator: ATNSimulator { print("CALL rule \(getRuleName(t.target.ruleIndex!)), ctx=\(String(describing: config.context))") } - let returnState: ATNState = t.followState - let newContext: PredictionContext = - SingletonPredictionContext.create(config.context, returnState.stateNumber) + let returnState = t.followState + let newContext = SingletonPredictionContext.create(config.context, returnState.stateNumber) return ATNConfig(config, t.target, newContext) } @@ -1857,8 +1821,8 @@ open class ParserATNSimulator: ATNSimulator { /// conflicting alternative subsets. If `configs` does not contain any /// conflicting subsets, this method returns an empty _java.util.BitSet_. /// - final func getConflictingAlts(_ configs: ATNConfigSet) throws -> BitSet { - let altsets: Array = try PredictionMode.getConflictingAltSubsets(configs) + final func getConflictingAlts(_ configs: ATNConfigSet) -> BitSet { + let altsets = PredictionMode.getConflictingAltSubsets(configs) return PredictionMode.getAlts(altsets) } @@ -1898,11 +1862,11 @@ open class ParserATNSimulator: ATNSimulator { /// ignore a set of conflicting alts when we have an alternative /// that we still need to pursue. /// - final func getConflictingAltsOrUniqueAlt(_ configs: ATNConfigSet) throws -> BitSet { + final func getConflictingAltsOrUniqueAlt(_ configs: ATNConfigSet) -> BitSet { var conflictingAlts: BitSet if configs.uniqueAlt != ATN.INVALID_ALT_NUMBER { conflictingAlts = BitSet() - try conflictingAlts.set(configs.uniqueAlt) + try! conflictingAlts.set(configs.uniqueAlt) } else { conflictingAlts = configs.conflictingAlts! } @@ -1914,9 +1878,8 @@ open class ParserATNSimulator: ATNSimulator { if t == CommonToken.EOF { return "EOF" } - //var vocabulary : Vocabulary = parser != nil ? parser.getVocabulary() : Vocabulary.EMPTY_VOCABULARY; - let vocabulary: Vocabulary = parser.getVocabulary() - let displayName: String = vocabulary.getDisplayName(t) + let vocabulary = parser.getVocabulary() + let displayName = vocabulary.getDisplayName(t) if displayName == String(t) { return displayName } @@ -1935,19 +1898,16 @@ open class ParserATNSimulator: ATNSimulator { /// public final func dumpDeadEndConfigs(_ nvae: NoViableAltException) { errPrint("dead end configs: ") - for c: ATNConfig in nvae.getDeadEndConfigs()!.configs { - var trans: String = "no edges" + for c in nvae.getDeadEndConfigs()!.configs { + var trans = "no edges" if c.state.getNumberOfTransitions() > 0 { - let t: Transition = c.state.transition(0) - if t is AtomTransition { - let at: AtomTransition = t as! AtomTransition + let t = c.state.transition(0) + if let at = t as? AtomTransition { trans = "Atom " + getTokenName(at.label) - } else { - if t is SetTransition { - let st: SetTransition = t as! SetTransition - let not: Bool = st is NotSetTransition - trans = (not ? "~" : "") + "Set " + st.set.toString() - } + } + else if let st = t as? SetTransition { + let not = st is NotSetTransition + trans = (not ? "~" : "") + "Set " + st.set.toString() } } errPrint("\(c.toString(parser, true)):\(trans)") @@ -1956,13 +1916,17 @@ open class ParserATNSimulator: ATNSimulator { final func noViableAlt(_ input: TokenStream, - _ outerContext: ParserRuleContext, - _ configs: ATNConfigSet, - _ startIndex: Int) throws -> NoViableAltException { - return try NoViableAltException(parser, input, - input.get(startIndex), - input.LT(1)!, - configs, outerContext) + _ outerContext: ParserRuleContext, + _ configs: ATNConfigSet, + _ startIndex: Int) -> NoViableAltException { + let startToken = try! input.get(startIndex) + var offendingToken: Token? = nil + do { + offendingToken = try input.LT(1) + } + catch { + } + return NoViableAltException(parser, input, startToken, offendingToken, configs, outerContext) } internal static func getUniqueAlt(_ configs: ATNConfigSet) -> Int { @@ -1994,7 +1958,7 @@ open class ParserATNSimulator: ATNSimulator { final func addDFAEdge(_ dfa: DFA, _ from: DFAState?, _ t: Int, - _ to: DFAState?) throws -> DFAState? { + _ to: DFAState?) -> DFAState? { var to = to if debug { print("EDGE \(String(describing: from)) -> \(String(describing: to)) upon \(getTokenName(t))") @@ -2004,7 +1968,7 @@ open class ParserATNSimulator: ATNSimulator { return nil } - to = try addDFAState(dfa, to!) // used existing if possible not incoming + to = addDFAState(dfa, to!) // used existing if possible not incoming if from == nil || t < -1 || t > atn.maxTokenType { return to } @@ -2021,7 +1985,6 @@ open class ParserATNSimulator: ATNSimulator { } if debug { - // print ("DFA=\n"+dfa.toString(parser != nil ? parser.getVocabulary() : Vocabulary.EMPTY_VOCABULARY)); print("DFA=\n" + dfa.toString(parser.getVocabulary())) } @@ -2043,12 +2006,12 @@ open class ParserATNSimulator: ATNSimulator { /// state if `D` is already in the DFA, or `D` itself if the /// state was not already present. /// - final func addDFAState(_ dfa: DFA, _ D: DFAState) throws -> DFAState { + final func addDFAState(_ dfa: DFA, _ D: DFAState) -> DFAState { if D == ATNSimulator.ERROR { return D } - return try dfaStatesMutex.synchronized { + return dfaStatesMutex.synchronized { if let existing = dfa.states[D] { return existing! } @@ -2056,7 +2019,7 @@ open class ParserATNSimulator: ATNSimulator { D.stateNumber = dfa.states.count if !D.configs.isReadonly() { - try D.configs.optimizeConfigs(self) + try! D.configs.optimizeConfigs(self) D.configs.setReadonly(true) } @@ -2069,24 +2032,20 @@ open class ParserATNSimulator: ATNSimulator { } } - func reportAttemptingFullContext(_ dfa: DFA, _ conflictingAlts: BitSet?, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) throws { + func reportAttemptingFullContext(_ dfa: DFA, _ conflictingAlts: BitSet?, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) { if debug || retry_debug { - let interval: Interval = Interval.of(startIndex, stopIndex) - try print("reportAttemptingFullContext decision=\(dfa.decision):\(configs), input=\(parser.getTokenStream()!.getText(interval))") + let input = getTextInInterval(startIndex, stopIndex) + print("reportAttemptingFullContext decision=\(dfa.decision):\(configs), input=\(input)") } - // if ( parser=nil ) { - try parser.getErrorListenerDispatch().reportAttemptingFullContext(parser, dfa, startIndex, stopIndex, conflictingAlts, configs) - // } + parser.getErrorListenerDispatch().reportAttemptingFullContext(parser, dfa, startIndex, stopIndex, conflictingAlts, configs) } - func reportContextSensitivity(_ dfa: DFA, _ prediction: Int, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) throws { + func reportContextSensitivity(_ dfa: DFA, _ prediction: Int, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) { if debug || retry_debug { - let interval: Interval = Interval.of(startIndex, stopIndex) - try print("reportContextSensitivity decision=\(dfa.decision):\(configs), input=\(parser.getTokenStream()!.getText(interval))") + let input = getTextInInterval(startIndex, stopIndex) + print("reportContextSensitivity decision=\(dfa.decision):\(configs), input=\(input)") } - //if ( parser=nil ) { - try parser.getErrorListenerDispatch().reportContextSensitivity(parser, dfa, startIndex, stopIndex, prediction, configs) - // } + parser.getErrorListenerDispatch().reportContextSensitivity(parser, dfa, startIndex, stopIndex, prediction, configs) } /// @@ -2098,17 +2057,24 @@ open class ParserATNSimulator: ATNSimulator { _ startIndex: Int, _ stopIndex: Int, _ exact: Bool, _ ambigAlts: BitSet, - _ configs: ATNConfigSet) throws + _ configs: ATNConfigSet) { if debug || retry_debug { - let interval: Interval = Interval.of(startIndex, stopIndex) - try print("reportAmbiguity \(ambigAlts):\(configs), input=\(parser.getTokenStream()!.getText(interval))") + let input = getTextInInterval(startIndex, stopIndex) + print("reportAmbiguity \(ambigAlts):\(configs), input=\(input)") } - //TODO ( parser != nil ? - //if ( parser != nil ) { - try parser .getErrorListenerDispatch().reportAmbiguity(parser, dfa, startIndex, stopIndex, + parser.getErrorListenerDispatch().reportAmbiguity(parser, dfa, startIndex, stopIndex, exact, ambigAlts, configs) - //} + } + + private func getTextInInterval(_ startIndex: Int, _ stopIndex: Int) -> String { + let interval = Interval.of(startIndex, stopIndex) + do { + return try parser.getTokenStream()?.getText(interval) ?? "" + } + catch { + return "" + } } public final func setPredictionMode(_ mode: PredictionMode) { @@ -2120,9 +2086,6 @@ open class ParserATNSimulator: ATNSimulator { return mode } - /// - /// - 4.3 - /// public final func getParser() -> Parser { return parser } diff --git a/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift b/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift index 783a1ab5b..660528da2 100644 --- a/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift +++ b/runtime/Swift/Sources/Antlr4/atn/PredictionContext.swift @@ -12,18 +12,19 @@ public class PredictionContext: Hashable, CustomStringConvertible { /// Represents `$` in local context prediction, which means wildcard. /// `+x = *`. /// - public static let EMPTY: EmptyPredictionContext = EmptyPredictionContext() + 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 = Int(Int32.max) + public static let EMPTY_RETURN_STATE = Int(Int32.max) - private static let INITIAL_HASH: Int = 1 + private static let INITIAL_HASH = UInt32(1) + + public static var globalNodeCount = 0 - public static var globalNodeCount: Int = 0 public final let id: Int = { let oldGlobalNodeCount = globalNodeCount globalNodeCount += 1 @@ -62,12 +63,7 @@ public class PredictionContext: Hashable, CustomStringConvertible { /// Return _#EMPTY_ if `outerContext` is empty or null. /// public static func fromRuleContext(_ atn: ATN, _ outerContext: RuleContext?) -> PredictionContext { - var _outerContext: RuleContext - if let outerContext = outerContext { - _outerContext = outerContext - }else { - _outerContext = RuleContext.EMPTY - } + let _outerContext = outerContext ?? RuleContext.EMPTY // if we are in RuleContext of start rule, s, then PredictionContext // is EMPTY. Nobody called us. (if we are empty, return empty) @@ -76,29 +72,25 @@ public class PredictionContext: Hashable, CustomStringConvertible { } // If we have a parent, convert it to a PredictionContext graph - var parent: PredictionContext = EMPTY - parent = PredictionContext.fromRuleContext(atn, _outerContext.parent) + let parent = PredictionContext.fromRuleContext(atn, _outerContext.parent) - let state: ATNState = atn.states[_outerContext.invokingState]! - let transition: RuleTransition = state.transition(0) as! RuleTransition + let state = atn.states[_outerContext.invokingState]! + let transition = state.transition(0) as! RuleTransition return SingletonPredictionContext.create(parent, transition.followState.stateNumber) } public func size() -> Int { - RuntimeException(#function + " must be overridden") - return 0 + fatalError(#function + " must be overridden") } public func getParent(_ index: Int) -> PredictionContext? { - RuntimeException(#function + " must be overridden") - return nil + fatalError(#function + " must be overridden") } public func getReturnState(_ index: Int) -> Int { - RuntimeException(#function + " must be overridden") - return 0 + fatalError(#function + " must be overridden") } @@ -118,21 +110,19 @@ public class PredictionContext: Hashable, CustomStringConvertible { } static func calculateEmptyHashCode() -> Int { - var hash: Int = MurmurHash.initialize(INITIAL_HASH) - hash = MurmurHash.finish(hash, 0) - return hash + let hash = MurmurHash.initialize(INITIAL_HASH) + return MurmurHash.finish(hash, 0) } static func calculateHashCode(_ parent: PredictionContext?, _ returnState: Int) -> Int { - var hash: Int = MurmurHash.initialize(INITIAL_HASH) + var hash = MurmurHash.initialize(INITIAL_HASH) hash = MurmurHash.update(hash, parent) hash = MurmurHash.update(hash, returnState) - hash = MurmurHash.finish(hash, 2) - return hash + return MurmurHash.finish(hash, 2) } static func calculateHashCode(_ parents: [PredictionContext?], _ returnStates: [Int]) -> Int { - var hash: Int = MurmurHash.initialize(INITIAL_HASH) + var hash = MurmurHash.initialize(INITIAL_HASH) var length = parents.count for i in 0..?) -> PredictionContext { if let mergeCache = mergeCache { - var previous: PredictionContext? = mergeCache.get(a, b) + var previous = mergeCache.get(a, b) if previous != nil { return previous! } @@ -243,45 +230,45 @@ public class PredictionContext: Hashable, CustomStringConvertible { return rootMerge } - if (a.returnState == b.returnState) { + if a.returnState == b.returnState { // a == b - let parent: PredictionContext = merge(a.parent!, b.parent!, rootIsWildcard, &mergeCache); + let parent = merge(a.parent!, b.parent!, rootIsWildcard, &mergeCache) // if parent is same as existing a or b parent or reduced to a parent, return it - if (parent === a.parent!) { + if parent === a.parent! { return a } // ax + bx = ax, if a=b - if (parent === b.parent!) { + if parent === b.parent! { return b } // ax + bx = bx, if a=b // else: ax + ay = a'[x,y] // merge parents x and y, giving array node with x,y then remainders // of those graphs. dup a, a' points at merged array // new joined parent so create new singleton pointing to it, a' - let a_: PredictionContext = SingletonPredictionContext.create(parent, a.returnState); - if (mergeCache != nil) { + let a_ = SingletonPredictionContext.create(parent, a.returnState); + if mergeCache != nil { mergeCache!.put(a, b, a_) } return a_ } else { // a != b payloads differ // see if we can collapse parents due to $+x parents if local ctx - var singleParent: PredictionContext? = nil; + var singleParent: PredictionContext? = nil //added by janyou if a === b || (a.parent != nil && a.parent! == b.parent) { // ax + bx = [a,b]x singleParent = a.parent } - if (singleParent != nil) { + if singleParent != nil { // parents are same // sort payloads and use same parent - var payloads: [Int] = [a.returnState, b.returnState]; - if (a.returnState > b.returnState) { + var payloads = [a.returnState, b.returnState] + if a.returnState > b.returnState { payloads[0] = b.returnState payloads[1] = a.returnState } - let parents: [PredictionContext?] = [singleParent, singleParent] - let a_: PredictionContext = ArrayPredictionContext(parents, payloads) - if (mergeCache != nil) { + let parents = [singleParent, singleParent] + let a_ = ArrayPredictionContext(parents, payloads) + if mergeCache != nil { mergeCache!.put(a, b, a_) } return a_ @@ -289,19 +276,19 @@ public class PredictionContext: Hashable, CustomStringConvertible { // parents differ and can't merge them. Just pack together // into array; can't merge. // ax + by = [ax,by] - var payloads: [Int] = [a.returnState, b.returnState] - var parents: [PredictionContext?] = [a.parent, b.parent]; - if (a.returnState > b.returnState) { + var payloads = [a.returnState, b.returnState] + var parents = [a.parent, b.parent] + if a.returnState > b.returnState { // sort by payload payloads[0] = b.returnState payloads[1] = a.returnState parents = [b.parent, a.parent] } if a is EmptyPredictionContext { - // print("parenet is null") + // print("parent is null") } - let a_: PredictionContext = ArrayPredictionContext(parents, payloads); - if (mergeCache != nil) { + let a_ = ArrayPredictionContext(parents, payloads) + if mergeCache != nil { mergeCache!.put(a, b, a_) } return a_ @@ -349,31 +336,29 @@ public class PredictionContext: Hashable, CustomStringConvertible { public static func mergeRoot(_ a: SingletonPredictionContext, _ b: SingletonPredictionContext, _ rootIsWildcard: Bool) -> PredictionContext? { - if (rootIsWildcard) { - if (a === PredictionContext.EMPTY) { + if rootIsWildcard { + if a === PredictionContext.EMPTY { return PredictionContext.EMPTY } // * + b = * - if (b === PredictionContext.EMPTY) { + if b === PredictionContext.EMPTY { return PredictionContext.EMPTY } // a + * = * } else { - if (a === PredictionContext.EMPTY && b === PredictionContext.EMPTY) { + if a === PredictionContext.EMPTY && b === PredictionContext.EMPTY { return PredictionContext.EMPTY } // $ + $ = $ - if (a === PredictionContext.EMPTY) { + if a === PredictionContext.EMPTY { // $ + x = [$,x] - let payloads: [Int] = [b.returnState, EMPTY_RETURN_STATE] - let parents: [PredictionContext?] = [b.parent, nil] - let joined: PredictionContext = - ArrayPredictionContext(parents, payloads) - return joined; + 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 === PredictionContext.EMPTY { // x + $ = [$,x] ($ is always first if present) - let payloads: [Int] = [a.returnState, EMPTY_RETURN_STATE] - let parents: [PredictionContext?] = [a.parent, nil] - let joined: PredictionContext = - ArrayPredictionContext(parents, payloads) + let payloads = [a.returnState, EMPTY_RETURN_STATE] + let parents = [a.parent, nil] + let joined = ArrayPredictionContext(parents, payloads) return joined } } @@ -405,30 +390,29 @@ public class PredictionContext: Hashable, CustomStringConvertible { _ rootIsWildcard: Bool, _ mergeCache: inout DoubleKeyMap?) -> PredictionContext { - if (mergeCache != nil) { - var previous: PredictionContext? = mergeCache!.get(a, b) - if (previous != nil) { + if mergeCache != nil { + var previous = mergeCache!.get(a, b) + if previous != nil { return previous! } previous = mergeCache!.get(b, a) - if (previous != nil) { + if previous != nil { return previous! } } // merge sorted payloads a + b => M - var i: Int = 0 // walks a - var j: Int = 0 // walks b - var k: Int = 0// walks target M array + var i = 0 // walks a + var j = 0 // walks b + var k = 0 // walks target M array let aReturnStatesLength = a.returnStates.count let bReturnStatesLength = b.returnStates.count let mergedReturnStatesLength = aReturnStatesLength + bReturnStatesLength - var mergedReturnStates: [Int] = [Int](repeating: 0, count: mergedReturnStatesLength) + var mergedReturnStates = [Int](repeating: 0, count: mergedReturnStatesLength) - var mergedParents: [PredictionContext?] = [PredictionContext?](repeating: nil, count: mergedReturnStatesLength) - //new PredictionContext[a.returnStates.length + b.returnStates.length]; + var mergedParents = [PredictionContext?](repeating: nil, count: mergedReturnStatesLength) // walk and merge to yield mergedParents, mergedReturnStates let aReturnStates = a.returnStates let bReturnStates = b.returnStates @@ -436,35 +420,27 @@ public class PredictionContext: Hashable, CustomStringConvertible { let bParents = b.parents while i < aReturnStatesLength && j < bReturnStatesLength { - let a_parent: PredictionContext? = aParents[i] - let b_parent: PredictionContext? = bParents[j] - if (aReturnStates[i] == bReturnStates[j]) { + let a_parent = aParents[i] + let b_parent = bParents[j] + if aReturnStates[i] == bReturnStates[j] { // same payload (stack tops are equal), must yield merged singleton - let payload: Int = aReturnStates[i] + let payload = aReturnStates[i] // $+$ = $ - var both$: Bool = (payload == EMPTY_RETURN_STATE) - both$ = both$ && a_parent == nil - both$ = both$ && b_parent == nil -// let both$: Bool = ((payload == EMPTY_RETURN_STATE) && -// a_parent == nil && b_parent == nil) - var ax_ax: Bool = (a_parent != nil && b_parent != nil) - ax_ax = ax_ax && a_parent! == b_parent! -// let ax_ax: Bool = (a_parent != nil && b_parent != nil) && a_parent! == b_parent! // ax+ax -> ax + let both$ = ((payload == EMPTY_RETURN_STATE) && a_parent == nil && b_parent == nil) + let ax_ax = (a_parent != nil && b_parent != nil && a_parent! == b_parent!) - - if (both$ || ax_ax) { + if both$ || ax_ax { mergedParents[k] = a_parent // choose left mergedReturnStates[k] = payload } else { // ax+ay -> a'[x,y] - let mergedParent: PredictionContext = - merge(a_parent!, b_parent!, rootIsWildcard, &mergeCache) + let mergedParent = merge(a_parent!, b_parent!, rootIsWildcard, &mergeCache) mergedParents[k] = mergedParent mergedReturnStates[k] = payload } i += 1 // hop over left one as usual j += 1 // but also skip one in right side since we merge - } else if (aReturnStates[i] < bReturnStates[j]) { + } else if aReturnStates[i] < bReturnStates[j] { // copy a[i] to M mergedParents[k] = a_parent mergedReturnStates[k] = aReturnStates[i] @@ -479,7 +455,7 @@ public class PredictionContext: Hashable, CustomStringConvertible { } // copy over any payloads remaining in either array - if (i < aReturnStatesLength) { + if i < aReturnStatesLength { for p in i.. String { - if (context == nil) { + if context == nil { return "" } - let buf: StringBuilder = StringBuilder() + let buf = StringBuilder() buf.append("digraph G {\n") buf.append("rankdir=LR;\n") - var nodes: Array = getAllContextNodes(context!) + var nodes = getAllContextNodes(context!) - nodes.sort(by: { $0.id > $1.id }) + nodes.sort { $0.id > $1.id } - for current: PredictionContext in nodes { - if (current is SingletonPredictionContext) { - let s: String = String(current.id) + for current in nodes { + if current is SingletonPredictionContext { + let s = String(current.id) buf.append(" s").append(s) - var returnState: String = String(current.getReturnState(0)) - if (current is EmptyPredictionContext) { + var returnState = String(current.getReturnState(0)) + if current is EmptyPredictionContext { returnState = "$" } buf.append(" [label=\"") @@ -567,17 +540,17 @@ public class PredictionContext: Hashable, CustomStringConvertible { buf.append("\"];\n") continue } - let arr: ArrayPredictionContext = current as! ArrayPredictionContext + let arr = current as! ArrayPredictionContext buf.append(" s").append(arr.id) buf.append(" [shape=box, label=\"") buf.append("[") - var first: Bool = true + var first = true let returnStates = arr.returnStates - for inv: Int in returnStates { - if (!first) { + for inv in returnStates { + if !first { buf.append(", ") } - if (inv == EMPTY_RETURN_STATE) { + if inv == EMPTY_RETURN_STATE { buf.append("$") } else { buf.append(inv) @@ -588,8 +561,8 @@ public class PredictionContext: Hashable, CustomStringConvertible { buf.append("\"];\n") } - for current: PredictionContext in nodes { - if (current === EMPTY) { + for current in nodes { + if current === EMPTY { continue } let length = current.size() @@ -597,13 +570,13 @@ public class PredictionContext: Hashable, CustomStringConvertible { guard let currentParent = current.getParent(i) else { continue } - let s: String = String(current.id) + let s = String(current.id) buf.append(" s").append(s) buf.append("->") buf.append("s") buf.append(currentParent.id) - if (current.size() > 1) { - buf.append(" [label=\"parent[\(i)]\"];\n"); + if current.size() > 1 { + buf.append(" [label=\"parent[\(i)]\"];\n") } else { buf.append(";\n") } @@ -619,23 +592,23 @@ public class PredictionContext: Hashable, CustomStringConvertible { _ context: PredictionContext, _ contextCache: PredictionContextCache, _ visited: HashMap) -> PredictionContext { - if (context.isEmpty()) { + if context.isEmpty() { return context } - var existing: PredictionContext? = visited[context] - if (existing != nil) { + var existing = visited[context] + if existing != nil { return existing! } existing = contextCache.get(context) - if (existing != nil) { + if existing != nil { visited[context] = existing! return existing! } - var changed: Bool = false - var parents: [PredictionContext?] = [PredictionContext?](repeating: nil, count: context.size()) + var changed = false + var parents = [PredictionContext?](repeating: nil, count: context.size()) let length = parents.count for i in 0.. Array { - var nodes: Array = Array() - let visited: HashMap = - HashMap() + public static func getAllContextNodes(_ context: PredictionContext) -> [PredictionContext] { + var nodes = [PredictionContext]() + let visited = HashMap() getAllContextNodes_(context, &nodes, visited) return nodes } public static func getAllContextNodes_(_ context: PredictionContext?, - _ nodes: inout Array, + _ nodes: inout [PredictionContext], _ visited: HashMap) { - //if (context == nil || visited.keys.contains(context!)) { - - guard let context = context , visited[context] == nil else { + guard let context = context, visited[context] == nil else { return } visited[context] = context @@ -723,56 +693,55 @@ public class PredictionContext: Hashable, CustomStringConvertible { // FROM SAM public func toStrings(_ recognizer: Recognizer?, _ stop: PredictionContext, _ currentState: Int) -> [String] { - var result: Array = Array() - var perm: Int = 0 + var result = [String]() + var perm = 0 outer: while true { - var offset: Int = 0 - var last: Bool = true - var p: PredictionContext = self - var stateNumber: Int = currentState - let localBuffer: StringBuilder = StringBuilder() + var offset = 0 + var last = true + var p = self + var stateNumber = currentState + let localBuffer = StringBuilder() localBuffer.append("[") while !p.isEmpty() && p !== stop { - var index: Int = 0 - if (p.size() > 0) { - var bits: Int = 1 + var index = 0 + if p.size() > 0 { + var bits = 1 while (1 << bits) < p.size() { bits += 1 } - let mask: Int = (1 << bits) - 1 + let mask = (1 << bits) - 1 index = (perm >> offset) & mask //last &= index >= p.size() - 1; //last = Bool(Int(last) & (index >= p.size() - 1)); last = last && (index >= p.size() - 1) - if (index >= p.size()) { + if index >= p.size() { continue outer } offset += bits } if let recognizer = recognizer { - if (localBuffer.length > 1) { + if localBuffer.length > 1 { // first char is '[', if more than that this isn't the first rule localBuffer.append(" ") } - let atn: ATN = recognizer.getATN() - let s: ATNState = atn.states[stateNumber]! - let ruleName: String = recognizer.getRuleNames()[s.ruleIndex!] + let atn = recognizer.getATN() + let s = atn.states[stateNumber]! + let ruleName = recognizer.getRuleNames()[s.ruleIndex!] localBuffer.append(ruleName) - } else { - if (p.getReturnState(index) != PredictionContext.EMPTY_RETURN_STATE) { - if (!p.isEmpty()) { - if (localBuffer.length > 1) { - // first char is '[', if more than that this isn't the first rule - localBuffer.append(" ") - } - - localBuffer.append(p.getReturnState(index)) + } + else if p.getReturnState(index) != PredictionContext.EMPTY_RETURN_STATE { + if !p.isEmpty() { + if localBuffer.length > 1 { + // first char is '[', if more than that this isn't the first rule + localBuffer.append(" ") } + + localBuffer.append(p.getReturnState(index)) } } stateNumber = p.getReturnState(index) @@ -781,7 +750,7 @@ public class PredictionContext: Hashable, CustomStringConvertible { localBuffer.append("]") result.append(localBuffer.toString()) - if (last) { + if last { break } @@ -792,17 +761,18 @@ public class PredictionContext: Hashable, CustomStringConvertible { } public var description: String { - return String(describing: PredictionContext.self) + "@" + String(Unmanaged.passUnretained(self).toOpaque().hashValue) } } public func ==(lhs: RuleContext, rhs: ParserRuleContext) -> Bool { - if !(lhs is ParserRuleContext) { + if let lhs = lhs as? ParserRuleContext { + return lhs === rhs + } + else { return false } - return (lhs as! ParserRuleContext) === rhs } public func ==(lhs: PredictionContext, rhs: PredictionContext) -> Bool { @@ -810,16 +780,16 @@ public func ==(lhs: PredictionContext, rhs: PredictionContext) -> Bool { if lhs === rhs { return true } - if (lhs is EmptyPredictionContext) { + if lhs is EmptyPredictionContext { return lhs === rhs } - if (lhs is SingletonPredictionContext) && (rhs is SingletonPredictionContext) { - return (lhs as! SingletonPredictionContext) == (rhs as! SingletonPredictionContext) + if let lhs = lhs as? SingletonPredictionContext, let rhs = rhs as? SingletonPredictionContext { + return lhs == rhs } - if (lhs is ArrayPredictionContext) && (rhs is ArrayPredictionContext) { - return (lhs as! ArrayPredictionContext) == (rhs as! ArrayPredictionContext) + if let lhs = lhs as? ArrayPredictionContext, let rhs = rhs as? ArrayPredictionContext { + return lhs == rhs } return false diff --git a/runtime/Swift/Sources/Antlr4/atn/PredictionMode.swift b/runtime/Swift/Sources/Antlr4/atn/PredictionMode.swift index 6967d34cc..2bbd71cd2 100644 --- a/runtime/Swift/Sources/Antlr4/atn/PredictionMode.swift +++ b/runtime/Swift/Sources/Antlr4/atn/PredictionMode.swift @@ -164,7 +164,7 @@ public enum PredictionMode { /// the configurations to strip out all of the predicates so that a standard /// _org.antlr.v4.runtime.atn.ATNConfigSet_ will merge everything ignoring predicates. /// - public static func hasSLLConflictTerminatingPrediction(_ mode: PredictionMode,_ configs: ATNConfigSet) throws -> Bool { + public static func hasSLLConflictTerminatingPrediction(_ mode: PredictionMode,_ configs: ATNConfigSet) -> Bool { var configs = configs /// /// Configs in rule stop states indicate reaching the end of the decision @@ -183,17 +183,16 @@ public enum PredictionMode { // since we'll often fail over anyway. if configs.hasSemanticContext { // dup configs, tossing out semantic predicates - configs = try configs.dupConfigsWithoutSemanticPredicates() + configs = configs.dupConfigsWithoutSemanticPredicates() } // now we have combined contexts for configs with dissimilar preds } // pure SLL or combined SLL+LL mode parsing - let altsets: Array = try getConflictingAltSubsets(configs) + let altsets = getConflictingAltSubsets(configs) - let heuristic: Bool = - try hasConflictingAltSet(altsets) && !hasStateAssociatedWithOneAlt(configs) + let heuristic = hasConflictingAltSet(altsets) && !hasStateAssociatedWithOneAlt(configs) return heuristic } @@ -364,8 +363,8 @@ public enum PredictionMode { /// we need exact ambiguity detection when the sets look like /// `A={{1,2`}} or `{{1,2`,{1,2}}}, etc... /// - public static func resolvesToJustOneViableAlt(_ altsets: Array) throws -> Int { - return try getSingleViableAlt(altsets) + public static func resolvesToJustOneViableAlt(_ altsets: [BitSet]) -> Int { + return getSingleViableAlt(altsets) } /// @@ -376,7 +375,7 @@ public enum PredictionMode { /// - returns: `true` if every _java.util.BitSet_ in `altsets` has /// _java.util.BitSet#cardinality cardinality_ > 1, otherwise `false` /// - public static func allSubsetsConflict(_ altsets: Array) -> Bool { + public static func allSubsetsConflict(_ altsets: [BitSet]) -> Bool { return !hasNonConflictingAltSet(altsets) } @@ -388,7 +387,7 @@ public enum PredictionMode { /// - returns: `true` if `altsets` contains a _java.util.BitSet_ with /// _java.util.BitSet#cardinality cardinality_ 1, otherwise `false` /// - public static func hasNonConflictingAltSet(_ altsets: Array) -> Bool { + public static func hasNonConflictingAltSet(_ altsets: [BitSet]) -> Bool { for alts: BitSet in altsets { if alts.cardinality() == 1 { return true @@ -405,7 +404,7 @@ public enum PredictionMode { /// - returns: `true` if `altsets` contains a _java.util.BitSet_ with /// _java.util.BitSet#cardinality cardinality_ > 1, otherwise `false` /// - public static func hasConflictingAltSet(_ altsets: Array) -> Bool { + public static func hasConflictingAltSet(_ altsets: [BitSet]) -> Bool { for alts: BitSet in altsets { if alts.cardinality() > 1 { return true @@ -421,7 +420,7 @@ public enum PredictionMode { /// - returns: `true` if every member of `altsets` is equal to the /// others, otherwise `false` /// - public static func allSubsetsEqual(_ altsets: Array) -> Bool { + public static func allSubsetsEqual(_ altsets: [BitSet]) -> Bool { let first: BitSet = altsets[0] for it in altsets { @@ -440,10 +439,10 @@ public enum PredictionMode { /// /// - parameter altsets: a collection of alternative subsets /// - public static func getUniqueAlt(_ altsets: Array) throws -> Int { + public static func getUniqueAlt(_ altsets: [BitSet]) -> Int { let all: BitSet = getAlts(altsets) if all.cardinality() == 1 { - return try all.nextSetBit(0) + return all.firstSetBit() } return ATN.INVALID_ALT_NUMBER } @@ -467,9 +466,8 @@ public enum PredictionMode { /// /// Get union of all alts from configs. - Since: 4.5.1 /// - public static func getAlts(_ configs: ATNConfigSet) throws -> BitSet { - - return try configs.getAltBitSet() + public static func getAlts(_ configs: ATNConfigSet) -> BitSet { + return configs.getAltBitSet() } @@ -483,9 +481,8 @@ public enum PredictionMode { /// /// - public static func getConflictingAltSubsets(_ configs: ATNConfigSet) throws -> Array { - - return try configs.getConflictingAltSubsets() + public static func getConflictingAltSubsets(_ configs: ATNConfigSet) -> [BitSet] { + return configs.getConflictingAltSubsets() } /// @@ -496,16 +493,13 @@ public enum PredictionMode { /// map[c._org.antlr.v4.runtime.atn.ATNConfig#state state_] U= c._org.antlr.v4.runtime.atn.ATNConfig#alt alt_ /// /// - public static func getStateToAltMap(_ configs: ATNConfigSet) throws -> HashMap { - - return try configs.getStateToAltMap() + public static func getStateToAltMap(_ configs: ATNConfigSet) -> HashMap { + return configs.getStateToAltMap() } - public static func hasStateAssociatedWithOneAlt(_ configs: ATNConfigSet) throws -> Bool { - let x: HashMap = try getStateToAltMap(configs) - let values = x.values - for alts: BitSet in values { - + public static func hasStateAssociatedWithOneAlt(_ configs: ATNConfigSet) -> Bool { + let x = getStateToAltMap(configs) + for alts in x.values { if alts.cardinality() == 1 { return true } @@ -513,17 +507,17 @@ public enum PredictionMode { return false } - public static func getSingleViableAlt(_ altsets: Array) throws -> Int { - let viableAlts: BitSet = BitSet() - for alts: BitSet in altsets { - let minAlt: Int = try alts.nextSetBit(0) - try viableAlts.set(minAlt) + public static func getSingleViableAlt(_ altsets: [BitSet]) -> Int { + let viableAlts = BitSet() + for alts in altsets { + let minAlt = alts.firstSetBit() + try! viableAlts.set(minAlt) if viableAlts.cardinality() > 1 { // more than 1 viable alt return ATN.INVALID_ALT_NUMBER } } - return try viableAlts.nextSetBit(0) + return viableAlts.firstSetBit() } } diff --git a/runtime/Swift/Sources/Antlr4/atn/ProfilingATNSimulator.swift b/runtime/Swift/Sources/Antlr4/atn/ProfilingATNSimulator.swift index 39e0fba64..59e082d94 100644 --- a/runtime/Swift/Sources/Antlr4/atn/ProfilingATNSimulator.swift +++ b/runtime/Swift/Sources/Antlr4/atn/ProfilingATNSimulator.swift @@ -113,7 +113,7 @@ public class ProfilingATNSimulator: ParserATNSimulator { override internal func computeTargetState(_ dfa: DFA, _ previousD: DFAState, _ t: Int) throws -> DFAState { - let state: DFAState = try super.computeTargetState(dfa, previousD, t) + let state = try super.computeTargetState(dfa, previousD, t) currentState = state return state } @@ -126,7 +126,7 @@ public class ProfilingATNSimulator: ParserATNSimulator { _llStopIndex = _input.index() } - let reachConfigs: ATNConfigSet? = try super.computeReachSet(closure, t, fullCtx) + let reachConfigs = try super.computeReachSet(closure, t, fullCtx) if fullCtx { decisions[currentDecision].LL_ATNTransitions += 1 // count computation even if error if reachConfigs != nil { @@ -152,12 +152,12 @@ public class ProfilingATNSimulator: ParserATNSimulator { override internal func evalSemanticContext(_ pred: SemanticContext, _ parserCallStack: ParserRuleContext, _ alt: Int, _ fullCtx: Bool) throws -> Bool { - let result: Bool = try super.evalSemanticContext(pred, parserCallStack, alt, fullCtx) + let result = try super.evalSemanticContext(pred, parserCallStack, alt, fullCtx) if !(pred is SemanticContext.PrecedencePredicate) { - let fullContext: Bool = _llStopIndex >= 0 - let stopIndex: Int = fullContext ? _llStopIndex : _sllStopIndex + let fullContext = _llStopIndex >= 0 + let stopIndex = fullContext ? _llStopIndex : _sllStopIndex decisions[currentDecision].predicateEvals.append( - PredicateEvalInfo(currentDecision, _input, _startIndex, stopIndex, pred, result, alt, fullCtx) + PredicateEvalInfo(currentDecision, _input, _startIndex, stopIndex, pred, result, alt, fullCtx) ) } @@ -165,34 +165,36 @@ public class ProfilingATNSimulator: ParserATNSimulator { } override - internal func reportAttemptingFullContext(_ dfa: DFA, _ conflictingAlts: BitSet?, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) throws { + internal func reportAttemptingFullContext(_ dfa: DFA, _ conflictingAlts: BitSet?, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) { if let conflictingAlts = conflictingAlts { - conflictingAltResolvedBySLL = try conflictingAlts.nextSetBit(0) + conflictingAltResolvedBySLL = conflictingAlts.firstSetBit() } else { - conflictingAltResolvedBySLL = try configs.getAlts().nextSetBit(0) + let configAlts = configs.getAlts() + conflictingAltResolvedBySLL = configAlts.firstSetBit() } decisions[currentDecision].LL_Fallback += 1 - try super.reportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex) + super.reportAttemptingFullContext(dfa, conflictingAlts, configs, startIndex, stopIndex) } override - internal func reportContextSensitivity(_ dfa: DFA, _ prediction: Int, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) throws { + internal func reportContextSensitivity(_ dfa: DFA, _ prediction: Int, _ configs: ATNConfigSet, _ startIndex: Int, _ stopIndex: Int) { if prediction != conflictingAltResolvedBySLL { decisions[currentDecision].contextSensitivities.append( ContextSensitivityInfo(currentDecision, configs, _input, startIndex, stopIndex) ) } - try super.reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex) + super.reportContextSensitivity(dfa, prediction, configs, startIndex, stopIndex) } override internal func reportAmbiguity(_ dfa: DFA, _ D: DFAState, _ startIndex: Int, _ stopIndex: Int, _ exact: Bool, - _ ambigAlts: BitSet?, _ configs: ATNConfigSet) throws { + _ ambigAlts: BitSet?, _ configs: ATNConfigSet) { var prediction: Int if let ambigAlts = ambigAlts { - prediction = try ambigAlts.nextSetBit(0) + prediction = ambigAlts.firstSetBit() } else { - prediction = try configs.getAlts().nextSetBit(0) + let configAlts = configs.getAlts() + prediction = configAlts.firstSetBit() } if configs.fullCtx && prediction != conflictingAltResolvedBySLL { // Even though this is an ambiguity we are reporting, we can @@ -208,7 +210,7 @@ public class ProfilingATNSimulator: ParserATNSimulator { AmbiguityInfo(currentDecision, configs, ambigAlts!, _input, startIndex, stopIndex, configs.fullCtx) ) - try super.reportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts!, configs) + super.reportAmbiguity(dfa, D, startIndex, stopIndex, exact, ambigAlts!, configs) } diff --git a/runtime/Swift/Sources/Antlr4/atn/RangeTransition.swift b/runtime/Swift/Sources/Antlr4/atn/RangeTransition.swift index 90d940543..ddb2c4e75 100644 --- a/runtime/Swift/Sources/Antlr4/atn/RangeTransition.swift +++ b/runtime/Swift/Sources/Antlr4/atn/RangeTransition.swift @@ -22,9 +22,8 @@ public final class RangeTransition: Transition, CustomStringConvertible { } override - //old label() - public func labelIntervalSet() throws -> IntervalSet { - return try IntervalSet.of(from, to) + public func labelIntervalSet() -> IntervalSet? { + return IntervalSet.of(from, to) } override diff --git a/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift b/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift index 4ad0bd935..261a3734e 100644 --- a/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift +++ b/runtime/Swift/Sources/Antlr4/atn/SemanticContext.swift @@ -38,8 +38,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { /// dependent predicate evaluation. /// public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { - RuntimeException(#function + " must be overridden") - return false + fatalError(#function + " must be overridden") } /// @@ -61,13 +60,13 @@ public class SemanticContext: Hashable, CustomStringConvertible { public func evalPrecedence(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> SemanticContext? { return self } + public var hashValue: Int { - RuntimeException(#function + " must be overridden") - return 0 + fatalError(#function + " must be overridden") } + public var description: String { - RuntimeException(#function + " must be overridden") - return "" + fatalError(#function + " must be overridden") } public class Predicate: SemanticContext { @@ -91,18 +90,17 @@ public class SemanticContext: Hashable, CustomStringConvertible { override public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { - let localctx: RuleContext? = isCtxDependent ? parserCallStack : nil + let localctx = isCtxDependent ? parserCallStack : nil return try parser.sempred(localctx, ruleIndex, predIndex) } override public var hashValue: Int { - var hashCode: Int = MurmurHash.initialize() + var hashCode = MurmurHash.initialize() hashCode = MurmurHash.update(hashCode, ruleIndex) hashCode = MurmurHash.update(hashCode, predIndex) hashCode = MurmurHash.update(hashCode, isCtxDependent ? 1 : 0) - hashCode = MurmurHash.finish(hashCode, 3) - return hashCode + return MurmurHash.finish(hashCode, 3) } @@ -127,12 +125,12 @@ public class SemanticContext: Hashable, CustomStringConvertible { override public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { - return try parser.precpred(parserCallStack, precedence) + return parser.precpred(parserCallStack, precedence) } override public func evalPrecedence(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> SemanticContext? { - if try parser.precpred(parserCallStack, precedence) { + if parser.precpred(parserCallStack, precedence) { return SemanticContext.NONE } else { return nil @@ -172,8 +170,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { /// public func getOperands() -> Array { - RuntimeException(" must overriden ") - return Array() + fatalError(#function + " must be overridden") } } @@ -186,7 +183,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { public let opnds: [SemanticContext] public init(_ a: SemanticContext, _ b: SemanticContext) { - var operands: Set = Set() + var operands = Set() if let aAnd = a as? AND { operands.formUnion(aAnd.opnds) } else { @@ -212,7 +209,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { } override - public func getOperands() -> Array { + public func getOperands() -> [SemanticContext] { return opnds } @@ -234,7 +231,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { /// override public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { - for opnd: SemanticContext in opnds { + for opnd in opnds { if try !opnd.eval(parser, parserCallStack) { return false } @@ -244,10 +241,10 @@ public class SemanticContext: Hashable, CustomStringConvertible { override public func evalPrecedence(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> SemanticContext? { - var differs: Bool = false - var operands: Array = Array() - for context: SemanticContext in opnds { - let evaluated: SemanticContext? = try context.evalPrecedence(parser, parserCallStack) + var differs = false + var operands = [SemanticContext]() + for context in opnds { + let evaluated = try context.evalPrecedence(parser, parserCallStack) //TODO differs |= (evaluated != context) //differs |= (evaluated != context); differs = differs || (evaluated != context) @@ -255,11 +252,10 @@ public class SemanticContext: Hashable, CustomStringConvertible { if evaluated == nil { // The AND context is false if any element is false return nil - } else { - if evaluated != SemanticContext.NONE { - // Reduce the result by skipping true elements - operands.append(evaluated!) - } + } + else if evaluated != SemanticContext.NONE { + // Reduce the result by skipping true elements + operands.append(evaluated!) } } @@ -272,7 +268,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { return SemanticContext.NONE } - var result: SemanticContext = operands[0] + var result = operands[0] let length = operands.count for i in 1.. Array { - return opnds //Arrays.asList(opnds); + public func getOperands() -> [SemanticContext] { + return opnds } @@ -347,7 +343,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { /// override public func eval(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> Bool { - for opnd: SemanticContext in opnds { + for opnd in opnds { if try opnd.eval(parser, parserCallStack) { return true } @@ -357,21 +353,18 @@ public class SemanticContext: Hashable, CustomStringConvertible { override public func evalPrecedence(_ parser: Recognizer, _ parserCallStack: RuleContext) throws -> SemanticContext? { - var differs: Bool = false - var operands: Array = Array() - for context: SemanticContext in opnds { - let evaluated: SemanticContext? = try context.evalPrecedence(parser, parserCallStack) - //differs |= (evaluated != context); + var differs = false + var operands = [SemanticContext]() + for context in opnds { + let evaluated = try context.evalPrecedence(parser, parserCallStack) differs = differs || (evaluated != context) if evaluated == SemanticContext.NONE { // The OR context is true if any element is true return SemanticContext.NONE - } else { - if evaluated != nil { - // Reduce the result by skipping false elements - operands.append(evaluated!) - //operands.add(evaluated); - } + } + else if let evaluated = evaluated { + // Reduce the result by skipping false elements + operands.append(evaluated) } } @@ -384,7 +377,7 @@ public class SemanticContext: Hashable, CustomStringConvertible { return nil } - var result: SemanticContext = operands[0] + var result = operands[0] let length = operands.count for i in 1.. IntervalSet { + public func labelIntervalSet() -> IntervalSet? { return set } diff --git a/runtime/Swift/Sources/Antlr4/atn/Transition.swift b/runtime/Swift/Sources/Antlr4/atn/Transition.swift index 7e7b07e2e..75cc5cefa 100644 --- a/runtime/Swift/Sources/Antlr4/atn/Transition.swift +++ b/runtime/Swift/Sources/Antlr4/atn/Transition.swift @@ -82,8 +82,7 @@ public class Transition { } public func getSerializationType() -> Int { - RuntimeException(#function + " must be overridden") - fatalError() + fatalError(#function + " must be overridden") } /// @@ -100,12 +99,11 @@ public class Transition { } - public func labelIntervalSet() throws -> IntervalSet? { + public func labelIntervalSet() -> IntervalSet? { return nil } public func matches(_ symbol: Int, _ minVocabSymbol: Int, _ maxVocabSymbol: Int) -> Bool { - RuntimeException(#function + " must be overridden") - fatalError() + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/dfa/DFA.swift b/runtime/Swift/Sources/Antlr4/dfa/DFA.swift index 8c608f543..3f8096ca1 100644 --- a/runtime/Swift/Sources/Antlr4/dfa/DFA.swift +++ b/runtime/Swift/Sources/Antlr4/dfa/DFA.swift @@ -170,23 +170,12 @@ public class DFA: CustomStringConvertible { return description } - /// - /// - Use _#toString(org.antlr.v4.runtime.Vocabulary)_ instead. - /// - public func toString(_ tokenNames: [String?]?) -> String { - if s0 == nil { - return "" - } - let serializer: DFASerializer = DFASerializer(self, tokenNames) - return serializer.toString() - } - public func toString(_ vocabulary: Vocabulary) -> String { if s0 == nil { return "" } - let serializer: DFASerializer = DFASerializer(self, vocabulary) + let serializer = DFASerializer(self, vocabulary) return serializer.toString() } @@ -194,7 +183,7 @@ public class DFA: CustomStringConvertible { if s0 == nil { return "" } - let serializer: DFASerializer = LexerDFASerializer(self) + let serializer = LexerDFASerializer(self) return serializer.toString() } diff --git a/runtime/Swift/Sources/Antlr4/dfa/DFASerializer.swift b/runtime/Swift/Sources/Antlr4/dfa/DFASerializer.swift index 6639e1bbd..3e19850de 100644 --- a/runtime/Swift/Sources/Antlr4/dfa/DFASerializer.swift +++ b/runtime/Swift/Sources/Antlr4/dfa/DFASerializer.swift @@ -10,19 +10,9 @@ /// public class DFASerializer: CustomStringConvertible { - private let dfa: DFA - private let vocabulary: Vocabulary - /// - /// - Use _#DFASerializer(org.antlr.v4.runtime.dfa.DFA, org.antlr.v4.runtime.Vocabulary)_ instead. - /// - //@Deprecated - public convenience init(_ dfa: DFA, _ tokenNames: [String?]?) { - self.init(dfa, Vocabulary.fromTokenNames(tokenNames)) - } - public init(_ dfa: DFA, _ vocabulary: Vocabulary) { self.dfa = dfa self.vocabulary = vocabulary @@ -32,18 +22,17 @@ public class DFASerializer: CustomStringConvertible { if dfa.s0 == nil { return "" } - let buf: StringBuilder = StringBuilder() - let states: Array = dfa.getStates() - for s: DFAState in states { - var n: Int = 0 - if let sEdges = s.edges { - n = sEdges.count + let buf = StringBuilder() + let states = dfa.getStates() + for s in states { + guard let edges = s.edges else { + continue } + let n = edges.count for i in 0..") @@ -53,7 +42,7 @@ public class DFASerializer: CustomStringConvertible { } } - let output: String = buf.toString() + let output = buf.toString() if output.length == 0 { return "" } @@ -72,16 +61,16 @@ public class DFASerializer: CustomStringConvertible { internal func getStateString(_ s: DFAState) -> String { - let n: Int = s.stateNumber + let n = s.stateNumber let s1 = s.isAcceptState ? ":" : "" let s2 = s.requiresFullContext ? "^" : "" - let baseStateStr: String = s1 + "s" + String(n) + s2 + let baseStateStr = s1 + "s" + String(n) + s2 if s.isAcceptState { if let predicates = s.predicates { return baseStateStr + "=>\(predicates)" } else { - return baseStateStr + "=>\(s.prediction!)" + return baseStateStr + "=>\(s.prediction)" } } else { return baseStateStr diff --git a/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift b/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift index 35cdc958e..f0a09c4d4 100644 --- a/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift +++ b/runtime/Swift/Sources/Antlr4/dfa/DFAState.swift @@ -32,10 +32,9 @@ /// public class DFAState: Hashable, CustomStringConvertible { - public var stateNumber: Int = -1 + public var stateNumber = -1 - - public var configs: ATNConfigSet = ATNConfigSet() + public var configs = ATNConfigSet() /// /// `edges[symbol]` points to target of symbol. Shift up by 1 so (-1) @@ -43,14 +42,14 @@ public class DFAState: Hashable, CustomStringConvertible { /// public var edges: [DFAState?]! - public var isAcceptState: Bool = false + public 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 var prediction: Int! = 0 + public var prediction = 0 public var lexerActionExecutor: LexerActionExecutor! @@ -60,7 +59,7 @@ public class DFAState: Hashable, CustomStringConvertible { /// _org.antlr.v4.runtime.atn.ParserATNSimulator#execATN_ invocations immediately jumped doing /// full context prediction if this field is true. /// - public var requiresFullContext: Bool = false + public var requiresFullContext = false /// /// During SLL parsing, this is a list of predicates associated with the @@ -83,20 +82,17 @@ public class DFAState: Hashable, CustomStringConvertible { /// public class PredPrediction: CustomStringConvertible { - public final var pred: SemanticContext // never null; at least SemanticContext.NONE public final var alt: Int + public init(_ pred: SemanticContext, _ alt: Int) { self.alt = alt self.pred = pred } - public var description: String { - return "(\(pred),\(alt))" - } } @@ -116,18 +112,14 @@ public class DFAState: Hashable, CustomStringConvertible { /// DFA state. /// public func getAltSet() -> Set? { - - let alts = configs.getAltSet() - - return alts + return configs.getAltSet() } public var hashValue: Int { - var hash: Int = MurmurHash.initialize(7) + var hash = MurmurHash.initialize(7) hash = MurmurHash.update(hash, configs.hashValue) - hash = MurmurHash.finish(hash, 1) - return hash + return MurmurHash.finish(hash, 1) } /// @@ -144,7 +136,7 @@ public class DFAState: Hashable, CustomStringConvertible { /// _#stateNumber_ is irrelevant. /// public var description: String { - let buf: StringBuilder = StringBuilder() + let buf = StringBuilder() buf.append(stateNumber).append(":").append(configs) if isAcceptState { buf.append("=>") @@ -156,15 +148,11 @@ public class DFAState: Hashable, CustomStringConvertible { } return buf.toString() } - - } public func ==(lhs: DFAState, rhs: DFAState) -> Bool { - if lhs === rhs { return true } - let sameSet: Bool = lhs.configs == rhs.configs - return sameSet + return (lhs.configs == rhs.configs) } diff --git a/runtime/Swift/Sources/Antlr4/misc/BitSet.swift b/runtime/Swift/Sources/Antlr4/misc/BitSet.swift index c68b698d0..4f9c5f899 100644 --- a/runtime/Swift/Sources/Antlr4/misc/BitSet.swift +++ b/runtime/Swift/Sources/Antlr4/misc/BitSet.swift @@ -592,7 +592,14 @@ public class BitSet: Hashable, CustomStringConvertible { return result } - /// + /// + /// Equivalent to nextSetBit(0), but guaranteed not to throw an exception. + /// + public func firstSetBit() -> Int { + return try! nextSetBit(0) + } + + /// /// Returns the index of the first bit that is set to `true` /// that occurs on or after the specified starting index. If no such /// bit exists then `-1` is returned. @@ -601,7 +608,7 @@ public class BitSet: Hashable, CustomStringConvertible { /// use the following loop: /// /// ` - /// for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { + /// for (int i = bs.firstSetBit(); i >= 0; i = bs.nextSetBit(i+1)) { /// // operate on index i here /// `} /// @@ -1114,24 +1121,20 @@ public class BitSet: Hashable, CustomStringConvertible { //let numBits: Int = (wordsInUse > 128) ? // cardinality() : wordsInUse * BitSet.BITS_PER_WORD - let b: StringBuilder = StringBuilder() + let b = StringBuilder() b.append("{") - do { - var i: Int = try nextSetBit(0) - if i != -1 { - b.append(i) - i = try nextSetBit(i + 1) - while i >= 0 { - let endOfRun: Int = try nextClearBit(i) - repeat { - b.append(", ").append(i) - i += 1 - } while i < endOfRun - i = try nextSetBit(i + 1) - } + var i = firstSetBit() + if i != -1 { + b.append(i) + i = try! nextSetBit(i + 1) + while i >= 0 { + let endOfRun = try! nextClearBit(i) + repeat { + b.append(", ").append(i) + i += 1 + } while i < endOfRun + i = try! nextSetBit(i + 1) } - } catch { - print("BitSet description error") } b.append("}") return b.toString() diff --git a/runtime/Swift/Sources/Antlr4/misc/HashMap.swift b/runtime/Swift/Sources/Antlr4/misc/HashMap.swift index 0157d8d56..a7cba83f7 100644 --- a/runtime/Swift/Sources/Antlr4/misc/HashMap.swift +++ b/runtime/Swift/Sources/Antlr4/misc/HashMap.swift @@ -74,19 +74,19 @@ public final class HashMap: Sequence /// /// The default initial capacity - MUST be a power of two. /// - let DEFAULT_INITIAL_CAPACITY: Int = 16 + private let DEFAULT_INITIAL_CAPACITY: Int = 16 /// /// The maximum capacity, used if a higher value is implicitly specified /// by either of the constructors with arguments. /// MUST be a power of two <= 1<<30. /// - let MAXIMUM_CAPACITY: Int = 1 << 30 + private let MAXIMUM_CAPACITY: Int = 1 << 30 /// /// The load factor used when none specified in constructor. /// - let DEFAULT_LOAD_FACTOR: Float = 0.75 + private let DEFAULT_LOAD_FACTOR: Float = 0.75 /// /// The table, resized as necessary. Length MUST Always be a power of two. diff --git a/runtime/Swift/Sources/Antlr4/misc/IntSet.swift b/runtime/Swift/Sources/Antlr4/misc/IntSet.swift index aa9848ac0..cc448593f 100644 --- a/runtime/Swift/Sources/Antlr4/misc/IntSet.swift +++ b/runtime/Swift/Sources/Antlr4/misc/IntSet.swift @@ -43,7 +43,7 @@ public protocol IntSet { /// current set and `a`. The value `null` may be returned in /// place of an empty result set. /// - func and(_ a: IntSet?) throws -> IntSet? + func and(_ a: IntSet?) -> IntSet? /// /// Return a new _org.antlr.v4.runtime.misc.IntSet_ object containing all elements that are @@ -60,7 +60,7 @@ public protocol IntSet { /// `elements` but not present in the current set. The value /// `null` may be returned in place of an empty result set. /// - func complement(_ elements: IntSet?) throws -> IntSet? + func complement(_ elements: IntSet?) -> IntSet? /// /// Return a new _org.antlr.v4.runtime.misc.IntSet_ object containing all elements that are @@ -76,7 +76,7 @@ public protocol IntSet { /// set and `a`. The value `null` may be returned in place of an /// empty result set. /// - func or(_ a: IntSet) throws -> IntSet + func or(_ a: IntSet) -> IntSet /// /// Return a new _org.antlr.v4.runtime.misc.IntSet_ object containing all elements that are @@ -93,7 +93,7 @@ public protocol IntSet { /// `elements` but not present in the current set. The value /// `null` may be returned in place of an empty result set. /// - func subtract(_ a: IntSet?) throws -> IntSet + func subtract(_ a: IntSet?) -> IntSet /// /// Return the total number of elements represented by the current set. @@ -145,7 +145,7 @@ public protocol IntSet { /// - returns: A list containing all element present in the current set, sorted /// in ascending numerical order. /// - func toList() -> Array + func toList() -> [Int] func toString() -> String } diff --git a/runtime/Swift/Sources/Antlr4/misc/IntervalSet.swift b/runtime/Swift/Sources/Antlr4/misc/IntervalSet.swift index 36f629e23..345f829cc 100644 --- a/runtime/Swift/Sources/Antlr4/misc/IntervalSet.swift +++ b/runtime/Swift/Sources/Antlr4/misc/IntervalSet.swift @@ -21,13 +21,13 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { public static let COMPLETE_CHAR_SET: IntervalSet = { - let set = try! IntervalSet.of(Lexer.MIN_CHAR_VALUE, Lexer.MAX_CHAR_VALUE) + let set = IntervalSet.of(Lexer.MIN_CHAR_VALUE, Lexer.MAX_CHAR_VALUE) try! set.setReadonly(true) return set }() public static let EMPTY_SET: IntervalSet = { - let set = try! IntervalSet() + let set = IntervalSet() try! set.setReadonly(true) return set }() @@ -36,47 +36,36 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// /// The list of sorted, disjoint intervals. /// - internal var intervals: Array + internal var intervals: [Interval] - internal var readonly: Bool = false - - public init(_ intervals: Array) { + internal var readonly = false + public init(_ intervals: [Interval]) { self.intervals = intervals } - public convenience init(_ set: IntervalSet) throws { - try self.init() - try addAll(set) + public convenience init(_ set: IntervalSet) { + self.init() + try! addAll(set) } - public init(_ els: Int...) throws { - if els.count == 0 { - intervals = Array() // most sets are 1 or 2 elements + public init(_ els: Int...) { + if els.isEmpty { + intervals = [Interval]() // most sets are 1 or 2 elements } else { - intervals = Array() - for e: Int in els { - try add(e) + intervals = [Interval]() + for e in els { + try! add(e) } } } - /// - /// Create a set with a single element, el. - /// - - public static func of(_ a: Int) throws -> IntervalSet { - let s: IntervalSet = try IntervalSet() - try s.add(a) - return s - } - - /// + /// /// Create a set with all ints within range [a..b] (inclusive) /// - public static func of(_ a: Int, _ b: Int) throws -> IntervalSet { - let s: IntervalSet = try IntervalSet() - try s.add(a, b) + public static func of(_ a: Int, _ b: Int) -> IntervalSet { + let s = IntervalSet() + try! s.add(a, b) return s } @@ -96,7 +85,7 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { if readonly { throw ANTLRError.illegalState(msg: "can't alter readonly IntervalSet") } - try add(el, el) + try! add(el, el) } /// @@ -126,21 +115,20 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { while i < intervals.count { - let r: Interval = intervals[i] + let r = intervals[i] if addition == r { return } if addition.adjacent(r) || !addition.disjoint(r) { // next to each other, make a single larger interval - let bigger: Interval = addition.union(r) + let bigger = addition.union(r) //iter.set(bigger); intervals[i] = bigger // make sure we didn't just create an interval that // should be merged with next interval in list - //while iter.hasNext() { while i < intervals.count - 1 { i += 1 - let next: Interval = intervals[i] //iter.next(); + let next = intervals[i] if !bigger.adjacent(next) && bigger.disjoint(next) { break } @@ -155,14 +143,11 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { intervals.remove(at: i) i -= 1 intervals[i] = bigger.union(next) - } return } if addition.startsBeforeDisjoint(r) { // insert before r - //iter.previous(); - //iter.add(addition); intervals.insert(addition, at: i) return } @@ -178,10 +163,10 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// /// combine all sets in the array returned the or'd value /// - public func or(_ sets: [IntervalSet]) throws -> IntSet { - let r: IntervalSet = try IntervalSet() - for s: IntervalSet in sets { - try r.addAll(s) + public func or(_ sets: [IntervalSet]) -> IntSet { + let r = IntervalSet() + for s in sets { + try! r.addAll(s) } return r } @@ -194,14 +179,12 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { } if let other = set as? IntervalSet { // walk set and add each interval - let n: Int = other.intervals.count - for i in 0.. IntSet? { - return try self.complement(IntervalSet.of(minElement, maxElement)) + public func complement(_ minElement: Int, _ maxElement: Int) -> IntSet? { + return complement(IntervalSet.of(minElement, maxElement)) } - /// + /// /// /// - public func complement(_ vocabulary: IntSet?) throws -> IntSet? { - guard let vocabulary = vocabulary , !vocabulary.isNil() else { + public func complement(_ vocabulary: IntSet?) -> IntSet? { + guard let vocabulary = vocabulary, !vocabulary.isNil() else { return nil // nothing in common with null set } var vocabularyIS: IntervalSet if let vocabulary = vocabulary as? IntervalSet { vocabularyIS = vocabulary } else { - vocabularyIS = try IntervalSet() - try vocabularyIS.addAll(vocabulary) + vocabularyIS = IntervalSet() + try! vocabularyIS.addAll(vocabulary) } - return try vocabularyIS.subtract(self) + return vocabularyIS.subtract(self) } - public func subtract(_ a: IntSet?) throws -> IntSet { - guard let a = a , !a.isNil() else { - return try IntervalSet(self) + public func subtract(_ a: IntSet?) -> IntSet { + guard let a = a, !a.isNil() else { + return IntervalSet(self) } if let a = a as? IntervalSet { - return try subtract(self, a) + return subtract(self, a) } - let other: IntervalSet = try IntervalSet() - try other.addAll(a) - return try subtract(self, other) + let other = IntervalSet() + try! other.addAll(a) + return subtract(self, other) } /// @@ -252,23 +235,23 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// `null`, it is treated as though it was an empty set. /// - public func subtract(_ left: IntervalSet?, _ right: IntervalSet?) throws -> IntervalSet { + public func subtract(_ left: IntervalSet?, _ right: IntervalSet?) -> IntervalSet { - guard let left = left , !left.isNil() else { - return try IntervalSet() + guard let left = left, !left.isNil() else { + return IntervalSet() } - let result: IntervalSet = try IntervalSet(left) + let result = IntervalSet(left) - guard let right = right , !right.isNil() else { + guard let right = right, !right.isNil() else { // right set has no elements; just return the copy of the current set return result } - var resultI: Int = 0 - var rightI: Int = 0 + var resultI = 0 + var rightI = 0 while resultI < result.intervals.count && rightI < right.intervals.count { - let resultInterval: Interval = result.intervals[resultI] - let rightInterval: Interval = right.intervals[rightI] + let resultInterval = result.intervals[resultI] + let rightInterval = right.intervals[rightI] // operation: (resultInterval - rightInterval) and update indexes @@ -296,9 +279,7 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { if let afterCurrent = afterCurrent { // split the current interval into two result.intervals[resultI] = beforeCurrent - //result.intervals.set(beforeCurrent,resultI); result.intervals.insert(afterCurrent, at: resultI + 1) - //result.intervals.add(, afterCurrent); resultI += 1 rightI += 1 continue @@ -330,10 +311,10 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { } - public func or(_ a: IntSet) throws -> IntSet { - let o: IntervalSet = try IntervalSet() - try o.addAll(self) - try o.addAll(a) + public func or(_ a: IntSet) -> IntSet { + let o = IntervalSet() + try! o.addAll(self) + try! o.addAll(a) return o } @@ -341,24 +322,23 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// /// - public func and(_ other: IntSet?) throws -> IntSet? { + public func and(_ other: IntSet?) -> IntSet? { if other == nil { - //|| !(other instanceof IntervalSet) ) { return nil // nothing in common with null set } - var myIntervals: Array = self.intervals - var theirIntervals: Array = (other as! IntervalSet).intervals + var myIntervals = self.intervals + var theirIntervals = (other as! IntervalSet).intervals var intersection: IntervalSet? = nil - let mySize: Int = myIntervals.count - let theirSize: Int = theirIntervals.count - var i: Int = 0 - var j: Int = 0 + let mySize = myIntervals.count + let theirSize = theirIntervals.count + var i = 0 + var j = 0 // iterate down both interval lists looking for nondisjoint intervals while i < mySize && j < theirSize { - let mine: Interval = myIntervals[i] - let theirs: Interval = theirIntervals[j] - //System.out.println("mine="+mine+" and theirs="+theirs); + let mine = myIntervals[i] + let theirs = theirIntervals[j] + if mine.startsBeforeDisjoint(theirs) { // move this iterator looking for interval that might overlap i += 1 @@ -370,26 +350,26 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { if mine.properlyContains(theirs) { // overlap, add intersection, get next theirs if intersection == nil { - intersection = try IntervalSet() + intersection = IntervalSet() } - try intersection!.add(mine.intersection(theirs)) + try! intersection!.add(mine.intersection(theirs)) j += 1 } else { if theirs.properlyContains(mine) { // overlap, add intersection, get next mine if intersection == nil { - intersection = try IntervalSet() + intersection = IntervalSet() } - try intersection!.add(mine.intersection(theirs)) + try! intersection!.add(mine.intersection(theirs)) i += 1 } else { if !mine.disjoint(theirs) { // overlap, add intersection if intersection == nil { - intersection = try IntervalSet() + intersection = IntervalSet() } - try intersection!.add(mine.intersection(theirs)) + try! intersection!.add(mine.intersection(theirs)) // Move the iterator of lower range [a..b], but not // the upper range as it may contain elements that will collide // with the next iterator. So, if mine=[0..115] and @@ -411,7 +391,7 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { } } if intersection == nil { - return try IntervalSet() + return IntervalSet() } return intersection } @@ -421,11 +401,9 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// public func contains(_ el: Int) -> Bool { - let n: Int = intervals.count - for i in 0..=I.a && el<=I.b ) { -/// return true; // found in this interval -/// } -/// } -/// return false; -/// } /// @@ -461,11 +427,10 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// public func getSingleElement() -> Int { - //intervals=nil && intervals.count==1 ) if intervals.count == 1 { - let I: Interval = intervals[0] - if I.a == I.b { - return I.a + let interval = intervals[0] + if interval.a == interval.b { + return interval.a } } return CommonToken.INVALID_TYPE @@ -481,7 +446,7 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { if isNil() { return CommonToken.INVALID_TYPE } - let last: Interval = intervals[intervals.count - 1] + let last = intervals[intervals.count - 1] return last.b } @@ -502,30 +467,28 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// /// Return a list of Interval objects. /// - public func getIntervals() -> Array { + public func getIntervals() -> [Interval] { return intervals } public func hashCode() -> Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() for I: Interval in intervals { hash = MurmurHash.update(hash, I.a) hash = MurmurHash.update(hash, I.b) } - hash = MurmurHash.finish(hash, intervals.count * 2) - return hash + return MurmurHash.finish(hash, intervals.count * 2) } public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() for I: Interval in intervals { hash = MurmurHash.update(hash, I.a) hash = MurmurHash.update(hash, I.b) } - hash = MurmurHash.finish(hash, intervals.count * 2) - return hash + return MurmurHash.finish(hash, intervals.count * 2) } /// /// Are two IntervalSets equal? Because all intervals are sorted @@ -551,25 +514,21 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { } public func toString(_ elemAreChar: Bool) -> String { - let buf: StringBuilder = StringBuilder() - //if ( self.intervals==nil || self.intervals.isEmpty() ) { + let buf = StringBuilder() if self.intervals.isEmpty { return "{}" } if self.size() > 1 { buf.append("{") } - //var iter : Iterator = self.intervals.iterator(); - //while iter.hasNext() { var first = true - for I: Interval in intervals { + for interval in intervals { if !first { buf.append(", ") } first = false - //var I : Interval = iter.next(); - let a: Int = I.a - let b: Int = I.b + let a = interval.a + let b = interval.b if a == b { if a == CommonToken.EOF { buf.append("") @@ -587,9 +546,6 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { buf.append(a).append("..").append(b) } } - //if ( iter.hasNext() ) { - // buf.append(", "); - //} } if self.size() > 1 { buf.append("}") @@ -597,16 +553,8 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { return buf.toString() } - /// - /// - Use _#toString(org.antlr.v4.runtime.Vocabulary)_ instead. - /// /@Deprecated - /// - public func toString(_ tokenNames: [String?]?) -> String { - return toString(Vocabulary.fromTokenNames(tokenNames)) - } - public func toString(_ vocabulary: Vocabulary) -> String { - let buf: StringBuilder = StringBuilder() + let buf = StringBuilder() if self.intervals.isEmpty { return "{}" @@ -616,14 +564,14 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { } var first = true - for I: Interval in intervals { + for interval in intervals { if !first { buf.append(", ") } first = false - //var I : Interval = iter.next(); - let a: Int = I.a - let b: Int = I.b + + let a = interval.a + let b = interval.b if a == b { buf.append(elementName(vocabulary, a)) } else { @@ -642,15 +590,6 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { return buf.toString() } - /// - /// - Use _#elementName(org.antlr.v4.runtime.Vocabulary, int)_ instead. - /// /@Deprecated - /// - internal func elementName(_ tokenNames: [String?]?, _ a: Int) -> String { - return elementName(Vocabulary.fromTokenNames(tokenNames), a) - } - - internal func elementName(_ vocabulary: Vocabulary, _ a: Int) -> String { if a == CommonToken.EOF { return "" @@ -665,43 +604,25 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { public func size() -> Int { - var n: Int = 0 - let numIntervals: Int = intervals.count + var n = 0 + let numIntervals = intervals.count if numIntervals == 1 { - let firstInterval: Interval = self.intervals[0] + let firstInterval = intervals[0] return firstInterval.b - firstInterval.a + 1 } for i in 0.. Array { - var values: Array = Array() - let n: Int = intervals.count - for i in 0.. Array { - var values: Array = Array() - let n: Int = intervals.count - for i in 0.. [Int] { + var values = [Int]() + for interval in intervals { + let a = interval.a + let b = interval.b for v in a...b { values.append(v) @@ -711,13 +632,12 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { } public func toSet() -> Set { - var s: Set = Set() - for I: Interval in intervals { - let a: Int = I.a - let b: Int = I.b + var s = Set() + for interval in intervals { + let a = interval.a + let b = interval.b for v in a...b { s.insert(v) - //s.add(v); } } return s @@ -729,12 +649,10 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible { /// ANTLR code gen target. /// public func get(_ i: Int) -> Int { - let n: Int = intervals.count - var index: Int = 0 - for j in 0.. [Int] { - return toIntegerList() - } - - public func remove(_ el: Int) throws { if readonly { throw ANTLRError.illegalState(msg: "can't alter readonly IntervalSet") } - let n: Int = intervals.count - for i in 0.. a && el < b { // found in this interval - let oldb: Int = I.b - I.b = el - 1 // [a..x-1] + let oldb = interval.b + interval.b = el - 1 // [a..x-1] try add(el + 1, oldb) // add [x+1..b] } } diff --git a/runtime/Swift/Sources/Antlr4/misc/MurmurHash.swift b/runtime/Swift/Sources/Antlr4/misc/MurmurHash.swift index 1bdbcd426..1386e8f09 100644 --- a/runtime/Swift/Sources/Antlr4/misc/MurmurHash.swift +++ b/runtime/Swift/Sources/Antlr4/misc/MurmurHash.swift @@ -6,20 +6,28 @@ /// +/// https://en.wikipedia.org/wiki/MurmurHash /// /// - Author: Sam Harwell /// public final class MurmurHash { - private static let DEFAULT_SEED: Int = 0 + private static let DEFAULT_SEED: UInt32 = 0 + + private static let c1 = UInt32(0xCC9E2D51) + private static let c2 = UInt32(0x1B873593) + private static let r1 = UInt32(15) + private static let r2 = UInt32(13) + private static let m = UInt32(5) + private static let n = UInt32(0xE6546B64) /// /// Initialize the hash using the default seed value. /// /// - Returns: the intermediate hash value /// - public static func initialize() -> Int { + public static func initialize() -> UInt32 { return initialize(DEFAULT_SEED) } @@ -29,10 +37,18 @@ public final class MurmurHash { /// - Parameter seed: the seed /// - Returns: the intermediate hash value /// - public static func initialize(_ seed: Int) -> Int { + public static func initialize(_ seed: UInt32) -> UInt32 { return seed } + private static func calcK(_ value: UInt32) -> UInt32 { + var k = value + k = k &* c1 + k = (k << r1) | (k >> (32 - r1)) + k = k &* c2 + return k + } + /// /// Update the intermediate hash value for the next input `value`. /// @@ -40,31 +56,14 @@ public final class MurmurHash { /// - Parameter value: the value to add to the current hash /// - Returns: the updated intermediate hash value /// - public static func update2(_ hashIn: Int, _ value: Int) -> Int { - - let c1: Int32 = -862048943//0xCC9E2D51; - let c2: Int32 = 0x1B873593 - let r1: Int32 = 15 - let r2: Int32 = 13 - let m: Int32 = 5 - let n: Int32 = -430675100//0xE6546B64; - - var k: Int32 = Int32(truncatingIfNeeded: value) - k = k.multipliedReportingOverflow(by: c1).partialValue - // (k,_) = UInt32.multiplyWithOverflow(k, c1) ;//( k * c1); - //TODO: CHECKE >>> - k = (k << r1) | (k >>> (Int32(32) - r1)) //k = (k << r1) | (k >>> (32 - r1)); - //k = UInt32 (truncatingBitPattern:Int64(Int64(k) * Int64(c2)));//( k * c2); - //(k,_) = UInt32.multiplyWithOverflow(k, c2) - k = k.multipliedReportingOverflow(by: c2).partialValue - var hash = Int32(hashIn) + public static func update2(_ hashIn: UInt32, _ value: Int) -> UInt32 { + let k = calcK(UInt32(truncatingIfNeeded: value)) + var hash = hashIn hash = hash ^ k - hash = (hash << r2) | (hash >>> (Int32(32) - r2))//hash = (hash << r2) | (hash >>> (32 - r2)); - hash = hash.multipliedReportingOverflow(by: m).partialValue - hash = hash.addingReportingOverflow(n).partialValue - //hash = hash * m + n; + hash = (hash << r2) | (hash >> (32 - r2)) + hash = hash &* m &+ n // print("murmur update2 : \(hash)") - return Int(hash) + return hash } /// @@ -74,9 +73,8 @@ public final class MurmurHash { /// - Parameter value: the value to add to the current hash /// - Returns: the updated intermediate hash value /// - public static func update(_ hash: Int, _ value: T?) -> Int { + public static func update(_ hash: UInt32, _ value: T?) -> UInt32 { return update2(hash, value != nil ? value!.hashValue : 0) - // return update2(hash, value); } /// @@ -84,21 +82,24 @@ public final class MurmurHash { /// to form the final result of the MurmurHash 3 hash function. /// /// - Parameter hash: the intermediate hash value - /// - Parameter numberOfWords: the number of integer values added to the hash + /// - Parameter numberOfWords: the number of UInt32 values added to the hash /// - Returns: the final hash result /// - public static func finish(_ hashin: Int, _ numberOfWordsIn: Int) -> Int { - var hash = Int32(hashin) - let numberOfWords = Int32(numberOfWordsIn) - hash = hash ^ numberOfWords.multipliedReportingOverflow(by: 4).partialValue //(numberOfWords * UInt32(4)); - hash = hash ^ (hash >>> Int32(16)) //hash = hash ^ (hash >>> 16); - hash = hash.multipliedReportingOverflow(by: -2048144789).partialValue //hash * UInt32(0x85EBCA6B); - hash = hash ^ (hash >>> Int32(13))//hash = hash ^ (hash >>> 13); - //hash = UInt32(truncatingBitPattern: UInt64(hash) * UInt64(0xC2B2AE35)) ; - hash = hash.multipliedReportingOverflow(by: -1028477387).partialValue - hash = hash ^ (hash >>> Int32(16))// hash = hash ^ (hash >>> 16); + public static func finish(_ hashin: UInt32, _ numberOfWords: Int) -> Int { + return Int(finish(hashin, byteCount: (numberOfWords &* 4))) + } + + private static func finish(_ hashin: UInt32, byteCount byteCountInt: Int) -> UInt32 { + let byteCount = UInt32(truncatingIfNeeded: byteCountInt) + var hash = hashin + hash ^= byteCount + hash ^= (hash >> 16) + hash = hash &* 0x85EBCA6B + hash ^= (hash >> 13) + hash = hash &* 0xC2B2AE35 + hash ^= (hash >> 16) //print("murmur finish : \(hash)") - return Int(hash) + return hash } /// @@ -111,14 +112,55 @@ public final class MurmurHash { /// - Returns: the hash code of the data /// public static func hashCode(_ data: [T], _ seed: Int) -> Int { - var hash: Int = initialize(seed) - for value: T in data { - //var hashValue = value != nil ? value.hashValue : 0 - hash = update(hash, value.hashValue) + var hash = initialize(UInt32(truncatingIfNeeded: seed)) + for value in data { + hash = update(hash, value) } - hash = finish(hash, data.count) - return hash + return finish(hash, data.count) + } + + /// + /// Compute a hash for the given String and seed. The String is encoded + /// using UTF-8, then the bytes are interpreted as unsigned 32-bit + /// little-endian values, giving UInt32 values for the update call. + /// + /// If the bytes do not evenly divide by 4, the final bytes are treated + /// slightly differently (not doing the final rotate / multiply / add). + /// + /// This matches the treatment of byte sequences in publicly available + /// test patterns (see MurmurHashTests.swift) and the example code on + /// Wikipedia. + /// + public static func hashString(_ s: String, _ seed: UInt32) -> UInt32 { + let bytes = Array(s.utf8) + return hashBytesLittleEndian(bytes, seed) + } + + private static func hashBytesLittleEndian(_ bytes: [UInt8], _ seed: UInt32) -> UInt32 { + let byteCount = bytes.count + + var hash = seed + for i in stride(from: 0, to: byteCount - 3, by: 4) { + var word = UInt32(bytes[i]) + word |= UInt32(bytes[i + 1]) << 8 + word |= UInt32(bytes[i + 2]) << 16 + word |= UInt32(bytes[i + 3]) << 24 + + hash = update(hash, word) + } + let remaining = byteCount & 3 + if remaining != 0 { + var lastWord = UInt32(0) + for r in 0 ..< remaining { + lastWord |= UInt32(bytes[byteCount - 1 - r]) << (8 * (remaining - 1 - r)) + } + + let k = calcK(lastWord) + hash ^= k + } + + return finish(hash, byteCount: byteCount) } private init() { diff --git a/runtime/Swift/Sources/Antlr4/misc/Triple.swift b/runtime/Swift/Sources/Antlr4/misc/Triple.swift index 871a6a50d..a05366038 100644 --- a/runtime/Swift/Sources/Antlr4/misc/Triple.swift +++ b/runtime/Swift/Sources/Antlr4/misc/Triple.swift @@ -16,7 +16,7 @@ public class Triple: Hashable, CustomStringC self.c = c } public var hashValue: Int { - var hash: Int = MurmurHash.initialize() + var hash = MurmurHash.initialize() hash = MurmurHash.update(hash, a) hash = MurmurHash.update(hash, b) hash = MurmurHash.update(hash, c) diff --git a/runtime/Swift/Sources/Antlr4/misc/Utils.swift b/runtime/Swift/Sources/Antlr4/misc/Utils.swift index bc1ac15ff..c025becdc 100644 --- a/runtime/Swift/Sources/Antlr4/misc/Utils.swift +++ b/runtime/Swift/Sources/Antlr4/misc/Utils.swift @@ -34,19 +34,6 @@ public class Utils { } - public static func writeFile(_ fileName: String, _ content: String, _ encoding: String.Encoding = String.Encoding.utf8) { - - //writing - do { - try content.write(toFile: fileName, atomically: false, encoding: encoding) - } catch { - /* error handling here */ - RuntimeException(" write file fail \(error)") - } - - } - - public static func readFile(_ path: String, _ encoding: String.Encoding = String.Encoding.utf8) -> [Character] { var fileContents: String @@ -60,35 +47,6 @@ public class Utils { return Array(fileContents.characters) } - public static func readFile2String(_ fileName: String, _ encoding: String.Encoding = String.Encoding.utf8) -> String { - let path = Bundle.main.path(forResource: fileName, ofType: nil) - if path == nil { - return "" - } - - var fileContents: String? = nil - do { - fileContents = try String(contentsOfFile: path!, encoding: encoding) - } catch { - return "" - } - - return fileContents ?? "" - } - - public static func readFile2StringByPath(_ path: String, _ encoding: String.Encoding = String.Encoding.utf8) -> String { - - var fileContents: String? = nil - - do { - fileContents = try String(contentsOfFile: path, encoding: String.Encoding.utf8) - } catch { - return "" - } - - return fileContents ?? "" - } - public static func toMap(_ keys: [String]) -> Dictionary { var m = Dictionary() for (index,v) in keys.enumerated() { diff --git a/runtime/Swift/Sources/Antlr4/misc/exception/ANTLRException.swift b/runtime/Swift/Sources/Antlr4/misc/exception/ANTLRException.swift index 9dec26e28..c4453384d 100644 --- a/runtime/Swift/Sources/Antlr4/misc/exception/ANTLRException.swift +++ b/runtime/Swift/Sources/Antlr4/misc/exception/ANTLRException.swift @@ -16,5 +16,5 @@ import Foundation public enum ANTLRException: Error { case cannotInvokeStartRule - case recognition(e:AnyObject) + case recognition(e: RecognitionException) } diff --git a/runtime/Swift/Sources/Antlr4/misc/utils/CommonUtil.swift b/runtime/Swift/Sources/Antlr4/misc/utils/CommonUtil.swift index f1126c589..ccb819a37 100644 --- a/runtime/Swift/Sources/Antlr4/misc/utils/CommonUtil.swift +++ b/runtime/Swift/Sources/Antlr4/misc/utils/CommonUtil.swift @@ -70,17 +70,6 @@ func log(_ message: String = "", file: String = #file, function: String = #funct // #endif } -func RuntimeException(_ message: String = "", file: String = #file, function: String = #function, lineNum: Int = #line) { - // #if DEBUG - let info = "FILE: \(URL(fileURLWithPath: file).pathComponents.last!),FUNC: \(function), LINE: \(lineNum) MESSAGE: \(message)" - // #else - // let info = "FILE: \(NSURL(fileURLWithPath: file).pathComponents!.last!),FUNC: \(function), LINE: \(lineNum) MESSAGE: \(message)" - // #endif - - fatalError(info) - -} - func toInt(_ c: Character) -> Int { return c.unicodeValue } diff --git a/runtime/Swift/Sources/Antlr4/tree/ParseTree.swift b/runtime/Swift/Sources/Antlr4/tree/ParseTree.swift index e25262604..dfddc4c67 100644 --- a/runtime/Swift/Sources/Antlr4/tree/ParseTree.swift +++ b/runtime/Swift/Sources/Antlr4/tree/ParseTree.swift @@ -11,21 +11,12 @@ /// /// The payload is either a _org.antlr.v4.runtime.Token_ or a _org.antlr.v4.runtime.RuleContext_ object. /// -//public protocol ParseTree : SyntaxTree { - -open class ParseTree: SyntaxTree, CustomStringConvertible , CustomDebugStringConvertible { - - // the following methods narrow the return type; they are not additional methods - - //func getParent() -> ParseTree? - - //func getChild(i : Int) -> ParseTree? +open class ParseTree: SyntaxTree, CustomStringConvertible, CustomDebugStringConvertible { /// The _org.antlr.v4.runtime.tree.ParseTreeVisitor_ needs a double dispatch method. open func accept(_ visitor: ParseTreeVisitor) -> T? { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } /// Return the combined text of all leaf nodes. Does not get any @@ -33,59 +24,45 @@ open class ParseTree: SyntaxTree, CustomStringConvertible , CustomDebugStringCon /// comments if they are sent to parser on hidden channel. /// open func getText() -> String { - RuntimeException(" must overriden !") - return "" + fatalError(#function + " must be overridden") } + /// Specialize toStringTree so that it can print out more information /// based upon the parser. - /// + /// open func toStringTree(_ parser: Parser) -> String { - RuntimeException(" must overriden !") - return "" - + fatalError(#function + " must be overridden") } - open func getSourceInterval() -> Interval { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } - open func getParent() -> Tree? { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } open func getPayload() -> AnyObject { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } open func getChild(_ i: Int) -> Tree? { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } - open func getChildCount() -> Int { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } open func toStringTree() -> String { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } - open var description: String { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } open var debugDescription: String { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/tree/ParseTreeVisitor.swift b/runtime/Swift/Sources/Antlr4/tree/ParseTreeVisitor.swift index 3cd8fb01e..5d1a48525 100644 --- a/runtime/Swift/Sources/Antlr4/tree/ParseTreeVisitor.swift +++ b/runtime/Swift/Sources/Antlr4/tree/ParseTreeVisitor.swift @@ -27,9 +27,7 @@ open class ParseTreeVisitor { /// - Returns: The result of visiting the parse tree. /// open func visit(_ tree: ParseTree) -> T? { - RuntimeException(" must overriden !") - return nil - + fatalError(#function + " must be overridden") } /// @@ -40,9 +38,7 @@ open class ParseTreeVisitor { /// - Returns: The result of visiting the children of the node. /// open func visitChildren(_ node: RuleNode) -> T? { - RuntimeException(" must overriden !") - return nil - + fatalError(#function + " must be overridden") } /// @@ -52,9 +48,7 @@ open class ParseTreeVisitor { /// - Returns: The result of visiting the node. /// open func visitTerminal(_ node: TerminalNode) -> T? { - RuntimeException(" must overriden !") - return nil - + fatalError(#function + " must be overridden") } /// @@ -64,7 +58,6 @@ open class ParseTreeVisitor { /// - Returns: The result of visiting the node. /// open func visitErrorNode(_ node: ErrorNode) -> T? { - RuntimeException(" must overriden !") - return nil + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/tree/RuleNode.swift b/runtime/Swift/Sources/Antlr4/tree/RuleNode.swift index e85dd8342..35af9c779 100644 --- a/runtime/Swift/Sources/Antlr4/tree/RuleNode.swift +++ b/runtime/Swift/Sources/Antlr4/tree/RuleNode.swift @@ -6,7 +6,6 @@ open class RuleNode: ParseTree { open func getRuleContext() -> RuleContext { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/tree/TerminalNode.swift b/runtime/Swift/Sources/Antlr4/tree/TerminalNode.swift index cfc27b87f..d2d9d9d5f 100644 --- a/runtime/Swift/Sources/Antlr4/tree/TerminalNode.swift +++ b/runtime/Swift/Sources/Antlr4/tree/TerminalNode.swift @@ -5,9 +5,7 @@ public class TerminalNode: ParseTree { public func getSymbol() -> Token? { - RuntimeException(" must overriden !") - fatalError() - + fatalError(#function + " must be overridden") } /// Set the parent for this leaf node. @@ -20,7 +18,6 @@ public class TerminalNode: ParseTree { /// - Since: 4.7 /// public func setParent(_ parent: RuleContext) { - RuntimeException(" must overriden !") - fatalError() + fatalError(#function + " must be overridden") } } diff --git a/runtime/Swift/Sources/Antlr4/tree/TerminalNodeImpl.swift b/runtime/Swift/Sources/Antlr4/tree/TerminalNodeImpl.swift index 8f5b0020d..4eab9bafc 100644 --- a/runtime/Swift/Sources/Antlr4/tree/TerminalNodeImpl.swift +++ b/runtime/Swift/Sources/Antlr4/tree/TerminalNodeImpl.swift @@ -6,7 +6,7 @@ public class TerminalNodeImpl: TerminalNode { public var symbol: Token - public var parent: ParseTree? + public weak var parent: ParseTree? public init(_ symbol: Token) { self.symbol = symbol diff --git a/runtime/Swift/Sources/Antlr4/tree/pattern/ParseTreePatternMatcher.swift b/runtime/Swift/Sources/Antlr4/tree/pattern/ParseTreePatternMatcher.swift index ecc9ae1d0..3b78b7fe8 100644 --- a/runtime/Swift/Sources/Antlr4/tree/pattern/ParseTreePatternMatcher.swift +++ b/runtime/Swift/Sources/Antlr4/tree/pattern/ParseTreePatternMatcher.swift @@ -68,12 +68,12 @@ public class ParseTreePatternMatcher { /// /// This is the backing field for _#getLexer()_. /// - private final var lexer: Lexer + private final let lexer: Lexer /// /// This is the backing field for _#getParser()_. /// - private final var parser: Parser + private final let parser: Parser internal var start: String = "<" internal var stop: String = ">" @@ -159,19 +159,18 @@ public class ParseTreePatternMatcher { /// _org.antlr.v4.runtime.tree.pattern.ParseTreePattern_ using this method. /// public func compile(_ pattern: String, _ patternRuleIndex: Int) throws -> ParseTreePattern { - let tokenList: Array = try tokenize(pattern) - let tokenSrc: ListTokenSource = ListTokenSource(tokenList) - let tokens: CommonTokenStream = CommonTokenStream(tokenSrc) + let tokenList = try tokenize(pattern) + let tokenSrc = ListTokenSource(tokenList) + let tokens = CommonTokenStream(tokenSrc) - let parserInterp: ParserInterpreter = try ParserInterpreter(parser.getGrammarFileName(), + let parserInterp = try ParserInterpreter(parser.getGrammarFileName(), parser.getVocabulary(), parser.getRuleNames(), parser.getATNWithBypassAlts(), tokens) - var tree: ParseTree parserInterp.setErrorHandler(BailErrorStrategy()) - tree = try parserInterp.parse(patternRuleIndex) + let tree = try parserInterp.parse(patternRuleIndex) // Make sure tree pattern compilation checks for a complete parse if try tokens.LA(1) != CommonToken.EOF { @@ -214,8 +213,8 @@ public class ParseTreePatternMatcher { // x and , x and y, or x and x; or could be mismatched types if tree is TerminalNode && patternTree is TerminalNode { - let t1: TerminalNode = tree as! TerminalNode - let t2: TerminalNode = patternTree as! TerminalNode + let t1 = tree as! TerminalNode + let t2 = patternTree as! TerminalNode var mismatchedNode: ParseTree? = nil // both are tokens and they have same type if t1.getSymbol()!.getType() == t2.getSymbol()!.getType() { @@ -252,7 +251,6 @@ public class ParseTreePatternMatcher { var mismatchedNode: ParseTree? = nil // (expr ...) and if let ruleTagToken = getRuleTagToken(r2) { - //var m : ParseTreeMatch? = nil; if r1.getRuleContext().getRuleIndex() == r2.getRuleContext().getRuleIndex() { // track label->list-of-nodes for both rule name and label (if any) labels.map(ruleTagToken.getRuleName(), tree) @@ -277,11 +275,8 @@ public class ParseTreePatternMatcher { return mismatchedNode } - let n: Int = r1.getChildCount() - for i in 0..)` subtree? internal func getRuleTagToken(_ t: ParseTree) -> RuleTagToken? { - if t is RuleNode { - let r: RuleNode = t as! RuleNode + if let r = t as? RuleNode { if r.getChildCount() == 1 && r.getChild(0) is TerminalNode { - let c: TerminalNode = r.getChild(0) as! TerminalNode + let c = r.getChild(0) as! TerminalNode if c.getSymbol() is RuleTagToken { // print("rule tag subtree "+t.toStringTree(parser)); return c.getSymbol() as? RuleTagToken @@ -310,21 +304,20 @@ public class ParseTreePatternMatcher { public func tokenize(_ pattern: String) throws -> Array { // split pattern into chunks: sea (raw input) and islands (, ) - let chunks: Array = try split(pattern) + let chunks = try split(pattern) // create token stream from text and tags - var tokens: Array = Array() - for chunk: Chunk in chunks { - if chunk is TagChunk { - let tagChunk: TagChunk = chunk as! TagChunk + var tokens = [Token]() + for chunk in chunks { + if let tagChunk = chunk as? TagChunk { // add special rule token or conjure up new token from name let firstStr = String(tagChunk.getTag()[0]) if firstStr.lowercased() != firstStr { - let ttype: Int = parser.getTokenType(tagChunk.getTag()) + let ttype = parser.getTokenType(tagChunk.getTag()) if ttype == CommonToken.INVALID_TYPE { throw ANTLRError.illegalArgument(msg: "Unknown token " + tagChunk.getTag() + " in pattern: " + pattern) } - let t: TokenTagToken = TokenTagToken(tagChunk.getTag(), ttype, tagChunk.getLabel()) + let t = TokenTagToken(tagChunk.getTag(), ttype, tagChunk.getLabel()) tokens.append(t) } else { if firstStr.uppercased() != firstStr { @@ -339,10 +332,10 @@ public class ParseTreePatternMatcher { } } } else { - let textChunk: TextChunk = chunk as! TextChunk - let inputStream: ANTLRInputStream = ANTLRInputStream(textChunk.getText()) + let textChunk = chunk as! TextChunk + let inputStream = ANTLRInputStream(textChunk.getText()) try lexer.setInputStream(inputStream) - var t: Token = try lexer.nextToken() + var t = try lexer.nextToken() while t.getType() != CommonToken.EOF { tokens.append(t) t = try lexer.nextToken() @@ -357,32 +350,30 @@ public class ParseTreePatternMatcher { /// /// Split ` = ;` into 4 chunks for tokenizing by _#tokenize_. /// - public func split(_ pattern: String) throws -> Array { - var p: Int = 0 - let n: Int = pattern.length - var chunks: Array = Array() + public func split(_ pattern: String) throws -> [Chunk] { + var p = 0 + let n = pattern.length + var chunks = [Chunk]() // find all start and stop indexes first, then collect - var starts: Array = Array() - var stops: Array = Array() + var starts = [Int]() + var stops = [Int]() while p < n { if p == pattern.indexOf(escape + start, startIndex: p) { p += escape.length + start.length - } else { - if p == pattern.indexOf(escape + stop, startIndex: p) { - p += escape.length + stop.length - } else { - if p == pattern.indexOf(start, startIndex: p) { - starts.append(p) - p += start.length - } else { - if p == pattern.indexOf(stop, startIndex: p) { - stops.append(p) - p += stop.length - } else { - p += 1 - } - } - } + } + else if p == pattern.indexOf(escape + stop, startIndex: p) { + p += escape.length + stop.length + } + else if p == pattern.indexOf(start, startIndex: p) { + starts.append(p) + p += start.length + } + else if p == pattern.indexOf(stop, startIndex: p) { + stops.append(p) + p += stop.length + } + else { + p += 1 } } @@ -394,58 +385,55 @@ public class ParseTreePatternMatcher { throw ANTLRError.illegalArgument(msg: "missing start tag in pattern: " + pattern) } - let ntags: Int = starts.count + let ntags = starts.count for i in 0.. 0 && starts[0] > 0 { // copy text up to first tag into chunks - let text: String = pattern[0 ..< starts[0]] //; substring(0, starts.get(0)); + let text = pattern[0 ..< starts[0]] chunks.append(TextChunk(text)) } - for i in 0.. - let tag: String = pattern[starts[i] + start.length ..< stops[i]] // pattern.substring(starts.get(i) + start.length(), stops.get(i)); - var ruleOrToken: String = tag - var label: String = "" - let colon: Int = tag.indexOf(":") + let tag = pattern[starts[i] + start.length ..< stops[i]] + var ruleOrToken = tag + var label = "" + let colon = tag.indexOf(":") if colon >= 0 { - label = tag[0 ..< colon] //(0,colon); - ruleOrToken = tag[colon + 1 ..< tag.length] //(colon+1, tag.length()); + label = tag[0 ..< colon] + ruleOrToken = tag[colon + 1 ..< tag.length] } chunks.append(try TagChunk(label, ruleOrToken)) if i + 1 < ntags { // copy from end of to start of next - let text: String = pattern[stops[i] + stop.length ..< starts[i] + 1] //.substring(stops.get(i) + stop.length(), starts.get(i + 1)); + let text = pattern[stops[i] + stop.length ..< starts[i] + 1] chunks.append(TextChunk(text)) } } if ntags > 0 { - let afterLastTag: Int = stops[ntags - 1] + stop.length + let afterLastTag = stops[ntags - 1] + stop.length if afterLastTag < n { // copy text from end of last tag to end - let text: String = pattern[afterLastTag ..< n] //.substring(afterLastTag, n); + let text = pattern[afterLastTag ..< n] chunks.append(TextChunk(text)) } } // strip out the escape sequences from text chunks but not tags - let length = chunks.count - for i in 0.. String? { - if label != nil { - return "<" + label! + ":" + ruleName + ">" + if let label = label { + return "<\(label):\(ruleName)>" } - - return "<" + ruleName + ">" + return "<\(ruleName)>" } /// @@ -152,14 +149,18 @@ public class RuleTagToken: Token, CustomStringConvertible { return nil } - /// + /// /// The implementation for _org.antlr.v4.runtime.tree.pattern.RuleTagToken_ always returns `null`. /// public func getInputStream() -> CharStream? { return nil } - /// + public func getTokenSourceAndStream() -> TokenSourceAndStream { + return TokenSourceAndStream.EMPTY + } + + /// /// The implementation for _org.antlr.v4.runtime.tree.pattern.RuleTagToken_ returns a string of the form /// `ruleName:bypassTokenType`. /// diff --git a/runtime/Swift/Tests/Antlr4Tests/MurmurHashTests.swift b/runtime/Swift/Tests/Antlr4Tests/MurmurHashTests.swift new file mode 100644 index 000000000..dad5853de --- /dev/null +++ b/runtime/Swift/Tests/Antlr4Tests/MurmurHashTests.swift @@ -0,0 +1,47 @@ +/// 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. + +/// The test patterns below are by Ian Boyd and have been released into the +/// public domain. +/// https://stackoverflow.com/questions/14747343/murmurhash3-test-vectors + +import XCTest +import Antlr4 + +class MurmurHashTests: XCTestCase { + + func testMurmurHash() { + doMurmurHashTest("", 0, 0) //empty string with zero seed should give zero + doMurmurHashTest("", 1, 0x514E28B7) + doMurmurHashTest("", 0xffffffff, 0x81F16F39) //make sure seed value is handled unsigned + doMurmurHashTest("\0\0\0\0", 0, 0x2362F9DE) //make sure we handle embedded nulls + + doMurmurHashTest("aaaa", 0x9747b28c, 0x5A97808A) //one full chunk + doMurmurHashTest("aaa", 0x9747b28c, 0x283E0130) //three characters + doMurmurHashTest("aa", 0x9747b28c, 0x5D211726) //two characters + doMurmurHashTest("a", 0x9747b28c, 0x7FA09EA6) //one character + + //Endian order within the chunks + doMurmurHashTest("abcd", 0x9747b28c, 0xF0478627) //one full chunk + doMurmurHashTest("abc", 0x9747b28c, 0xC84A62DD) + doMurmurHashTest("ab", 0x9747b28c, 0x74875592) + doMurmurHashTest("a", 0x9747b28c, 0x7FA09EA6) + + doMurmurHashTest("Hello, world!", 0x9747b28c, 0x24884CBA) + + //Make sure you handle UTF-8 high characters. A bcrypt implementation messed this up + doMurmurHashTest("ππππππππ", 0x9747b28c, 0xD58063C1) //U+03C0: Greek Small Letter Pi + + //String of 256 characters. + doMurmurHashTest(String(repeating: "a", count: 256), 0x9747b28c, 0x37405BDC) + + doMurmurHashTest("abc", 0, 0xB3DD93FA) + doMurmurHashTest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 0, 0xEE925B90) + doMurmurHashTest("The quick brown fox jumps over the lazy dog", 0x9747b28c, 0x2FA826CD) + } +} + +private func doMurmurHashTest(_ input: String, _ seed: UInt32, _ expected: UInt32) { + XCTAssertEqual(MurmurHash.hashString(input, seed), expected) +} diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Swift/Swift.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Swift/Swift.stg index 2367a441f..6586a3878 100755 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Swift/Swift.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Swift/Swift.stg @@ -241,12 +241,14 @@ open class : { } return decisionToDFA }() - internal static let _sharedContextCache: PredictionContextCache = PredictionContextCache() + internal static let _sharedContextCache = PredictionContextCache() + public enum Tokens: Int { case EOF = -1, = }; separator=", ", wrap, anchor> } + public static let = }; separator=", ", wrap, anchor> public static let ruleNames: [String] = [ "}; separator=", ", wrap, anchor> @@ -285,8 +287,8 @@ case : - public static let _serializedATN : String = ATN().jsonString - public static let _ATN: ATN = ATNDeserializer().deserializeFromJson(_serializedATN) + public static let _serializedATN = ATN().jsonString + public static let _ATN = ATNDeserializer().deserializeFromJson(_serializedATN) } >> @@ -297,33 +299,7 @@ private static let _LITERAL_NAMES: [String?] = [ private static let _SYMBOLIC_NAMES: [String?] = [ }; null="nil", separator=", ", wrap, anchor> ] -public static let VOCABULARY: Vocabulary = Vocabulary(_LITERAL_NAMES, _SYMBOLIC_NAMES) - -/** - * @deprecated Use {@link #VOCABULARY} instead. - */ -//@Deprecated -public let tokenNames: [String?]? = { - let length = _SYMBOLIC_NAMES.count - var tokenNames = [String?](repeating: nil, count: length) - for i in 0..\ -open func getTokenNames() -> [String?]? { - return tokenNames -} +public static let VOCABULARY = Vocabulary(_LITERAL_NAMES, _SYMBOLIC_NAMES) >> dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= << @@ -361,11 +337,12 @@ open override func getVocabulary() -> Vocabulary { return .VOCABULARY } -public override init(_ input:TokenStream)throws { +public override init(_ input:TokenStream) throws { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION) try super.init(input) _interp = ParserATNSimulator(self,._ATN,._decisionToDFA, ._sharedContextCache) } + >> /* This generates a private method since the actionIndex is generated, making an @@ -612,7 +589,7 @@ case +1: Sync(s) ::= "sync();" -ThrowNoViableAlt(t) ::= "throw try ANTLRException.recognition(e: NoViableAltException(self))" +ThrowNoViableAlt(t) ::= "throw ANTLRException.recognition(e: NoViableAltException(self))" TestSetInline(s) ::= << }; separator=" || ">!> @@ -717,7 +694,7 @@ ArgAction(a, chunks) ::= "" SemPred(p, chunks, failChunks) ::= << setState() if (!()) { - throw try ANTLRException.recognition(e:FailedPredicateException(self, , , )) + throw ANTLRException.recognition(e:FailedPredicateException(self, , , )) } >> @@ -796,7 +773,7 @@ open func (_ i:Int) -> TerminalNode?{ >> ContextRuleGetterDecl(r) ::= << open func () -> ? { - return getRuleContext(.self,0) + return getRuleContext(.self, 0) } >> ContextRuleListGetterDecl(r) ::= << @@ -806,7 +783,7 @@ open func () -> Array\<\> { >> ContextRuleListIndexedGetterDecl(r) ::= << open func (_ i: Int) -> ? { - return getRuleContext(.self,i) + return getRuleContext(.self, i) } >> @@ -827,7 +804,7 @@ CaptureNextTokenType(d) ::= " = try _input.LA(1)" StructDecl(struct,ctorAttrs,attrs,getters,dispatchMethods,interfaces,extensionMembers, superClass={ParserRuleContext}) ::= << -open class :ParserRuleContext, { +open class : ParserRuleContext, { }; separator="\n"> }; separator="\n"> public init(_ parent: ParserRuleContext,_ invokingState: Int) { super.init(parent, invokingState) } !> @@ -865,8 +842,8 @@ public final class : Context { ListenerDispatchMethod(method) ::= << override open func enterexitRule(_ listener: ParseTreeListener) { - if listener is Listener { - (listener as! Listener).enterexit(self) + if let listener = listener as? Listener { + listener.enterexit(self) } } >> @@ -874,11 +851,12 @@ open func enterexitRule(_ listener: ParseTreeLi VisitorDispatchMethod(method) ::= << override open func accept\(_ visitor: ParseTreeVisitor\) -> T? { - if visitor is Visitor { - return (visitor as! Visitor\).visit(self) - }else if visitor is BaseVisitor { - return (visitor as! BaseVisitor\).visit(self) - } + if let visitor = visitor as? Visitor { + return visitor.visit(self) + } + else if let visitor = visitor as? BaseVisitor { + return visitor.visit(self) + } else { return visitor.visitChildren(self) } @@ -959,7 +937,7 @@ open class : { return decisionToDFA }() - internal static let _sharedContextCache:PredictionContextCache = PredictionContextCache() + internal static let _sharedContextCache = PredictionContextCache() public static let =}; separator=", ", wrap, anchor> public static let =}; separator=", ", wrap, anchor> @@ -986,7 +964,7 @@ open class : { return .VOCABULARY } - public override init(_ input: CharStream) { + public required init(_ input: CharStream) { RuntimeMetaData.checkVersion("", RuntimeMetaData.VERSION) super.init(input) _interp = LexerATNSimulator(self, ._ATN, ._decisionToDFA, ._sharedContextCache) diff --git a/tool/resources/org/antlr/v4/tool/templates/messages/formats/gnu.stg b/tool/resources/org/antlr/v4/tool/templates/messages/formats/gnu.stg index f243ab785..c7d06d9e8 100644 --- a/tool/resources/org/antlr/v4/tool/templates/messages/formats/gnu.stg +++ b/tool/resources/org/antlr/v4/tool/templates/messages/formats/gnu.stg @@ -31,9 +31,9 @@ This file contains the actual layout of the messages emitted by ANTLR. This file contains the format that mimicks GCC output. */ -location(file, line, column) ::= "::" +location(file, line, column) ::= ":::" -message(id, text) ::= " ()" +message(id, text) ::= " [error ]" report(location, message, type) ::= " : " diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 0363508ee..0862e4d02 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -117,6 +117,7 @@ public class Tool { public Map grammarOptions = null; public boolean warnings_are_errors = false; public boolean longMessages = false; + public boolean exact_output_dir = false; public static Option[] optionDefs = { new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"), @@ -137,6 +138,7 @@ public class Tool { new Option("ST_inspector_wait_for_close", "-XdbgSTWait", "wait for STViz to close before continuing"), new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"), new Option("log", "-Xlog", "dump lots of logging info to antlr-timestamp.log"), + new Option("exact_output_dir", "-Xexact-output-dir", "all output goes into -o dir regardless of paths/package"), }; // helper vars for option management @@ -193,8 +195,11 @@ public class Tool { public Tool(String[] args) { this.args = args; errMgr = new ErrorManager(this); - errMgr.setFormat(msgFormat); + // We have to use the default message format until we have + // parsed the -message-format command line option. + errMgr.setFormat("antlr"); handleArgs(); + errMgr.setFormat(msgFormat); } protected void handleArgs() { @@ -248,7 +253,7 @@ public class Tool { haveOutputDir = true; if (outDir.exists() && !outDir.isDirectory()) { errMgr.toolError(ErrorType.OUTPUT_DIR_IS_FILE, outputDirectory); - libDirectory = "."; + outputDirectory = "."; } } else { @@ -820,6 +825,10 @@ public class Tool { * @param fileNameWithPath path to input source */ public File getOutputDirectory(String fileNameWithPath) { + if ( exact_output_dir ) { + return new_getOutputDirectory(fileNameWithPath); + } + File outputDir; String fileDirectory; @@ -845,12 +854,12 @@ public class Tool { // -o . /usr/lib/t.g4 => ./T.java if (fileDirectory != null && (new File(fileDirectory).isAbsolute() || - fileDirectory.startsWith("~"))) { // isAbsolute doesn't count this :( + fileDirectory.startsWith("~"))) { // isAbsolute doesn't count this :( // somebody set the dir, it takes precendence; write new file there outputDir = new File(outputDirectory); } else { - // -o /tmp subdir/t.g4 => /tmp/subdir/t.g4 + // -o /tmp subdir/t.g4 => /tmp/subdir/T.java if (fileDirectory != null) { outputDir = new File(outputDirectory, fileDirectory); } @@ -869,6 +878,37 @@ public class Tool { return outputDir; } + /** @since 4.7.1 in response to -Xexact-output-dir */ + public File new_getOutputDirectory(String fileNameWithPath) { + File outputDir; + String fileDirectory; + + if (fileNameWithPath.lastIndexOf(File.separatorChar) == -1) { + // No path is included in the file name, so make the file + // directory the same as the parent grammar (which might still be just "" + // but when it is not, we will write the file in the correct place. + fileDirectory = "."; + } + else { + fileDirectory = fileNameWithPath.substring(0, fileNameWithPath.lastIndexOf(File.separatorChar)); + } + if ( haveOutputDir ) { + // -o /tmp /var/lib/t.g4 => /tmp/T.java + // -o subdir/output /usr/lib/t.g4 => subdir/output/T.java + // -o . /usr/lib/t.g4 => ./T.java + // -o /tmp subdir/t.g4 => /tmp/T.java + outputDir = new File(outputDirectory); + } + else { + // they didn't specify a -o dir so just write to location + // where grammar is, absolute or relative, this will only happen + // with command line invocation as build tools will always + // supply an output directory. + outputDir = new File(fileDirectory); + } + return outputDir; + } + protected void writeDOTFile(Grammar g, Rule r, String dot) throws IOException { writeDOTFile(g, r.g.name + "." + r.name, dot); } diff --git a/tool/src/org/antlr/v4/codegen/target/GoTarget.java b/tool/src/org/antlr/v4/codegen/target/GoTarget.java index 6c70376c7..34c62045f 100644 --- a/tool/src/org/antlr/v4/codegen/target/GoTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/GoTarget.java @@ -49,8 +49,18 @@ public class GoTarget extends Target { "make", "new", "panic", "print", "println", "real", "recover" }; + // interface definition of RuleContext from runtime/Go/antlr/rule_context.go + private static final String[] goRuleContextInterfaceMethods = { + "Accept", "GetAltNumber", "GetBaseRuleContext", "GetChild", "GetChildCount", + "GetChildren", "GetInvokingState", "GetParent", "GetPayload", "GetRuleContext", + "GetRuleIndex", "GetSourceInterval", "GetText", "IsEmpty", "SetAltNumber", + "SetInvokingState", "SetParent", "String" + }; + /** Avoid grammar symbols in this set to prevent conflicts in gen'd code. */ - private final Set badWords = new HashSet(goKeywords.length + goPredeclaredIdentifiers.length + 3); + private final Set badWords = new HashSet( + goKeywords.length + goPredeclaredIdentifiers.length + goRuleContextInterfaceMethods.length + 3 + ); private static final boolean DO_GOFMT = !Boolean.parseBoolean(System.getenv("ANTLR_GO_DISABLE_GOFMT")) && !Boolean.parseBoolean(System.getProperty("antlr.go.disable-gofmt")); @@ -75,6 +85,7 @@ public class GoTarget extends Target { protected void addBadWords() { badWords.addAll(Arrays.asList(goKeywords)); badWords.addAll(Arrays.asList(goPredeclaredIdentifiers)); + badWords.addAll(Arrays.asList(goRuleContextInterfaceMethods)); badWords.add("rule"); badWords.add("parserRule"); badWords.add("action"); diff --git a/tool/src/org/antlr/v4/gui/TreeViewer.java b/tool/src/org/antlr/v4/gui/TreeViewer.java index f20f3d8ea..2c000aa90 100644 --- a/tool/src/org/antlr/v4/gui/TreeViewer.java +++ b/tool/src/org/antlr/v4/gui/TreeViewer.java @@ -37,7 +37,10 @@ import java.awt.geom.CubicCurve2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; +import java.io.FileWriter; +import java.io.BufferedWriter; import java.io.IOException; +import java.io.Writer; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -245,6 +248,69 @@ public class TreeViewer extends JComponent { } } + protected void generateEdges(Writer writer, Tree parent) throws IOException { + if (!getTree().isLeaf(parent)) { + Rectangle2D.Double b1 = getBoundsOfNode(parent); + double x1 = b1.getCenterX(); + double y1 = b1.getCenterY(); + + for (Tree child : getTree().getChildren(parent)) { + Rectangle2D.Double childBounds = getBoundsOfNode(child); + double x2 = childBounds.getCenterX(); + double y2 = childBounds.getMinY(); + writer.write(line(""+x1, ""+y1, ""+x2, ""+y2, + "stroke:black; stroke-width:1px;")); + generateEdges(writer, child); + } + } + } + + protected void generateBox(Writer writer, Tree parent) throws IOException { + + // draw the box in the background + Rectangle2D.Double box = getBoundsOfNode(parent); + writer.write(rect(""+box.x, ""+box.y, ""+box.width, ""+box.height, + "fill:orange; stroke:rgb(0,0,0);", "rx=\"1\"")); + + // draw the text on top of the box (possibly multiple lines) + String line = getText(parent).replace("<","<").replace(">",">"); + int fontSize = 10; + int x = (int) box.x + 2; + int y = (int) box.y + fontSize - 1; + String style = String.format("font-family:sans-serif;font-size:%dpx;", + fontSize); + writer.write(text(""+x, ""+y, style, line)); + } + + private static String line(String x1, String y1, String x2, String y2, + String style) { + return String + .format("\n", + x1, y1, x2, y2, style); + } + + private static String rect(String x, String y, String width, String height, + String style, String extraAttributes) { + return String + .format("\n", + x, y, width, height, style, extraAttributes); + } + + private static String text(String x, String y, String style, String text) { + return String.format( + "\n%s\n\n", x, y, + style, text); + } + + private void paintSVG(Writer writer) throws IOException { + + generateEdges(writer, getTree().getRoot()); + + for (Tree tree : treeLayout.getNodeBounds().keySet()) { + generateBox(writer, tree); + } + } + @Override protected Graphics getComponentGraphics(Graphics g) { Graphics2D g2d=(Graphics2D)g; @@ -307,6 +373,18 @@ public class TreeViewer extends JComponent { ); wrapper.add(png); + // Add an export-to-png button right of the "OK" button + JButton svg = new JButton("Export as SVG"); + svg.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + generateSVGFile(viewer, dialog); + } + } + ); + wrapper.add(svg); + bottomPanel.add(wrapper, BorderLayout.SOUTH); // Add scale slider @@ -418,29 +496,7 @@ public class TreeViewer extends JComponent { g.dispose(); try { - File suggestedFile = generateNonExistingPngFile(); - JFileChooser fileChooser = new JFileChooserConfirmOverwrite(); - fileChooser.setCurrentDirectory(suggestedFile.getParentFile()); - fileChooser.setSelectedFile(suggestedFile); - FileFilter pngFilter = new FileFilter() { - - @Override - public boolean accept(File pathname) { - if (pathname.isFile()) { - return pathname.getName().toLowerCase().endsWith(".png"); - } - - return true; - } - - @Override - public String getDescription() { - return "PNG Files (*.png)"; - } - }; - - fileChooser.addChoosableFileFilter(pngFilter); - fileChooser.setFileFilter(pngFilter); + JFileChooser fileChooser = getFileChooser(".png", "PNG files"); int returnValue = fileChooser.showSaveDialog(dialog); if (returnValue == JFileChooser.APPROVE_OPTION) { @@ -469,23 +525,85 @@ public class TreeViewer extends JComponent { } } - private static File generateNonExistingPngFile() { + private static JFileChooser getFileChooser(final String fileEnding, + final String description) { + File suggestedFile = generateNonExistingFile(fileEnding); + JFileChooser fileChooser = new JFileChooserConfirmOverwrite(); + fileChooser.setCurrentDirectory(suggestedFile.getParentFile()); + fileChooser.setSelectedFile(suggestedFile); + FileFilter filter = new FileFilter() { + + @Override + public boolean accept(File pathname) { + if (pathname.isFile()) { + return pathname.getName().toLowerCase().endsWith(fileEnding); + } + + return true; + } + + @Override + public String getDescription() { + return description+" (*"+fileEnding+")"; + } + }; + fileChooser.addChoosableFileFilter(filter); + fileChooser.setFileFilter(filter); + return fileChooser; + } + + private static void generateSVGFile(TreeViewer viewer, JFrame dialog) { + + try { + JFileChooser fileChooser = getFileChooser(".svg", "SVG files"); + + int returnValue = fileChooser.showSaveDialog(dialog); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File svgFile = fileChooser.getSelectedFile(); + // save the new svg file here! + BufferedWriter writer = new BufferedWriter(new FileWriter(svgFile)); + // HACK: multiplying with 1.1 should be replaced wit an accurate number + writer.write(""); + viewer.paintSVG(writer); + writer.write(""); + writer.flush(); + writer.close(); + try { + // Try to open the parent folder using the OS' native file manager. + Desktop.getDesktop().open(svgFile.getParentFile()); + } catch (Exception ex) { + // We could not launch the file manager: just show a popup that we + // succeeded in saving the PNG file. + JOptionPane.showMessageDialog(dialog, "Saved SVG to: " + + svgFile.getAbsolutePath()); + ex.printStackTrace(); + } + } + } catch (Exception ex) { + JOptionPane.showMessageDialog(dialog, + "Could not export to SVG: " + ex.getMessage(), + "Error", + JOptionPane.ERROR_MESSAGE); + ex.printStackTrace(); + } + } + + private static File generateNonExistingFile(String extension) { final String parent = "."; final String name = "antlr4_parse_tree"; - final String extension = ".png"; - File pngFile = new File(parent, name + extension); + File file = new File(parent, name + extension); int counter = 1; // Keep looping until we create a File that does not yet exist. - while (pngFile.exists()) { - pngFile = new File(parent, name + "_"+ counter + extension); + while (file.exists()) { + file = new File(parent, name + "_" + counter + extension); counter++; } - return pngFile; + return file; } private static void fillTree(TreeNodeWrapper node, Tree tree, TreeViewer viewer) { diff --git a/tool/src/org/antlr/v4/parse/TokenVocabParser.java b/tool/src/org/antlr/v4/parse/TokenVocabParser.java index 4267a8d96..cf84a923a 100644 --- a/tool/src/org/antlr/v4/parse/TokenVocabParser.java +++ b/tool/src/org/antlr/v4/parse/TokenVocabParser.java @@ -146,6 +146,22 @@ public class TokenVocabParser { // files are generated (in the base, not relative to the input // location.) f = new File(g.tool.outputDirectory, vocabName + CodeGenerator.VOCAB_FILE_EXTENSION); - return f; + if ( f.exists() ) { + return f; + } + + // Still not found? Use the grammar's subfolder then. + String fileDirectory; + + if (g.fileName.lastIndexOf(File.separatorChar) == -1) { + // No path is included in the file name, so make the file + // directory the same as the parent grammar (which might still be just "" + // but when it is not, we will write the file in the correct place. + fileDirectory = "."; + } + else { + fileDirectory = g.fileName.substring(0, g.fileName.lastIndexOf(File.separatorChar)); + } + return new File(fileDirectory, vocabName + CodeGenerator.VOCAB_FILE_EXTENSION); } } diff --git a/tool/src/org/antlr/v4/tool/ErrorManager.java b/tool/src/org/antlr/v4/tool/ErrorManager.java index 8178abc71..0230d2b2f 100644 --- a/tool/src/org/antlr/v4/tool/ErrorManager.java +++ b/tool/src/org/antlr/v4/tool/ErrorManager.java @@ -60,11 +60,20 @@ public class ErrorManager { locationValid = true; } if (msg.fileName != null) { - File f = new File(msg.fileName); - // Don't show path to file in messages; too long. String displayFileName = msg.fileName; - if ( f.exists() ) { - displayFileName = f.getName(); + if (format.equals("antlr")) { + // Don't show path to file in messages in ANTLR format; + // they're too long. + File f = new File(msg.fileName); + if ( f.exists() ) { + displayFileName = f.getName(); + } + } + else { + // For other message formats, use the full filename in the + // message. This assumes that these formats are intended to + // be parsed by IDEs, and so they need the full path to + // resolve correctly. } locationST.add("file", displayFileName); locationValid = true;