[third_party] remove antlr

Bug: v8:7754
Change-Id: Iffd3a2f665258032e2284e5cd700f9a3286618d1
Reviewed-on: https://chromium-review.googlesource.com/1145064
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54581}
This commit is contained in:
Tobias Tebbi 2018-07-20 12:48:24 +02:00 committed by Commit Bot
parent 7221681b7b
commit 29d08f1cd8
312 changed files with 0 additions and 30847 deletions

View File

@ -1,342 +0,0 @@
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
config("antlr-compatibility") {
if (!is_clang && !is_win) {
cflags = [
# Avoid warnings in generated Antlr code
"-Wno-unused-but-set-variable",
]
}
if (is_aix) {
cflags += [ "-fdollars-in-identifiers" ]
}
}
source_set("antlr4") {
defines = [ "ANTLR4CPP_STATIC" ]
include_dirs = [ "runtime/Cpp/runtime/src" ]
sources = [
"runtime/Cpp/runtime/src/ANTLRErrorListener.cpp",
"runtime/Cpp/runtime/src/ANTLRErrorListener.h",
"runtime/Cpp/runtime/src/ANTLRErrorStrategy.cpp",
"runtime/Cpp/runtime/src/ANTLRErrorStrategy.h",
"runtime/Cpp/runtime/src/ANTLRFileStream.cpp",
"runtime/Cpp/runtime/src/ANTLRFileStream.h",
"runtime/Cpp/runtime/src/ANTLRInputStream.cpp",
"runtime/Cpp/runtime/src/ANTLRInputStream.h",
"runtime/Cpp/runtime/src/BailErrorStrategy.cpp",
"runtime/Cpp/runtime/src/BailErrorStrategy.h",
"runtime/Cpp/runtime/src/BaseErrorListener.cpp",
"runtime/Cpp/runtime/src/BaseErrorListener.h",
"runtime/Cpp/runtime/src/BufferedTokenStream.cpp",
"runtime/Cpp/runtime/src/BufferedTokenStream.h",
"runtime/Cpp/runtime/src/CharStream.cpp",
"runtime/Cpp/runtime/src/CharStream.h",
"runtime/Cpp/runtime/src/CommonToken.cpp",
"runtime/Cpp/runtime/src/CommonToken.h",
"runtime/Cpp/runtime/src/CommonTokenFactory.cpp",
"runtime/Cpp/runtime/src/CommonTokenFactory.h",
"runtime/Cpp/runtime/src/CommonTokenStream.cpp",
"runtime/Cpp/runtime/src/CommonTokenStream.h",
"runtime/Cpp/runtime/src/ConsoleErrorListener.cpp",
"runtime/Cpp/runtime/src/ConsoleErrorListener.h",
"runtime/Cpp/runtime/src/DefaultErrorStrategy.cpp",
"runtime/Cpp/runtime/src/DefaultErrorStrategy.h",
"runtime/Cpp/runtime/src/DiagnosticErrorListener.cpp",
"runtime/Cpp/runtime/src/DiagnosticErrorListener.h",
"runtime/Cpp/runtime/src/Exceptions.cpp",
"runtime/Cpp/runtime/src/Exceptions.h",
"runtime/Cpp/runtime/src/FailedPredicateException.cpp",
"runtime/Cpp/runtime/src/FailedPredicateException.h",
"runtime/Cpp/runtime/src/InputMismatchException.cpp",
"runtime/Cpp/runtime/src/InputMismatchException.h",
"runtime/Cpp/runtime/src/IntStream.cpp",
"runtime/Cpp/runtime/src/IntStream.h",
"runtime/Cpp/runtime/src/InterpreterRuleContext.cpp",
"runtime/Cpp/runtime/src/InterpreterRuleContext.h",
"runtime/Cpp/runtime/src/Lexer.cpp",
"runtime/Cpp/runtime/src/Lexer.h",
"runtime/Cpp/runtime/src/LexerInterpreter.cpp",
"runtime/Cpp/runtime/src/LexerInterpreter.h",
"runtime/Cpp/runtime/src/LexerNoViableAltException.cpp",
"runtime/Cpp/runtime/src/LexerNoViableAltException.h",
"runtime/Cpp/runtime/src/ListTokenSource.cpp",
"runtime/Cpp/runtime/src/ListTokenSource.h",
"runtime/Cpp/runtime/src/NoViableAltException.cpp",
"runtime/Cpp/runtime/src/NoViableAltException.h",
"runtime/Cpp/runtime/src/Parser.cpp",
"runtime/Cpp/runtime/src/Parser.h",
"runtime/Cpp/runtime/src/ParserInterpreter.cpp",
"runtime/Cpp/runtime/src/ParserInterpreter.h",
"runtime/Cpp/runtime/src/ParserRuleContext.cpp",
"runtime/Cpp/runtime/src/ParserRuleContext.h",
"runtime/Cpp/runtime/src/ProxyErrorListener.cpp",
"runtime/Cpp/runtime/src/ProxyErrorListener.h",
"runtime/Cpp/runtime/src/RecognitionException.cpp",
"runtime/Cpp/runtime/src/RecognitionException.h",
"runtime/Cpp/runtime/src/Recognizer.cpp",
"runtime/Cpp/runtime/src/Recognizer.h",
"runtime/Cpp/runtime/src/RuleContext.cpp",
"runtime/Cpp/runtime/src/RuleContext.h",
"runtime/Cpp/runtime/src/RuleContextWithAltNum.cpp",
"runtime/Cpp/runtime/src/RuleContextWithAltNum.h",
"runtime/Cpp/runtime/src/RuntimeMetaData.cpp",
"runtime/Cpp/runtime/src/RuntimeMetaData.h",
"runtime/Cpp/runtime/src/Token.cpp",
"runtime/Cpp/runtime/src/Token.h",
"runtime/Cpp/runtime/src/TokenFactory.h",
"runtime/Cpp/runtime/src/TokenSource.cpp",
"runtime/Cpp/runtime/src/TokenSource.h",
"runtime/Cpp/runtime/src/TokenStream.cpp",
"runtime/Cpp/runtime/src/TokenStream.h",
"runtime/Cpp/runtime/src/TokenStreamRewriter.cpp",
"runtime/Cpp/runtime/src/TokenStreamRewriter.h",
"runtime/Cpp/runtime/src/UnbufferedCharStream.cpp",
"runtime/Cpp/runtime/src/UnbufferedCharStream.h",
"runtime/Cpp/runtime/src/UnbufferedTokenStream.cpp",
"runtime/Cpp/runtime/src/UnbufferedTokenStream.h",
"runtime/Cpp/runtime/src/Vocabulary.cpp",
"runtime/Cpp/runtime/src/Vocabulary.h",
"runtime/Cpp/runtime/src/WritableToken.cpp",
"runtime/Cpp/runtime/src/WritableToken.h",
"runtime/Cpp/runtime/src/antlr4-common.h",
"runtime/Cpp/runtime/src/antlr4-runtime.h",
"runtime/Cpp/runtime/src/atn/ATN.cpp",
"runtime/Cpp/runtime/src/atn/ATN.h",
"runtime/Cpp/runtime/src/atn/ATNConfig.cpp",
"runtime/Cpp/runtime/src/atn/ATNConfig.h",
"runtime/Cpp/runtime/src/atn/ATNConfigSet.cpp",
"runtime/Cpp/runtime/src/atn/ATNConfigSet.h",
"runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.cpp",
"runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.h",
"runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp",
"runtime/Cpp/runtime/src/atn/ATNDeserializer.h",
"runtime/Cpp/runtime/src/atn/ATNSerializer.cpp",
"runtime/Cpp/runtime/src/atn/ATNSerializer.h",
"runtime/Cpp/runtime/src/atn/ATNSimulator.cpp",
"runtime/Cpp/runtime/src/atn/ATNSimulator.h",
"runtime/Cpp/runtime/src/atn/ATNState.cpp",
"runtime/Cpp/runtime/src/atn/ATNState.h",
"runtime/Cpp/runtime/src/atn/ATNType.h",
"runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.cpp",
"runtime/Cpp/runtime/src/atn/AbstractPredicateTransition.h",
"runtime/Cpp/runtime/src/atn/ActionTransition.cpp",
"runtime/Cpp/runtime/src/atn/ActionTransition.h",
"runtime/Cpp/runtime/src/atn/AmbiguityInfo.cpp",
"runtime/Cpp/runtime/src/atn/AmbiguityInfo.h",
"runtime/Cpp/runtime/src/atn/ArrayPredictionContext.cpp",
"runtime/Cpp/runtime/src/atn/ArrayPredictionContext.h",
"runtime/Cpp/runtime/src/atn/AtomTransition.cpp",
"runtime/Cpp/runtime/src/atn/AtomTransition.h",
"runtime/Cpp/runtime/src/atn/BasicBlockStartState.cpp",
"runtime/Cpp/runtime/src/atn/BasicBlockStartState.h",
"runtime/Cpp/runtime/src/atn/BasicState.cpp",
"runtime/Cpp/runtime/src/atn/BasicState.h",
"runtime/Cpp/runtime/src/atn/BlockEndState.cpp",
"runtime/Cpp/runtime/src/atn/BlockEndState.h",
"runtime/Cpp/runtime/src/atn/BlockStartState.cpp",
"runtime/Cpp/runtime/src/atn/BlockStartState.h",
"runtime/Cpp/runtime/src/atn/ContextSensitivityInfo.cpp",
"runtime/Cpp/runtime/src/atn/ContextSensitivityInfo.h",
"runtime/Cpp/runtime/src/atn/DecisionEventInfo.cpp",
"runtime/Cpp/runtime/src/atn/DecisionEventInfo.h",
"runtime/Cpp/runtime/src/atn/DecisionInfo.cpp",
"runtime/Cpp/runtime/src/atn/DecisionInfo.h",
"runtime/Cpp/runtime/src/atn/DecisionState.cpp",
"runtime/Cpp/runtime/src/atn/DecisionState.h",
"runtime/Cpp/runtime/src/atn/EmptyPredictionContext.cpp",
"runtime/Cpp/runtime/src/atn/EmptyPredictionContext.h",
"runtime/Cpp/runtime/src/atn/EpsilonTransition.cpp",
"runtime/Cpp/runtime/src/atn/EpsilonTransition.h",
"runtime/Cpp/runtime/src/atn/ErrorInfo.cpp",
"runtime/Cpp/runtime/src/atn/ErrorInfo.h",
"runtime/Cpp/runtime/src/atn/LL1Analyzer.cpp",
"runtime/Cpp/runtime/src/atn/LL1Analyzer.h",
"runtime/Cpp/runtime/src/atn/LexerATNConfig.cpp",
"runtime/Cpp/runtime/src/atn/LexerATNConfig.h",
"runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp",
"runtime/Cpp/runtime/src/atn/LexerATNSimulator.h",
"runtime/Cpp/runtime/src/atn/LexerAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerAction.h",
"runtime/Cpp/runtime/src/atn/LexerActionExecutor.cpp",
"runtime/Cpp/runtime/src/atn/LexerActionExecutor.h",
"runtime/Cpp/runtime/src/atn/LexerActionType.h",
"runtime/Cpp/runtime/src/atn/LexerChannelAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerChannelAction.h",
"runtime/Cpp/runtime/src/atn/LexerCustomAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerCustomAction.h",
"runtime/Cpp/runtime/src/atn/LexerIndexedCustomAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerIndexedCustomAction.h",
"runtime/Cpp/runtime/src/atn/LexerModeAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerModeAction.h",
"runtime/Cpp/runtime/src/atn/LexerMoreAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerMoreAction.h",
"runtime/Cpp/runtime/src/atn/LexerPopModeAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerPopModeAction.h",
"runtime/Cpp/runtime/src/atn/LexerPushModeAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerPushModeAction.h",
"runtime/Cpp/runtime/src/atn/LexerSkipAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerSkipAction.h",
"runtime/Cpp/runtime/src/atn/LexerTypeAction.cpp",
"runtime/Cpp/runtime/src/atn/LexerTypeAction.h",
"runtime/Cpp/runtime/src/atn/LookaheadEventInfo.cpp",
"runtime/Cpp/runtime/src/atn/LookaheadEventInfo.h",
"runtime/Cpp/runtime/src/atn/LoopEndState.cpp",
"runtime/Cpp/runtime/src/atn/LoopEndState.h",
"runtime/Cpp/runtime/src/atn/NotSetTransition.cpp",
"runtime/Cpp/runtime/src/atn/NotSetTransition.h",
"runtime/Cpp/runtime/src/atn/OrderedATNConfigSet.cpp",
"runtime/Cpp/runtime/src/atn/OrderedATNConfigSet.h",
"runtime/Cpp/runtime/src/atn/ParseInfo.cpp",
"runtime/Cpp/runtime/src/atn/ParseInfo.h",
"runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp",
"runtime/Cpp/runtime/src/atn/ParserATNSimulator.h",
"runtime/Cpp/runtime/src/atn/PlusBlockStartState.cpp",
"runtime/Cpp/runtime/src/atn/PlusBlockStartState.h",
"runtime/Cpp/runtime/src/atn/PlusLoopbackState.cpp",
"runtime/Cpp/runtime/src/atn/PlusLoopbackState.h",
"runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.cpp",
"runtime/Cpp/runtime/src/atn/PrecedencePredicateTransition.h",
"runtime/Cpp/runtime/src/atn/PredicateEvalInfo.cpp",
"runtime/Cpp/runtime/src/atn/PredicateEvalInfo.h",
"runtime/Cpp/runtime/src/atn/PredicateTransition.cpp",
"runtime/Cpp/runtime/src/atn/PredicateTransition.h",
"runtime/Cpp/runtime/src/atn/PredictionContext.cpp",
"runtime/Cpp/runtime/src/atn/PredictionContext.h",
"runtime/Cpp/runtime/src/atn/PredictionMode.cpp",
"runtime/Cpp/runtime/src/atn/PredictionMode.h",
"runtime/Cpp/runtime/src/atn/ProfilingATNSimulator.cpp",
"runtime/Cpp/runtime/src/atn/ProfilingATNSimulator.h",
"runtime/Cpp/runtime/src/atn/RangeTransition.cpp",
"runtime/Cpp/runtime/src/atn/RangeTransition.h",
"runtime/Cpp/runtime/src/atn/RuleStartState.cpp",
"runtime/Cpp/runtime/src/atn/RuleStartState.h",
"runtime/Cpp/runtime/src/atn/RuleStopState.cpp",
"runtime/Cpp/runtime/src/atn/RuleStopState.h",
"runtime/Cpp/runtime/src/atn/RuleTransition.cpp",
"runtime/Cpp/runtime/src/atn/RuleTransition.h",
"runtime/Cpp/runtime/src/atn/SemanticContext.cpp",
"runtime/Cpp/runtime/src/atn/SemanticContext.h",
"runtime/Cpp/runtime/src/atn/SetTransition.cpp",
"runtime/Cpp/runtime/src/atn/SetTransition.h",
"runtime/Cpp/runtime/src/atn/SingletonPredictionContext.cpp",
"runtime/Cpp/runtime/src/atn/SingletonPredictionContext.h",
"runtime/Cpp/runtime/src/atn/StarBlockStartState.cpp",
"runtime/Cpp/runtime/src/atn/StarBlockStartState.h",
"runtime/Cpp/runtime/src/atn/StarLoopEntryState.cpp",
"runtime/Cpp/runtime/src/atn/StarLoopEntryState.h",
"runtime/Cpp/runtime/src/atn/StarLoopbackState.cpp",
"runtime/Cpp/runtime/src/atn/StarLoopbackState.h",
"runtime/Cpp/runtime/src/atn/TokensStartState.cpp",
"runtime/Cpp/runtime/src/atn/TokensStartState.h",
"runtime/Cpp/runtime/src/atn/Transition.cpp",
"runtime/Cpp/runtime/src/atn/Transition.h",
"runtime/Cpp/runtime/src/atn/WildcardTransition.cpp",
"runtime/Cpp/runtime/src/atn/WildcardTransition.h",
"runtime/Cpp/runtime/src/dfa/DFA.cpp",
"runtime/Cpp/runtime/src/dfa/DFA.h",
"runtime/Cpp/runtime/src/dfa/DFASerializer.cpp",
"runtime/Cpp/runtime/src/dfa/DFASerializer.h",
"runtime/Cpp/runtime/src/dfa/DFAState.cpp",
"runtime/Cpp/runtime/src/dfa/DFAState.h",
"runtime/Cpp/runtime/src/dfa/LexerDFASerializer.cpp",
"runtime/Cpp/runtime/src/dfa/LexerDFASerializer.h",
"runtime/Cpp/runtime/src/misc/InterpreterDataReader.cpp",
"runtime/Cpp/runtime/src/misc/InterpreterDataReader.h",
"runtime/Cpp/runtime/src/misc/Interval.cpp",
"runtime/Cpp/runtime/src/misc/Interval.h",
"runtime/Cpp/runtime/src/misc/IntervalSet.cpp",
"runtime/Cpp/runtime/src/misc/IntervalSet.h",
"runtime/Cpp/runtime/src/misc/MurmurHash.cpp",
"runtime/Cpp/runtime/src/misc/MurmurHash.h",
"runtime/Cpp/runtime/src/misc/Predicate.cpp",
"runtime/Cpp/runtime/src/misc/Predicate.h",
"runtime/Cpp/runtime/src/support/Any.cpp",
"runtime/Cpp/runtime/src/support/Any.h",
"runtime/Cpp/runtime/src/support/Arrays.cpp",
"runtime/Cpp/runtime/src/support/Arrays.h",
"runtime/Cpp/runtime/src/support/BitSet.h",
"runtime/Cpp/runtime/src/support/CPPUtils.cpp",
"runtime/Cpp/runtime/src/support/CPPUtils.h",
"runtime/Cpp/runtime/src/support/Declarations.h",
"runtime/Cpp/runtime/src/support/StringUtils.cpp",
"runtime/Cpp/runtime/src/support/StringUtils.h",
"runtime/Cpp/runtime/src/support/guid.cpp",
"runtime/Cpp/runtime/src/support/guid.h",
"runtime/Cpp/runtime/src/tree/AbstractParseTreeVisitor.h",
"runtime/Cpp/runtime/src/tree/ErrorNode.cpp",
"runtime/Cpp/runtime/src/tree/ErrorNode.h",
"runtime/Cpp/runtime/src/tree/ErrorNodeImpl.cpp",
"runtime/Cpp/runtime/src/tree/ErrorNodeImpl.h",
"runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.cpp",
"runtime/Cpp/runtime/src/tree/IterativeParseTreeWalker.h",
"runtime/Cpp/runtime/src/tree/ParseTree.cpp",
"runtime/Cpp/runtime/src/tree/ParseTree.h",
"runtime/Cpp/runtime/src/tree/ParseTreeListener.cpp",
"runtime/Cpp/runtime/src/tree/ParseTreeListener.h",
"runtime/Cpp/runtime/src/tree/ParseTreeProperty.h",
"runtime/Cpp/runtime/src/tree/ParseTreeVisitor.cpp",
"runtime/Cpp/runtime/src/tree/ParseTreeVisitor.h",
"runtime/Cpp/runtime/src/tree/ParseTreeWalker.cpp",
"runtime/Cpp/runtime/src/tree/ParseTreeWalker.h",
"runtime/Cpp/runtime/src/tree/TerminalNode.cpp",
"runtime/Cpp/runtime/src/tree/TerminalNode.h",
"runtime/Cpp/runtime/src/tree/TerminalNodeImpl.cpp",
"runtime/Cpp/runtime/src/tree/TerminalNodeImpl.h",
"runtime/Cpp/runtime/src/tree/Trees.cpp",
"runtime/Cpp/runtime/src/tree/Trees.h",
"runtime/Cpp/runtime/src/tree/pattern/Chunk.cpp",
"runtime/Cpp/runtime/src/tree/pattern/Chunk.h",
"runtime/Cpp/runtime/src/tree/pattern/ParseTreeMatch.cpp",
"runtime/Cpp/runtime/src/tree/pattern/ParseTreeMatch.h",
"runtime/Cpp/runtime/src/tree/pattern/ParseTreePattern.cpp",
"runtime/Cpp/runtime/src/tree/pattern/ParseTreePattern.h",
"runtime/Cpp/runtime/src/tree/pattern/ParseTreePatternMatcher.cpp",
"runtime/Cpp/runtime/src/tree/pattern/ParseTreePatternMatcher.h",
"runtime/Cpp/runtime/src/tree/pattern/RuleTagToken.cpp",
"runtime/Cpp/runtime/src/tree/pattern/RuleTagToken.h",
"runtime/Cpp/runtime/src/tree/pattern/TagChunk.cpp",
"runtime/Cpp/runtime/src/tree/pattern/TagChunk.h",
"runtime/Cpp/runtime/src/tree/pattern/TextChunk.cpp",
"runtime/Cpp/runtime/src/tree/pattern/TextChunk.h",
"runtime/Cpp/runtime/src/tree/pattern/TokenTagToken.cpp",
"runtime/Cpp/runtime/src/tree/pattern/TokenTagToken.h",
"runtime/Cpp/runtime/src/tree/xpath/XPath.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPath.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathElement.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathLexer.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathLexer.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathLexerErrorListener.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathLexerErrorListener.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathRuleAnywhereElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathRuleAnywhereElement.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathRuleElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathRuleElement.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathTokenAnywhereElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathTokenAnywhereElement.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathTokenElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathTokenElement.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathWildcardAnywhereElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathWildcardAnywhereElement.h",
"runtime/Cpp/runtime/src/tree/xpath/XPathWildcardElement.cpp",
"runtime/Cpp/runtime/src/tree/xpath/XPathWildcardElement.h",
]
configs -= [
"//build/config/compiler:chromium_code",
"//build/config/compiler:no_rtti",
"//build/config/compiler:no_exceptions",
]
configs += [
"//build/config/compiler:no_chromium_code",
"//build/config/compiler:rtti",
"//build/config/compiler:exceptions",
":antlr-compatibility",
]
}

View File

@ -1,52 +0,0 @@
[The "BSD 3-clause license"]
Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=====
MIT License for codepointat.js from https://git.io/codepointat
MIT License for fromcodepoint.js from https://git.io/vDW1m
Copyright Mathias Bynens <https://mathiasbynens.be/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,59 +0,0 @@
# C++ target for ANTLR 4
This folder contains the C++ runtime support for ANTLR. See [the canonical antlr4 repository](https://github.com/antlr/antlr4) for in depth detail about how to use ANTLR 4.
## Authors and major contributors
ANTLR 4 is the result of substantial effort of the following people:
* [Terence Parr](http://www.cs.usfca.edu/~parrt/), parrt@cs.usfca.edu
ANTLR project lead and supreme dictator for life
[University of San Francisco](http://www.usfca.edu/)
* [Sam Harwell](http://tunnelvisionlabs.com/)
Tool co-author, Java and C# target)
The C++ target has been the work of the following people:
* Dan McLaughlin, dan.mclaughlin@gmail.com (initial port, got code to compile)
* David Sisson, dsisson@google.com (initial port, made the runtime C++ tests runnable)
* [Mike Lischke](www.soft-gems.net), mike@lischke-online.de (brought the initial port to a working library, made most runtime tests passing)
## Other contributors
* Marcin Szalowicz, mszalowicz@mailplus.pl (cmake build setup)
* Tim O'Callaghan, timo@linux.com (additional superbuild cmake pattern script)
## Project Status
* Building on OS X, Windows, and Linux
* No errors and warnings
* Library linking
* Some unit tests in the OSX project, for important base classes with almost 100% code coverage.
* All memory allocations checked
* Simple command line demo application working on all supported platforms.
* All runtime tests pass.
### Build + Usage Notes
The minimum C++ version to compile the ANTLR C++ runtime with is C++11. The supplied projects can built the runtime either as static or dynamic library, as both 32bit and 64bit arch. The OSX project contains a target for iOS and can also be built using cmake (instead of XCode).
Include the antlr4-runtime.h umbrella header in your target application to get everything needed to use the library.
If you are compiling with cmake, the minimum version required is cmake 2.8.
#### Compiling on Windows
Simply open the VS solution (VS 2013+) and build it.
#### Compiling on OSX
Either open the included XCode project and build that or use the cmake compilation as described for linux.
#### Compiling on Linux
- cd <antlr4-dir>/runtime/Cpp (this is where this readme is located)
- mkdir build && mkdir run && cd build
- cmake .. -DANTLR_JAR_LOCATION=full/path/to/antlr4-4.5.4-SNAPSHOT.jar -DWITH_DEMO=True
- make
- DESTDIR=<antlr4-dir>/runtime/Cpp/run make install
If you don't want to build the demo then simply run cmake without parameters.
There is another cmake script available in the subfolder cmake/ for those who prefer the superbuild cmake pattern.

View File

@ -1 +0,0 @@
4.7.1

View File

@ -1,8 +0,0 @@
/* 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.
*/
#include "ANTLRErrorListener.h"
antlr4::ANTLRErrorListener::~ANTLRErrorListener() {}

View File

@ -1,171 +0,0 @@
/* 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.
*/
#pragma once
#include "RecognitionException.h"
namespace antlrcpp {
class BitSet;
}
namespace antlr4 {
/// How to emit recognition errors (an interface in Java).
class ANTLR4CPP_PUBLIC ANTLRErrorListener {
public:
virtual ~ANTLRErrorListener();
/// <summary>
/// Upon syntax error, notify any interested parties. This is not how to
/// recover from errors or compute error messages. <seealso
/// cref="ANTLRErrorStrategy"/> specifies how to recover from syntax errors
/// and how to compute error messages. This listener's job is simply to emit a
/// computed message, though it has enough information to create its own
/// message in many cases. <p/> The <seealso cref="RecognitionException"/> is
/// non-null for all syntax errors except when we discover mismatched token
/// errors that we can recover from in-line, without returning from the
/// surrounding rule (via the single token insertion and deletion mechanism).
/// </summary>
/// <param name="recognizer">
/// What parser got the error. From this
/// object, you can access the context as well
/// as the input stream. </param>
/// <param name="offendingSymbol">
/// The offending token in the input token
/// stream, unless recognizer is a lexer (then it's null). If
/// no viable alternative error, {@code e} has token at which we
/// started production for the decision. </param>
/// <param name="line">
/// The line number in the input where the error occurred.
/// </param> <param name="charPositionInLine"> The character
/// position within that line where the error occurred. </param> <param
/// name="msg"> The message to emit. </param> <param name="e">
/// The exception generated by the parser that led to
/// the reporting of an error. It is null in the case where
/// the parser was able to recover in line without exiting the
/// surrounding rule. </param>
virtual void syntaxError(Recognizer* recognizer, Token* offendingSymbol,
size_t line, size_t charPositionInLine,
const std::string& msg, std::exception_ptr e) = 0;
/**
* This method is called by the parser when a full-context prediction
* results in an ambiguity.
*
* <p>Each full-context prediction which does not result in a syntax error
* will call either {@link #reportContextSensitivity} or
* {@link #reportAmbiguity}.</p>
*
* <p>When {@code ambigAlts} is not null, it contains the set of potentially
* viable alternatives identified by the prediction algorithm. When
* {@code ambigAlts} is null, use {@link ATNConfigSet#getAlts} to obtain the
* represented alternatives from the {@code configs} argument.</p>
*
* <p>When {@code exact} is {@code true}, <em>all</em> of the potentially
* viable alternatives are truly viable, i.e. this is reporting an exact
* ambiguity. When {@code exact} is {@code false}, <em>at least two</em> of
* the potentially viable alternatives are viable for the current input, but
* the prediction algorithm terminated as soon as it determined that at
* least the <em>minimum</em> potentially viable alternative is truly
* viable.</p>
*
* <p>When the {@link PredictionMode#LL_EXACT_AMBIG_DETECTION} prediction
* mode is used, the parser is required to identify exact ambiguities so
* {@code exact} will always be {@code true}.</p>
*
* <p>This method is not used by lexers.</p>
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input input where the ambiguity was identified
* @param exact {@code true} if the ambiguity is exactly known, otherwise
* {@code false}. This is always {@code true} when
* {@link PredictionMode#LL_EXACT_AMBIG_DETECTION} is used.
* @param ambigAlts the potentially ambiguous alternatives, or {@code null}
* to indicate that the potentially ambiguous alternatives are the complete
* set of represented alternatives in {@code configs}
* @param configs the ATN configuration set where the ambiguity was
* identified
*/
virtual void reportAmbiguity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet& ambigAlts,
atn::ATNConfigSet* configs) = 0;
/**
* This method is called when an SLL conflict occurs and the parser is about
* to use the full context information to make an LL decision.
*
* <p>If one or more configurations in {@code configs} contains a semantic
* predicate, the predicates are evaluated before this method is called. The
* subset of alternatives which are still viable after predicates are
* evaluated is reported in {@code conflictingAlts}.</p>
*
* <p>This method is not used by lexers.</p>
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input index where the SLL conflict occurred
* @param conflictingAlts The specific conflicting alternatives. If this is
* {@code null}, the conflicting alternatives are all alternatives
* represented in {@code configs}. At the moment, conflictingAlts is non-null
* (for the reference implementation, but Sam's optimized version can see this
* as null).
* @param configs the ATN configuration set where the SLL conflict was
* detected
*/
virtual void reportAttemptingFullContext(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet& conflictingAlts,
atn::ATNConfigSet* configs) = 0;
/**
* This method is called by the parser when a full-context prediction has a
* unique result.
*
* <p>Each full-context prediction which does not result in a syntax error
* will call either {@link #reportContextSensitivity} or
* {@link #reportAmbiguity}.</p>
*
* <p>For prediction implementations that only evaluate full-context
* predictions when an SLL conflict is found (including the default
* {@link ParserATNSimulator} implementation), this method reports cases
* where SLL conflicts were resolved to unique full-context predictions,
* i.e. the decision was context-sensitive. This report does not necessarily
* indicate a problem, and it may appear even in completely unambiguous
* grammars.</p>
*
* <p>{@code configs} may have more than one represented alternative if the
* full-context prediction algorithm does not evaluate predicates before
* beginning the full-context prediction. In all cases, the final prediction
* is passed as the {@code prediction} argument.</p>
*
* <p>Note that the definition of "context sensitivity" in this method
* differs from the concept in {@link DecisionInfo#contextSensitivities}.
* This method reports all instances where an SLL conflict occurred but LL
* parsing produced a unique result, whether or not that unique result
* matches the minimum alternative in the SLL conflicting set.</p>
*
* <p>This method is not used by lexers.</p>
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input index where the context sensitivity was
* finally determined
* @param prediction the unambiguous result of the full-context prediction
* @param configs the ATN configuration set where the unambiguous prediction
* was determined
*/
virtual void reportContextSensitivity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex,
size_t prediction,
atn::ATNConfigSet* configs) = 0;
};
} // namespace antlr4

View File

@ -1,8 +0,0 @@
/* 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.
*/
#include "ANTLRErrorStrategy.h"
antlr4::ANTLRErrorStrategy::~ANTLRErrorStrategy() {}

View File

@ -1,121 +0,0 @@
/* 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.
*/
#pragma once
#include "Token.h"
namespace antlr4 {
/// <summary>
/// The interface for defining strategies to deal with syntax errors encountered
/// during a parse by ANTLR-generated parsers. We distinguish between three
/// different kinds of errors:
///
/// <ul>
/// <li>The parser could not figure out which path to take in the ATN (none of
/// the available alternatives could possibly match)</li>
/// <li>The current input does not match what we were looking for</li>
/// <li>A predicate evaluated to false</li>
/// </ul>
///
/// Implementations of this interface report syntax errors by calling
/// <seealso cref="Parser#notifyErrorListeners"/>.
/// <p/>
/// TO_DO: what to do about lexers
/// </summary>
class ANTLR4CPP_PUBLIC ANTLRErrorStrategy {
public:
/// <summary>
/// Reset the error handler state for the specified {@code recognizer}.
/// </summary> <param name="recognizer"> the parser instance </param>
virtual ~ANTLRErrorStrategy();
virtual void reset(Parser* recognizer) = 0;
/**
* This method is called when an unexpected symbol is encountered during an
* inline match operation, such as {@link Parser#match}. If the error
* strategy successfully recovers from the match failure, this method
* returns the {@link Token} instance which should be treated as the
* successful result of the match.
*
* <p>This method handles the consumption of any tokens - the caller should
* <b>not</b> call {@link Parser#consume} after a successful recovery.</p>
*
* <p>Note that the calling code will not report an error if this method
* returns successfully. The error strategy implementation is responsible
* for calling {@link Parser#notifyErrorListeners} as appropriate.</p>
*
* @param recognizer the parser instance
* @throws RecognitionException if the error strategy was not able to
* recover from the unexpected input symbol
*/
virtual Token* recoverInline(Parser* recognizer) = 0;
/// <summary>
/// This method is called to recover from exception {@code e}. This method is
/// called after <seealso cref="#reportError"/> by the default exception
/// handler generated for a rule method.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception to recover from </param>
/// <exception cref="RecognitionException"> if the error strategy could not
/// recover from the recognition exception </exception>
virtual void recover(Parser* recognizer, std::exception_ptr e) = 0;
/// <summary>
/// This method provides the error handler with an opportunity to handle
/// syntactic or semantic errors in the input stream before they result in a
/// <seealso cref="RecognitionException"/>.
/// <p/>
/// The generated code currently contains calls to <seealso cref="#sync"/>
/// after entering the decision state of a closure block ({@code (...)*} or
/// {@code (...)+}).
/// <p/>
/// For an implementation based on Jim Idle's "magic sync" mechanism, see
/// <seealso cref="DefaultErrorStrategy#sync"/>.
/// </summary>
/// <seealso cref= DefaultErrorStrategy#sync
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <exception cref="RecognitionException"> if an error is detected by the
/// error strategy but cannot be automatically recovered at the current state
/// in the parsing process </exception>
virtual void sync(Parser* recognizer) = 0;
/// <summary>
/// Tests whether or not {@code recognizer} is in the process of recovering
/// from an error. In error recovery mode, <seealso cref="Parser#consume"/>
/// adds symbols to the parse tree by calling
/// {@link Parser#createErrorNode(ParserRuleContext, Token)} then
/// {@link ParserRuleContext#addErrorNode(ErrorNode)} instead of
/// {@link Parser#createTerminalNode(ParserRuleContext, Token)}.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <returns> {@code true} if the parser is currently recovering from a parse
/// error, otherwise {@code false} </returns>
virtual bool inErrorRecoveryMode(Parser* recognizer) = 0;
/// <summary>
/// This method is called by when the parser successfully matches an input
/// symbol.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
virtual void reportMatch(Parser* recognizer) = 0;
/// <summary>
/// Report any kind of <seealso cref="RecognitionException"/>. This method is
/// called by the default exception handler generated for a rule method.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception to report </param>
virtual void reportError(Parser* recognizer,
const RecognitionException& e) = 0;
};
} // namespace antlr4

View File

@ -1,32 +0,0 @@
/* 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.
*/
#include "support/StringUtils.h"
#include "ANTLRFileStream.h"
using namespace antlr4;
ANTLRFileStream::ANTLRFileStream(const std::string& fileName) {
_fileName = fileName;
loadFromFile(fileName);
}
void ANTLRFileStream::loadFromFile(const std::string& fileName) {
_fileName = fileName;
if (_fileName.empty()) {
return;
}
#ifdef _MSC_VER
std::ifstream stream(antlrcpp::s2ws(fileName), std::ios::binary);
#else
std::ifstream stream(fileName, std::ios::binary);
#endif
ANTLRInputStream::load(stream);
}
std::string ANTLRFileStream::getSourceName() const { return _fileName; }

View File

@ -1,28 +0,0 @@
/* 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.
*/
#pragma once
#include "ANTLRInputStream.h"
namespace antlr4 {
/// This is an ANTLRInputStream that is loaded from a file all at once
/// when you construct the object (or call load()).
// TODO: this class needs testing.
class ANTLR4CPP_PUBLIC ANTLRFileStream : public ANTLRInputStream {
protected:
std::string _fileName; // UTF-8 encoded file name.
public:
// Assumes a file name encoded in UTF-8 and file content in the same encoding
// (with or w/o BOM).
ANTLRFileStream(const std::string& fileName);
virtual void loadFromFile(const std::string& fileName);
virtual std::string getSourceName() const override;
};
} // namespace antlr4

View File

@ -1,143 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "IntStream.h"
#include "misc/Interval.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "ANTLRInputStream.h"
using namespace antlr4;
using namespace antlrcpp;
using misc::Interval;
ANTLRInputStream::ANTLRInputStream(const std::string& input) {
InitializeInstanceFields();
load(input);
}
ANTLRInputStream::ANTLRInputStream(const char data_[],
size_t numberOfActualCharsInArray)
: ANTLRInputStream(std::string(data_, numberOfActualCharsInArray)) {}
ANTLRInputStream::ANTLRInputStream(std::istream& stream) {
InitializeInstanceFields();
load(stream);
}
void ANTLRInputStream::load(const std::string& input) {
// Remove the UTF-8 BOM if present.
const char bom[4] = "\xef\xbb\xbf";
if (input.compare(0, 3, bom, 3) == 0)
_data =
antlrcpp::utf8_to_utf32(input.data() + 3, input.data() + input.size());
else
_data = antlrcpp::utf8_to_utf32(input.data(), input.data() + input.size());
p = 0;
}
void ANTLRInputStream::load(std::istream& stream) {
if (!stream.good() || stream.eof()) // No fail, bad or EOF.
return;
_data.clear();
std::string s((std::istreambuf_iterator<char>(stream)),
std::istreambuf_iterator<char>());
load(s);
}
void ANTLRInputStream::reset() { p = 0; }
void ANTLRInputStream::consume() {
if (p >= _data.size()) {
assert(LA(1) == IntStream::EOF);
throw IllegalStateException("cannot consume EOF");
}
if (p < _data.size()) {
p++;
}
}
size_t ANTLRInputStream::LA(ssize_t i) {
if (i == 0) {
return 0; // undefined
}
ssize_t position = static_cast<ssize_t>(p);
if (i < 0) {
i++; // e.g., translate LA(-1) to use offset i=0; then _data[p+0-1]
if ((position + i - 1) < 0) {
return IntStream::EOF; // invalid; no char before first char
}
}
if ((position + i - 1) >= static_cast<ssize_t>(_data.size())) {
return IntStream::EOF;
}
return _data[static_cast<size_t>((position + i - 1))];
}
size_t ANTLRInputStream::LT(ssize_t i) { return LA(i); }
size_t ANTLRInputStream::index() { return p; }
size_t ANTLRInputStream::size() { return _data.size(); }
// Mark/release do nothing. We have entire buffer.
ssize_t ANTLRInputStream::mark() { return -1; }
void ANTLRInputStream::release(ssize_t /* marker */) {}
void ANTLRInputStream::seek(size_t index) {
if (index <= p) {
p = index; // just jump; don't update stream state (line, ...)
return;
}
// seek forward, consume until p hits index or n (whichever comes first)
index = std::min(index, _data.size());
while (p < index) {
consume();
}
}
std::string ANTLRInputStream::getText(const Interval& interval) {
if (interval.a < 0 || interval.b < 0) {
return "";
}
size_t start = static_cast<size_t>(interval.a);
size_t stop = static_cast<size_t>(interval.b);
if (stop >= _data.size()) {
stop = _data.size() - 1;
}
size_t count = stop - start + 1;
if (start >= _data.size()) {
return "";
}
return antlrcpp::utf32_to_utf8(_data.substr(start, count));
}
std::string ANTLRInputStream::getSourceName() const {
if (name.empty()) {
return IntStream::UNKNOWN_SOURCE_NAME;
}
return name;
}
std::string ANTLRInputStream::toString() const {
return antlrcpp::utf32_to_utf8(_data);
}
void ANTLRInputStream::InitializeInstanceFields() { p = 0; }

View File

@ -1,69 +0,0 @@
/* 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.
*/
#pragma once
#include "CharStream.h"
namespace antlr4 {
// Vacuum all input from a stream and then treat it
// like a string. Can also pass in a string or char[] to use.
// Input is expected to be encoded in UTF-8 and converted to UTF-32 internally.
class ANTLR4CPP_PUBLIC ANTLRInputStream : public CharStream {
protected:
/// The data being scanned.
// UTF-32
UTF32String _data;
/// 0..n-1 index into string of next char </summary>
size_t p;
public:
/// What is name or source of this char stream?
std::string name;
ANTLRInputStream(const std::string& input = "");
ANTLRInputStream(const char data_[], size_t numberOfActualCharsInArray);
ANTLRInputStream(std::istream& stream);
virtual void load(const std::string& input);
virtual void load(std::istream& stream);
/// Reset the stream so that it's in the same state it was
/// when the object was created *except* the data array is not
/// touched.
virtual void reset();
virtual void consume() override;
virtual size_t LA(ssize_t i) override;
virtual size_t LT(ssize_t i);
/// <summary>
/// Return the current input symbol index 0..n where n indicates the
/// last symbol has been read. The index is the index of char to
/// be returned from LA(1).
/// </summary>
virtual size_t index() override;
virtual size_t size() override;
/// <summary>
/// mark/release do nothing; we have entire buffer </summary>
virtual ssize_t mark() override;
virtual void release(ssize_t marker) override;
/// <summary>
/// consume() ahead until p==index; can't just set p=index as we must
/// update line and charPositionInLine. If we seek backwards, just set p
/// </summary>
virtual void seek(size_t index) override;
virtual std::string getText(const misc::Interval& interval) override;
virtual std::string getSourceName() const override;
virtual std::string toString() const override;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,59 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "InputMismatchException.h"
#include "Parser.h"
#include "ParserRuleContext.h"
#include "BailErrorStrategy.h"
using namespace antlr4;
void BailErrorStrategy::recover(Parser* recognizer, std::exception_ptr e) {
ParserRuleContext* context = recognizer->getContext();
do {
context->exception = e;
if (context->parent == nullptr) break;
context = static_cast<ParserRuleContext*>(context->parent);
} while (true);
try {
std::rethrow_exception(
e); // Throw the exception to be able to catch and rethrow nested.
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
} catch (RecognitionException& inner) {
throw ParseCancellationException(inner.what());
#else
} catch (RecognitionException& /*inner*/) {
std::throw_with_nested(ParseCancellationException());
#endif
}
}
Token* BailErrorStrategy::recoverInline(Parser* recognizer) {
InputMismatchException e(recognizer);
std::exception_ptr exception = std::make_exception_ptr(e);
ParserRuleContext* context = recognizer->getContext();
do {
context->exception = exception;
if (context->parent == nullptr) break;
context = static_cast<ParserRuleContext*>(context->parent);
} while (true);
try {
throw e;
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
} catch (InputMismatchException& inner) {
throw ParseCancellationException(inner.what());
#else
} catch (InputMismatchException& /*inner*/) {
std::throw_with_nested(ParseCancellationException());
#endif
}
}
void BailErrorStrategy::sync(Parser* /*recognizer*/) {}

View File

@ -1,60 +0,0 @@
/* 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.
*/
#pragma once
#include "DefaultErrorStrategy.h"
namespace antlr4 {
/**
* This implementation of {@link ANTLRErrorStrategy} responds to syntax errors
* by immediately canceling the parse operation with a
* {@link ParseCancellationException}. The implementation ensures that the
* {@link ParserRuleContext#exception} field is set for all parse tree nodes
* that were not completed prior to encountering the error.
*
* <p>
* This error strategy is useful in the following scenarios.</p>
*
* <ul>
* <li><strong>Two-stage parsing:</strong> This error strategy allows the first
* stage of two-stage parsing to immediately terminate if an error is
* encountered, and immediately fall back to the second stage. In addition to
* avoiding wasted work by attempting to recover from errors here, the empty
* implementation of {@link BailErrorStrategy#sync} improves the performance of
* the first stage.</li>
* <li><strong>Silent validation:</strong> When syntax errors are not being
* reported or logged, and the parse result is simply ignored if errors occur,
* the {@link BailErrorStrategy} avoids wasting work on recovering from errors
* when the result will be ignored either way.</li>
* </ul>
*
* <p>
* {@code myparser.setErrorHandler(new BailErrorStrategy());}</p>
*
* @see Parser#setErrorHandler(ANTLRErrorStrategy)
*/
class ANTLR4CPP_PUBLIC BailErrorStrategy : public DefaultErrorStrategy {
/// <summary>
/// Instead of recovering from exception {@code e}, re-throw it wrapped
/// in a <seealso cref="ParseCancellationException"/> so it is not caught by
/// the rule function catches. Use <seealso cref="Exception#getCause()"/> to
/// get the original <seealso cref="RecognitionException"/>.
/// </summary>
public:
virtual void recover(Parser* recognizer, std::exception_ptr e) override;
/// Make sure we don't attempt to recover inline; if the parser
/// successfully recovers, it won't throw an exception.
virtual Token* recoverInline(Parser* recognizer) override;
/// <summary>
/// Make sure we don't attempt to recover from problems in subrules.
/// </summary>
virtual void sync(Parser* recognizer) override;
};
} // namespace antlr4

View File

@ -1,32 +0,0 @@
/* 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.
*/
#include "BaseErrorListener.h"
#include "RecognitionException.h"
using namespace antlr4;
void BaseErrorListener::syntaxError(Recognizer* /*recognizer*/,
Token* /*offendingSymbol*/, size_t /*line*/,
size_t /*charPositionInLine*/,
const std::string& /*msg*/,
std::exception_ptr /*e*/) {}
void BaseErrorListener::reportAmbiguity(Parser* /*recognizer*/,
const dfa::DFA& /*dfa*/,
size_t /*startIndex*/,
size_t /*stopIndex*/, bool /*exact*/,
const antlrcpp::BitSet& /*ambigAlts*/,
atn::ATNConfigSet* /*configs*/) {}
void BaseErrorListener::reportAttemptingFullContext(
Parser* /*recognizer*/, const dfa::DFA& /*dfa*/, size_t /*startIndex*/,
size_t /*stopIndex*/, const antlrcpp::BitSet& /*conflictingAlts*/,
atn::ATNConfigSet* /*configs*/) {}
void BaseErrorListener::reportContextSensitivity(
Parser* /*recognizer*/, const dfa::DFA& /*dfa*/, size_t /*startIndex*/,
size_t /*stopIndex*/, size_t /*prediction*/,
atn::ATNConfigSet* /*configs*/) {}

View File

@ -1,43 +0,0 @@
/* 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.
*/
#pragma once
#include "ANTLRErrorListener.h"
namespace antlrcpp {
class BitSet;
}
namespace antlr4 {
/**
* Provides an empty default implementation of {@link ANTLRErrorListener}. The
* default implementation of each method does nothing, but can be overridden as
* necessary.
*/
class ANTLR4CPP_PUBLIC BaseErrorListener : public ANTLRErrorListener {
virtual void syntaxError(Recognizer* recognizer, Token* offendingSymbol,
size_t line, size_t charPositionInLine,
const std::string& msg,
std::exception_ptr e) override;
virtual void reportAmbiguity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet& ambigAlts,
atn::ATNConfigSet* configs) override;
virtual void reportAttemptingFullContext(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet& conflictingAlts,
atn::ATNConfigSet* configs) override;
virtual void reportContextSensitivity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex,
size_t prediction,
atn::ATNConfigSet* configs) override;
};
} // namespace antlr4

View File

@ -1,407 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "Lexer.h"
#include "RuleContext.h"
#include "WritableToken.h"
#include "misc/Interval.h"
#include "support/CPPUtils.h"
#include "BufferedTokenStream.h"
using namespace antlr4;
using namespace antlrcpp;
BufferedTokenStream::BufferedTokenStream(TokenSource* tokenSource)
: _tokenSource(tokenSource) {
InitializeInstanceFields();
}
TokenSource* BufferedTokenStream::getTokenSource() const {
return _tokenSource;
}
size_t BufferedTokenStream::index() { return _p; }
ssize_t BufferedTokenStream::mark() { return 0; }
void BufferedTokenStream::release(ssize_t /*marker*/) {
// no resources to release
}
void BufferedTokenStream::reset() { seek(0); }
void BufferedTokenStream::seek(size_t index) {
lazyInit();
_p = adjustSeekIndex(index);
}
size_t BufferedTokenStream::size() { return _tokens.size(); }
void BufferedTokenStream::consume() {
bool skipEofCheck = false;
if (!_needSetup) {
if (_fetchedEOF) {
// the last token in tokens is EOF. skip check if p indexes any
// fetched token except the last.
skipEofCheck = _p < _tokens.size() - 1;
} else {
// no EOF token in tokens. skip check if p indexes a fetched token.
skipEofCheck = _p < _tokens.size();
}
} else {
// not yet initialized
skipEofCheck = false;
}
if (!skipEofCheck && LA(1) == Token::EOF) {
throw IllegalStateException("cannot consume EOF");
}
if (sync(_p + 1)) {
_p = adjustSeekIndex(_p + 1);
}
}
bool BufferedTokenStream::sync(size_t i) {
if (i + 1 < _tokens.size()) return true;
size_t n = i - _tokens.size() + 1; // how many more elements we need?
if (n > 0) {
size_t fetched = fetch(n);
return fetched >= n;
}
return true;
}
size_t BufferedTokenStream::fetch(size_t n) {
if (_fetchedEOF) {
return 0;
}
size_t i = 0;
while (i < n) {
std::unique_ptr<Token> t(_tokenSource->nextToken());
if (is<WritableToken*>(t.get())) {
(static_cast<WritableToken*>(t.get()))->setTokenIndex(_tokens.size());
}
_tokens.push_back(std::move(t));
++i;
if (_tokens.back()->getType() == Token::EOF) {
_fetchedEOF = true;
break;
}
}
return i;
}
Token* BufferedTokenStream::get(size_t i) const {
if (i >= _tokens.size()) {
throw IndexOutOfBoundsException(
std::string("token index ") + std::to_string(i) +
std::string(" out of range 0..") + std::to_string(_tokens.size() - 1));
}
return _tokens[i].get();
}
std::vector<Token*> BufferedTokenStream::get(size_t start, size_t stop) {
std::vector<Token*> subset;
lazyInit();
if (_tokens.empty()) {
return subset;
}
if (stop >= _tokens.size()) {
stop = _tokens.size() - 1;
}
for (size_t i = start; i <= stop; i++) {
Token* t = _tokens[i].get();
if (t->getType() == Token::EOF) {
break;
}
subset.push_back(t);
}
return subset;
}
size_t BufferedTokenStream::LA(ssize_t i) { return LT(i)->getType(); }
Token* BufferedTokenStream::LB(size_t k) {
if (k > _p) {
return nullptr;
}
return _tokens[_p - k].get();
}
Token* BufferedTokenStream::LT(ssize_t k) {
lazyInit();
if (k == 0) {
return nullptr;
}
if (k < 0) {
return LB(-k);
}
size_t i = _p + k - 1;
sync(i);
if (i >= _tokens.size()) { // return EOF token
// EOF must be last token
return _tokens.back().get();
}
return _tokens[i].get();
}
ssize_t BufferedTokenStream::adjustSeekIndex(size_t i) { return i; }
void BufferedTokenStream::lazyInit() {
if (_needSetup) {
setup();
}
}
void BufferedTokenStream::setup() {
_needSetup = false;
sync(0);
_p = adjustSeekIndex(0);
}
void BufferedTokenStream::setTokenSource(TokenSource* tokenSource) {
_tokenSource = tokenSource;
_tokens.clear();
_fetchedEOF = false;
_needSetup = true;
}
std::vector<Token*> BufferedTokenStream::getTokens() {
std::vector<Token*> result;
for (auto& t : _tokens) result.push_back(t.get());
return result;
}
std::vector<Token*> BufferedTokenStream::getTokens(size_t start, size_t stop) {
return getTokens(start, stop, std::vector<size_t>());
}
std::vector<Token*> BufferedTokenStream::getTokens(
size_t start, size_t stop, const std::vector<size_t>& types) {
lazyInit();
if (stop >= _tokens.size() || start >= _tokens.size()) {
throw IndexOutOfBoundsException(
std::string("start ") + std::to_string(start) +
std::string(" or stop ") + std::to_string(stop) +
std::string(" not in 0..") + std::to_string(_tokens.size() - 1));
}
std::vector<Token*> filteredTokens;
if (start > stop) {
return filteredTokens;
}
for (size_t i = start; i <= stop; i++) {
Token* tok = _tokens[i].get();
if (types.empty() ||
std::find(types.begin(), types.end(), tok->getType()) != types.end()) {
filteredTokens.push_back(tok);
}
}
return filteredTokens;
}
std::vector<Token*> BufferedTokenStream::getTokens(size_t start, size_t stop,
size_t ttype) {
std::vector<size_t> s;
s.push_back(ttype);
return getTokens(start, stop, s);
}
ssize_t BufferedTokenStream::nextTokenOnChannel(size_t i, size_t channel) {
sync(i);
if (i >= size()) {
return size() - 1;
}
Token* token = _tokens[i].get();
while (token->getChannel() != channel) {
if (token->getType() == Token::EOF) {
return i;
}
i++;
sync(i);
token = _tokens[i].get();
}
return i;
}
ssize_t BufferedTokenStream::previousTokenOnChannel(size_t i, size_t channel) {
sync(i);
if (i >= size()) {
// the EOF token is on every channel
return size() - 1;
}
while (true) {
Token* token = _tokens[i].get();
if (token->getType() == Token::EOF || token->getChannel() == channel) {
return i;
}
if (i == 0) break;
i--;
}
return i;
}
std::vector<Token*> BufferedTokenStream::getHiddenTokensToRight(
size_t tokenIndex, ssize_t channel) {
lazyInit();
if (tokenIndex >= _tokens.size()) {
throw IndexOutOfBoundsException(std::to_string(tokenIndex) + " not in 0.." +
std::to_string(_tokens.size() - 1));
}
ssize_t nextOnChannel =
nextTokenOnChannel(tokenIndex + 1, Lexer::DEFAULT_TOKEN_CHANNEL);
size_t to;
size_t from = tokenIndex + 1;
// if none onchannel to right, nextOnChannel=-1 so set to = last token
if (nextOnChannel == -1) {
to = static_cast<ssize_t>(size() - 1);
} else {
to = nextOnChannel;
}
return filterForChannel(from, to, channel);
}
std::vector<Token*> BufferedTokenStream::getHiddenTokensToRight(
size_t tokenIndex) {
return getHiddenTokensToRight(tokenIndex, -1);
}
std::vector<Token*> BufferedTokenStream::getHiddenTokensToLeft(
size_t tokenIndex, ssize_t channel) {
lazyInit();
if (tokenIndex >= _tokens.size()) {
throw IndexOutOfBoundsException(std::to_string(tokenIndex) + " not in 0.." +
std::to_string(_tokens.size() - 1));
}
if (tokenIndex == 0) {
// Obviously no tokens can appear before the first token.
return {};
}
ssize_t prevOnChannel =
previousTokenOnChannel(tokenIndex - 1, Lexer::DEFAULT_TOKEN_CHANNEL);
if (prevOnChannel == static_cast<ssize_t>(tokenIndex - 1)) {
return {};
}
// if none onchannel to left, prevOnChannel=-1 then from=0
size_t from = static_cast<size_t>(prevOnChannel + 1);
size_t to = tokenIndex - 1;
return filterForChannel(from, to, channel);
}
std::vector<Token*> BufferedTokenStream::getHiddenTokensToLeft(
size_t tokenIndex) {
return getHiddenTokensToLeft(tokenIndex, -1);
}
std::vector<Token*> BufferedTokenStream::filterForChannel(size_t from,
size_t to,
ssize_t channel) {
std::vector<Token*> hidden;
for (size_t i = from; i <= to; i++) {
Token* t = _tokens[i].get();
if (channel == -1) {
if (t->getChannel() != Lexer::DEFAULT_TOKEN_CHANNEL) {
hidden.push_back(t);
}
} else {
if (t->getChannel() == static_cast<size_t>(channel)) {
hidden.push_back(t);
}
}
}
return hidden;
}
bool BufferedTokenStream::isInitialized() const { return !_needSetup; }
/**
* Get the text of all tokens in this buffer.
*/
std::string BufferedTokenStream::getSourceName() const {
return _tokenSource->getSourceName();
}
std::string BufferedTokenStream::getText() {
return getText(misc::Interval(0U, size() - 1));
}
std::string BufferedTokenStream::getText(const misc::Interval& interval) {
lazyInit();
fill();
size_t start = interval.a;
size_t stop = interval.b;
if (start == INVALID_INDEX || stop == INVALID_INDEX) {
return "";
}
if (stop >= _tokens.size()) {
stop = _tokens.size() - 1;
}
std::stringstream ss;
for (size_t i = start; i <= stop; i++) {
Token* t = _tokens[i].get();
if (t->getType() == Token::EOF) {
break;
}
ss << t->getText();
}
return ss.str();
}
std::string BufferedTokenStream::getText(RuleContext* ctx) {
return getText(ctx->getSourceInterval());
}
std::string BufferedTokenStream::getText(Token* start, Token* stop) {
if (start != nullptr && stop != nullptr) {
return getText(
misc::Interval(start->getTokenIndex(), stop->getTokenIndex()));
}
return "";
}
void BufferedTokenStream::fill() {
lazyInit();
const size_t blockSize = 1000;
while (true) {
size_t fetched = fetch(blockSize);
if (fetched < blockSize) {
return;
}
}
}
void BufferedTokenStream::InitializeInstanceFields() {
_needSetup = true;
_fetchedEOF = false;
}

View File

@ -1,207 +0,0 @@
/* 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.
*/
#pragma once
#include "TokenStream.h"
namespace antlr4 {
/**
* This implementation of {@link TokenStream} loads tokens from a
* {@link TokenSource} on-demand, and places the tokens in a buffer to provide
* access to any previous token by index.
*
* <p>
* This token stream ignores the value of {@link Token#getChannel}. If your
* parser requires the token stream filter tokens to only those on a particular
* channel, such as {@link Token#DEFAULT_CHANNEL} or
* {@link Token#HIDDEN_CHANNEL}, use a filtering token stream such a
* {@link CommonTokenStream}.</p>
*/
class ANTLR4CPP_PUBLIC BufferedTokenStream : public TokenStream {
public:
BufferedTokenStream(TokenSource* tokenSource);
BufferedTokenStream(const BufferedTokenStream& other) = delete;
BufferedTokenStream& operator=(const BufferedTokenStream& other) = delete;
virtual TokenSource* getTokenSource() const override;
virtual size_t index() override;
virtual ssize_t mark() override;
virtual void release(ssize_t marker) override;
virtual void reset();
virtual void seek(size_t index) override;
virtual size_t size() override;
virtual void consume() override;
virtual Token* get(size_t i) const override;
/// Get all tokens from start..stop inclusively.
virtual std::vector<Token*> get(size_t start, size_t stop);
virtual size_t LA(ssize_t i) override;
virtual Token* LT(ssize_t k) override;
/// Reset this token stream by setting its token source.
virtual void setTokenSource(TokenSource* tokenSource);
virtual std::vector<Token*> getTokens();
virtual std::vector<Token*> getTokens(size_t start, size_t stop);
/// <summary>
/// Given a start and stop index, return a List of all tokens in
/// the token type BitSet. Return null if no tokens were found. This
/// method looks at both on and off channel tokens.
/// </summary>
virtual std::vector<Token*> getTokens(size_t start, size_t stop,
const std::vector<size_t>& types);
virtual std::vector<Token*> getTokens(size_t start, size_t stop,
size_t ttype);
/// Collect all tokens on specified channel to the right of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL or
/// EOF. If channel is -1, find any non default channel token.
virtual std::vector<Token*> getHiddenTokensToRight(size_t tokenIndex,
ssize_t channel);
/// <summary>
/// Collect all hidden tokens (any off-default channel) to the right of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL
/// or EOF.
/// </summary>
virtual std::vector<Token*> getHiddenTokensToRight(size_t tokenIndex);
/// <summary>
/// Collect all tokens on specified channel to the left of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
/// If channel is -1, find any non default channel token.
/// </summary>
virtual std::vector<Token*> getHiddenTokensToLeft(size_t tokenIndex,
ssize_t channel);
/// <summary>
/// Collect all hidden tokens (any off-default channel) to the left of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
/// </summary>
virtual std::vector<Token*> getHiddenTokensToLeft(size_t tokenIndex);
virtual std::string getSourceName() const override;
virtual std::string getText() override;
virtual std::string getText(const misc::Interval& interval) override;
virtual std::string getText(RuleContext* ctx) override;
virtual std::string getText(Token* start, Token* stop) override;
/// Get all tokens from lexer until EOF.
virtual void fill();
protected:
/**
* The {@link TokenSource} from which tokens for this stream are fetched.
*/
TokenSource* _tokenSource;
/**
* A collection of all tokens fetched from the token source. The list is
* considered a complete view of the input once {@link #fetchedEOF} is set
* to {@code true}.
*/
std::vector<std::unique_ptr<Token>> _tokens;
/**
* The index into {@link #tokens} of the current token (next token to
* {@link #consume}). {@link #tokens}{@code [}{@link #p}{@code ]} should be
* {@link #LT LT(1)}.
*
* <p>This field is set to -1 when the stream is first constructed or when
* {@link #setTokenSource} is called, indicating that the first token has
* not yet been fetched from the token source. For additional information,
* see the documentation of {@link IntStream} for a description of
* Initializing Methods.</p>
*/
// ml: since -1 requires to make this member signed for just this single
// aspect we use a member _needSetup instead.
// Use bool isInitialized() to find out if this stream has started
// reading.
size_t _p;
/**
* Indicates whether the {@link Token#EOF} token has been fetched from
* {@link #tokenSource} and added to {@link #tokens}. This field improves
* performance for the following cases:
*
* <ul>
* <li>{@link #consume}: The lookahead check in {@link #consume} to prevent
* consuming the EOF symbol is optimized by checking the values of
* {@link #fetchedEOF} and {@link #p} instead of calling {@link #LA}.</li>
* <li>{@link #fetch}: The check to prevent adding multiple EOF symbols into
* {@link #tokens} is trivial with this field.</li>
* <ul>
*/
bool _fetchedEOF;
/// <summary>
/// Make sure index {@code i} in tokens has a token.
/// </summary>
/// <returns> {@code true} if a token is located at index {@code i}, otherwise
/// {@code false}. </returns>
/// <seealso cref= #get(int i) </seealso>
virtual bool sync(size_t i);
/// <summary>
/// Add {@code n} elements to buffer.
/// </summary>
/// <returns> The actual number of elements added to the buffer. </returns>
virtual size_t fetch(size_t n);
virtual Token* LB(size_t k);
/// Allowed derived classes to modify the behavior of operations which change
/// the current stream position by adjusting the target token index of a seek
/// operation. The default implementation simply returns {@code i}. If an
/// exception is thrown in this method, the current stream index should not be
/// changed.
/// <p/>
/// For example, <seealso cref="CommonTokenStream"/> overrides this method to
/// ensure that the seek target is always an on-channel token.
///
/// <param name="i"> The target token index. </param>
/// <returns> The adjusted target token index. </returns>
virtual ssize_t adjustSeekIndex(size_t i);
void lazyInit();
virtual void setup();
/**
* Given a starting index, return the index of the next token on channel.
* Return {@code i} if {@code tokens[i]} is on channel. Return the index of
* the EOF token if there are no tokens on channel between {@code i} and
* EOF.
*/
virtual ssize_t nextTokenOnChannel(size_t i, size_t channel);
/**
* Given a starting index, return the index of the previous token on
* channel. Return {@code i} if {@code tokens[i]} is on channel. Return -1
* if there are no tokens on channel between {@code i} and 0.
*
* <p>
* If {@code i} specifies an index at or after the EOF token, the EOF token
* index is returned. This is due to the fact that the EOF token is treated
* as though it were on every channel.</p>
*/
virtual ssize_t previousTokenOnChannel(size_t i, size_t channel);
virtual std::vector<Token*> filterForChannel(size_t from, size_t to,
ssize_t channel);
bool isInitialized() const;
private:
bool _needSetup;
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,10 +0,0 @@
/* 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.
*/
#include "CharStream.h"
using namespace antlr4;
CharStream::~CharStream() {}

View File

@ -1,38 +0,0 @@
/* 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.
*/
#pragma once
#include "IntStream.h"
#include "misc/Interval.h"
namespace antlr4 {
/// A source of characters for an ANTLR lexer.
class ANTLR4CPP_PUBLIC CharStream : public IntStream {
public:
virtual ~CharStream();
/// This method returns the text for a range of characters within this input
/// stream. This method is guaranteed to not throw an exception if the
/// specified interval lies entirely within a marked range. For more
/// information about marked ranges, see IntStream::mark.
///
/// <param name="interval"> an interval within the stream </param>
/// <returns> the text of the specified interval
/// </returns>
/// <exception cref="NullPointerException"> if {@code interval} is {@code
/// null} </exception> <exception cref="IllegalArgumentException"> if {@code
/// interval.a < 0}, or if
/// {@code interval.b < interval.a - 1}, or if {@code interval.b} lies at or
/// past the end of the stream </exception>
/// <exception cref="UnsupportedOperationException"> if the stream does not
/// support getting the text of the specified interval </exception>
virtual std::string getText(const misc::Interval& interval) = 0;
virtual std::string toString() const = 0;
};
} // namespace antlr4

View File

@ -1,170 +0,0 @@
/* 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.
*/
#include "CharStream.h"
#include "Recognizer.h"
#include "TokenSource.h"
#include "Vocabulary.h"
#include "misc/Interval.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "CommonToken.h"
using namespace antlr4;
using namespace antlr4::misc;
using namespace antlrcpp;
const std::pair<TokenSource*, CharStream*> CommonToken::EMPTY_SOURCE(nullptr,
nullptr);
CommonToken::CommonToken(size_t type) {
InitializeInstanceFields();
_type = type;
}
CommonToken::CommonToken(std::pair<TokenSource*, CharStream*> source,
size_t type, size_t channel, size_t start,
size_t stop) {
InitializeInstanceFields();
_source = source;
_type = type;
_channel = channel;
_start = start;
_stop = stop;
if (_source.first != nullptr) {
_line = static_cast<int>(source.first->getLine());
_charPositionInLine = source.first->getCharPositionInLine();
}
}
CommonToken::CommonToken(size_t type, const std::string& text) {
InitializeInstanceFields();
_type = type;
_channel = DEFAULT_CHANNEL;
_text = text;
_source = EMPTY_SOURCE;
}
CommonToken::CommonToken(Token* oldToken) {
InitializeInstanceFields();
_type = oldToken->getType();
_line = oldToken->getLine();
_index = oldToken->getTokenIndex();
_charPositionInLine = oldToken->getCharPositionInLine();
_channel = oldToken->getChannel();
_start = oldToken->getStartIndex();
_stop = oldToken->getStopIndex();
if (is<CommonToken*>(oldToken)) {
_text = (static_cast<CommonToken*>(oldToken))->_text;
_source = (static_cast<CommonToken*>(oldToken))->_source;
} else {
_text = oldToken->getText();
_source = {oldToken->getTokenSource(), oldToken->getInputStream()};
}
}
size_t CommonToken::getType() const { return _type; }
void CommonToken::setLine(size_t line) { _line = line; }
std::string CommonToken::getText() const {
if (!_text.empty()) {
return _text;
}
CharStream* input = getInputStream();
if (input == nullptr) {
return "";
}
size_t n = input->size();
if (_start < n && _stop < n) {
return input->getText(misc::Interval(_start, _stop));
} else {
return "<EOF>";
}
}
void CommonToken::setText(const std::string& text) { _text = text; }
size_t CommonToken::getLine() const { return _line; }
size_t CommonToken::getCharPositionInLine() const {
return _charPositionInLine;
}
void CommonToken::setCharPositionInLine(size_t charPositionInLine) {
_charPositionInLine = charPositionInLine;
}
size_t CommonToken::getChannel() const { return _channel; }
void CommonToken::setChannel(size_t channel) { _channel = channel; }
void CommonToken::setType(size_t type) { _type = type; }
size_t CommonToken::getStartIndex() const { return _start; }
void CommonToken::setStartIndex(size_t start) { _start = start; }
size_t CommonToken::getStopIndex() const { return _stop; }
void CommonToken::setStopIndex(size_t stop) { _stop = stop; }
size_t CommonToken::getTokenIndex() const { return _index; }
void CommonToken::setTokenIndex(size_t index) { _index = index; }
antlr4::TokenSource* CommonToken::getTokenSource() const {
return _source.first;
}
antlr4::CharStream* CommonToken::getInputStream() const {
return _source.second;
}
std::string CommonToken::toString() const { return toString(nullptr); }
std::string CommonToken::toString(Recognizer* r) const {
std::stringstream ss;
std::string channelStr;
if (_channel > 0) {
channelStr = ",channel=" + std::to_string(_channel);
}
std::string txt = getText();
if (!txt.empty()) {
antlrcpp::replaceAll(txt, "\n", "\\n");
antlrcpp::replaceAll(txt, "\r", "\\r");
antlrcpp::replaceAll(txt, "\t", "\\t");
} else {
txt = "<no text>";
}
std::string typeString = std::to_string(symbolToNumeric(_type));
if (r != nullptr) typeString = r->getVocabulary().getDisplayName(_type);
ss << "[@" << symbolToNumeric(getTokenIndex()) << ","
<< symbolToNumeric(_start) << ":" << symbolToNumeric(_stop) << "='" << txt
<< "',<" << typeString << ">" << channelStr << "," << _line << ":"
<< getCharPositionInLine() << "]";
return ss.str();
}
void CommonToken::InitializeInstanceFields() {
_type = 0;
_line = 0;
_charPositionInLine = INVALID_INDEX;
_channel = DEFAULT_CHANNEL;
_index = INVALID_INDEX;
_start = 0;
_stop = 0;
_source = EMPTY_SOURCE;
}

View File

@ -1,162 +0,0 @@
/* 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.
*/
#pragma once
#include "WritableToken.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC CommonToken : public WritableToken {
protected:
/**
* An empty {@link Pair} which is used as the default value of
* {@link #source} for tokens that do not have a source.
*/
static const std::pair<TokenSource*, CharStream*> EMPTY_SOURCE;
/**
* This is the backing field for {@link #getType} and {@link #setType}.
*/
size_t _type;
/**
* This is the backing field for {@link #getLine} and {@link #setLine}.
*/
size_t _line;
/**
* This is the backing field for {@link #getCharPositionInLine} and
* {@link #setCharPositionInLine}.
*/
size_t _charPositionInLine; // set to invalid position
/**
* This is the backing field for {@link #getChannel} and
* {@link #setChannel}.
*/
size_t _channel;
/**
* This is the backing field for {@link #getTokenSource} and
* {@link #getInputStream}.
*
* <p>
* These properties share a field to reduce the memory footprint of
* {@link CommonToken}. Tokens created by a {@link CommonTokenFactory} from
* the same source and input stream share a reference to the same
* {@link Pair} containing these values.</p>
*/
std::pair<TokenSource*, CharStream*> _source; // ml: pure references, usually
// from statically allocated
// classes.
/**
* This is the backing field for {@link #getText} when the token text is
* explicitly set in the constructor or via {@link #setText}.
*
* @see #getText()
*/
std::string _text;
/**
* This is the backing field for {@link #getTokenIndex} and
* {@link #setTokenIndex}.
*/
size_t _index;
/**
* This is the backing field for {@link #getStartIndex} and
* {@link #setStartIndex}.
*/
size_t _start;
/**
* This is the backing field for {@link #getStopIndex} and
* {@link #setStopIndex}.
*/
size_t _stop;
public:
/**
* Constructs a new {@link CommonToken} with the specified token type.
*
* @param type The token type.
*/
CommonToken(size_t type);
CommonToken(std::pair<TokenSource*, CharStream*> source, size_t type,
size_t channel, size_t start, size_t stop);
/**
* Constructs a new {@link CommonToken} with the specified token type and
* text.
*
* @param type The token type.
* @param text The text of the token.
*/
CommonToken(size_t type, const std::string& text);
/**
* Constructs a new {@link CommonToken} as a copy of another {@link Token}.
*
* <p>
* If {@code oldToken} is also a {@link CommonToken} instance, the newly
* constructed token will share a reference to the {@link #text} field and
* the {@link Pair} stored in {@link #source}. Otherwise, {@link #text} will
* be assigned the result of calling {@link #getText}, and {@link #source}
* will be constructed from the result of {@link Token#getTokenSource} and
* {@link Token#getInputStream}.</p>
*
* @param oldToken The token to copy.
*/
CommonToken(Token* oldToken);
virtual size_t getType() const override;
/**
* Explicitly set the text for this token. If {code text} is not
* {@code null}, then {@link #getText} will return this value rather than
* extracting the text from the input.
*
* @param text The explicit text of the token, or {@code null} if the text
* should be obtained from the input along with the start and stop indexes
* of the token.
*/
virtual void setText(const std::string& text) override;
virtual std::string getText() const override;
virtual void setLine(size_t line) override;
virtual size_t getLine() const override;
virtual size_t getCharPositionInLine() const override;
virtual void setCharPositionInLine(size_t charPositionInLine) override;
virtual size_t getChannel() const override;
virtual void setChannel(size_t channel) override;
virtual void setType(size_t type) override;
virtual size_t getStartIndex() const override;
virtual void setStartIndex(size_t start);
virtual size_t getStopIndex() const override;
virtual void setStopIndex(size_t stop);
virtual size_t getTokenIndex() const override;
virtual void setTokenIndex(size_t index) override;
virtual TokenSource* getTokenSource() const override;
virtual CharStream* getInputStream() const override;
virtual std::string toString() const override;
virtual std::string toString(Recognizer* r) const;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,41 +0,0 @@
/* 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.
*/
#include "CharStream.h"
#include "CommonToken.h"
#include "misc/Interval.h"
#include "CommonTokenFactory.h"
using namespace antlr4;
const Ref<TokenFactory<CommonToken>> CommonTokenFactory::DEFAULT =
std::make_shared<CommonTokenFactory>();
CommonTokenFactory::CommonTokenFactory(bool copyText_) : copyText(copyText_) {}
CommonTokenFactory::CommonTokenFactory() : CommonTokenFactory(false) {}
std::unique_ptr<CommonToken> CommonTokenFactory::create(
std::pair<TokenSource*, CharStream*> source, size_t type,
const std::string& text, size_t channel, size_t start, size_t stop,
size_t line, size_t charPositionInLine) {
std::unique_ptr<CommonToken> t(
new CommonToken(source, type, channel, start, stop));
t->setLine(line);
t->setCharPositionInLine(charPositionInLine);
if (text != "") {
t->setText(text);
} else if (copyText && source.second != nullptr) {
t->setText(source.second->getText(misc::Interval(start, stop)));
}
return t;
}
std::unique_ptr<CommonToken> CommonTokenFactory::create(
size_t type, const std::string& text) {
return std::unique_ptr<CommonToken>(new CommonToken(type, text));
}

View File

@ -1,77 +0,0 @@
/* 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.
*/
#pragma once
#include "TokenFactory.h"
namespace antlr4 {
/**
* This default implementation of {@link TokenFactory} creates
* {@link CommonToken} objects.
*/
class ANTLR4CPP_PUBLIC CommonTokenFactory : public TokenFactory<CommonToken> {
public:
/**
* The default {@link CommonTokenFactory} instance.
*
* <p>
* This token factory does not explicitly copy token text when constructing
* tokens.</p>
*/
static const Ref<TokenFactory<CommonToken>> DEFAULT;
protected:
/**
* Indicates whether {@link CommonToken#setText} should be called after
* constructing tokens to explicitly set the text. This is useful for cases
* where the input stream might not be able to provide arbitrary substrings
* of text from the input after the lexer creates a token (e.g. the
* implementation of {@link CharStream#getText} in
* {@link UnbufferedCharStream} throws an
* {@link UnsupportedOperationException}). Explicitly setting the token text
* allows {@link Token#getText} to be called at any time regardless of the
* input stream implementation.
*
* <p>
* The default value is {@code false} to avoid the performance and memory
* overhead of copying text for every token unless explicitly requested.</p>
*/
const bool copyText;
public:
/**
* Constructs a {@link CommonTokenFactory} with the specified value for
* {@link #copyText}.
*
* <p>
* When {@code copyText} is {@code false}, the {@link #DEFAULT} instance
* should be used instead of constructing a new instance.</p>
*
* @param copyText The value for {@link #copyText}.
*/
CommonTokenFactory(bool copyText);
/**
* Constructs a {@link CommonTokenFactory} with {@link #copyText} set to
* {@code false}.
*
* <p>
* The {@link #DEFAULT} instance should be used instead of calling this
* directly.</p>
*/
CommonTokenFactory();
virtual std::unique_ptr<CommonToken> create(
std::pair<TokenSource*, CharStream*> source, size_t type,
const std::string& text, size_t channel, size_t start, size_t stop,
size_t line, size_t charPositionInLine) override;
virtual std::unique_ptr<CommonToken> create(size_t type,
const std::string& text) override;
};
} // namespace antlr4

View File

@ -1,77 +0,0 @@
/* 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.
*/
#include "Token.h"
#include "CommonTokenStream.h"
using namespace antlr4;
CommonTokenStream::CommonTokenStream(TokenSource* tokenSource)
: CommonTokenStream(tokenSource, Token::DEFAULT_CHANNEL) {}
CommonTokenStream::CommonTokenStream(TokenSource* tokenSource, size_t channel_)
: BufferedTokenStream(tokenSource), channel(channel_) {}
ssize_t CommonTokenStream::adjustSeekIndex(size_t i) {
return nextTokenOnChannel(i, channel);
}
Token* CommonTokenStream::LB(size_t k) {
if (k == 0 || k > _p) {
return nullptr;
}
ssize_t i = static_cast<ssize_t>(_p);
size_t n = 1;
// find k good tokens looking backwards
while (n <= k) {
// skip off-channel tokens
i = previousTokenOnChannel(i - 1, channel);
n++;
}
if (i < 0) {
return nullptr;
}
return _tokens[i].get();
}
Token* CommonTokenStream::LT(ssize_t k) {
lazyInit();
if (k == 0) {
return nullptr;
}
if (k < 0) {
return LB(static_cast<size_t>(-k));
}
size_t i = _p;
ssize_t 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
if (sync(i + 1)) {
i = nextTokenOnChannel(i + 1, channel);
}
n++;
}
return _tokens[i].get();
}
int CommonTokenStream::getNumberOfOnChannelTokens() {
int n = 0;
fill();
for (size_t i = 0; i < _tokens.size(); i++) {
Token* t = _tokens[i].get();
if (t->getChannel() == channel) {
n++;
}
if (t->getType() == Token::EOF) {
break;
}
}
return n;
}

View File

@ -1,78 +0,0 @@
/* 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.
*/
#pragma once
#include "BufferedTokenStream.h"
namespace antlr4 {
/**
* This class extends {@link BufferedTokenStream} with functionality to filter
* token streams to tokens on a particular channel (tokens where
* {@link Token#getChannel} returns a particular value).
*
* <p>
* This token stream provides access to all tokens by index or when calling
* methods like {@link #getText}. The channel filtering is only used for code
* accessing tokens via the lookahead methods {@link #LA}, {@link #LT}, and
* {@link #LB}.</p>
*
* <p>
* By default, tokens are placed on the default channel
* ({@link Token#DEFAULT_CHANNEL}), but may be reassigned by using the
* {@code ->channel(HIDDEN)} lexer command, or by using an embedded action to
* call {@link Lexer#setChannel}.
* </p>
*
* <p>
* Note: lexer rules which use the {@code ->skip} lexer command or call
* {@link Lexer#skip} do not produce tokens at all, so input text matched by
* such a rule will not be available as part of the token stream, regardless of
* channel.</p>
*/
class ANTLR4CPP_PUBLIC CommonTokenStream : public BufferedTokenStream {
public:
/**
* Constructs a new {@link CommonTokenStream} using the specified token
* source and the default token channel ({@link Token#DEFAULT_CHANNEL}).
*
* @param tokenSource The token source.
*/
CommonTokenStream(TokenSource* tokenSource);
/**
* Constructs a new {@link CommonTokenStream} using the specified token
* source and filtering tokens to the specified channel. Only tokens whose
* {@link Token#getChannel} matches {@code channel} or have the
* {@link Token#getType} equal to {@link Token#EOF} will be returned by the
* token stream lookahead methods.
*
* @param tokenSource The token source.
* @param channel The channel to use for filtering tokens.
*/
CommonTokenStream(TokenSource* tokenSource, size_t channel);
virtual Token* LT(ssize_t k) override;
/// Count EOF just once.
virtual int getNumberOfOnChannelTokens();
protected:
/**
* Specifies the channel to use for filtering tokens.
*
* <p>
* The default value is {@link Token#DEFAULT_CHANNEL}, which matches the
* default channel assigned to tokens created by the lexer.</p>
*/
size_t channel;
virtual ssize_t adjustSeekIndex(size_t i) override;
virtual Token* LB(size_t k) override;
};
} // namespace antlr4

View File

@ -1,19 +0,0 @@
/* 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.
*/
#include "ConsoleErrorListener.h"
using namespace antlr4;
ConsoleErrorListener ConsoleErrorListener::INSTANCE;
void ConsoleErrorListener::syntaxError(Recognizer* /*recognizer*/,
Token* /*offendingSymbol*/, size_t line,
size_t charPositionInLine,
const std::string& msg,
std::exception_ptr /*e*/) {
std::cerr << "line " << line << ":" << charPositionInLine << " " << msg
<< std::endl;
}

View File

@ -1,37 +0,0 @@
/* 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.
*/
#pragma once
#include "BaseErrorListener.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC ConsoleErrorListener : public BaseErrorListener {
public:
/**
* Provides a default instance of {@link ConsoleErrorListener}.
*/
static ConsoleErrorListener INSTANCE;
/**
* {@inheritDoc}
*
* <p>
* This implementation prints messages to {@link System#err} containing the
* values of {@code line}, {@code charPositionInLine}, and {@code msg} using
* the following format.</p>
*
* <pre>
* line <em>line</em>:<em>charPositionInLine</em> <em>msg</em>
* </pre>
*/
virtual void syntaxError(Recognizer* recognizer, Token* offendingSymbol,
size_t line, size_t charPositionInLine,
const std::string& msg,
std::exception_ptr e) override;
};
} // namespace antlr4

View File

@ -1,355 +0,0 @@
/* 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.
*/
#include "CommonToken.h"
#include "FailedPredicateException.h"
#include "InputMismatchException.h"
#include "NoViableAltException.h"
#include "Parser.h"
#include "ParserRuleContext.h"
#include "Vocabulary.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "atn/ParserATNSimulator.h"
#include "atn/RuleTransition.h"
#include "misc/IntervalSet.h"
#include "support/StringUtils.h"
#include "DefaultErrorStrategy.h"
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;
DefaultErrorStrategy::DefaultErrorStrategy() { InitializeInstanceFields(); }
DefaultErrorStrategy::~DefaultErrorStrategy() {}
void DefaultErrorStrategy::reset(Parser* recognizer) {
_errorSymbols.clear();
endErrorCondition(recognizer);
}
void DefaultErrorStrategy::beginErrorCondition(Parser* /*recognizer*/) {
errorRecoveryMode = true;
}
bool DefaultErrorStrategy::inErrorRecoveryMode(Parser* /*recognizer*/) {
return errorRecoveryMode;
}
void DefaultErrorStrategy::endErrorCondition(Parser* /*recognizer*/) {
errorRecoveryMode = false;
lastErrorIndex = -1;
}
void DefaultErrorStrategy::reportMatch(Parser* recognizer) {
endErrorCondition(recognizer);
}
void DefaultErrorStrategy::reportError(Parser* recognizer,
const RecognitionException& e) {
// If we've already reported an error and have not matched a token
// yet successfully, don't report any errors.
if (inErrorRecoveryMode(recognizer)) {
return; // don't report spurious errors
}
beginErrorCondition(recognizer);
if (is<const NoViableAltException*>(&e)) {
reportNoViableAlternative(recognizer,
static_cast<const NoViableAltException&>(e));
} else if (is<const InputMismatchException*>(&e)) {
reportInputMismatch(recognizer,
static_cast<const InputMismatchException&>(e));
} else if (is<const FailedPredicateException*>(&e)) {
reportFailedPredicate(recognizer,
static_cast<const FailedPredicateException&>(e));
} else if (is<const RecognitionException*>(&e)) {
recognizer->notifyErrorListeners(e.getOffendingToken(), e.what(),
std::current_exception());
}
}
void DefaultErrorStrategy::recover(Parser* recognizer,
std::exception_ptr /*e*/) {
if (lastErrorIndex ==
static_cast<int>(recognizer->getInputStream()->index()) &&
lastErrorStates.contains(recognizer->getState())) {
// uh oh, another error at same token index and previously-visited
// state in ATN; must be a case where LT(1) is in the recovery
// token set so nothing got consumed. Consume a single token
// at least to prevent an infinite loop; this is a failsafe.
recognizer->consume();
}
lastErrorIndex = static_cast<int>(recognizer->getInputStream()->index());
lastErrorStates.add(recognizer->getState());
misc::IntervalSet followSet = getErrorRecoverySet(recognizer);
consumeUntil(recognizer, followSet);
}
void DefaultErrorStrategy::sync(Parser* recognizer) {
atn::ATNState* s = recognizer->getInterpreter<atn::ATNSimulator>()
->atn.states[recognizer->getState()];
// If already recovering, don't try to sync
if (inErrorRecoveryMode(recognizer)) {
return;
}
TokenStream* tokens = recognizer->getTokenStream();
size_t la = tokens->LA(1);
// try cheaper subset first; might get lucky. seems to shave a wee bit off
auto nextTokens = recognizer->getATN().nextTokens(s);
if (nextTokens.contains(Token::EPSILON) || nextTokens.contains(la)) {
return;
}
switch (s->getStateType()) {
case atn::ATNState::BLOCK_START:
case atn::ATNState::STAR_BLOCK_START:
case atn::ATNState::PLUS_BLOCK_START:
case atn::ATNState::STAR_LOOP_ENTRY:
// report error and recover if possible
if (singleTokenDeletion(recognizer) != nullptr) {
return;
}
throw InputMismatchException(recognizer);
case atn::ATNState::PLUS_LOOP_BACK:
case atn::ATNState::STAR_LOOP_BACK: {
reportUnwantedToken(recognizer);
misc::IntervalSet expecting = recognizer->getExpectedTokens();
misc::IntervalSet whatFollowsLoopIterationOrRule =
expecting.Or(getErrorRecoverySet(recognizer));
consumeUntil(recognizer, whatFollowsLoopIterationOrRule);
} break;
default:
// do nothing if we can't identify the exact kind of ATN state
break;
}
}
void DefaultErrorStrategy::reportNoViableAlternative(
Parser* recognizer, const NoViableAltException& e) {
TokenStream* tokens = recognizer->getTokenStream();
std::string input;
if (tokens != nullptr) {
if (e.getStartToken()->getType() == Token::EOF) {
input = "<EOF>";
} else {
input = tokens->getText(e.getStartToken(), e.getOffendingToken());
}
} else {
input = "<unknown input>";
}
std::string msg = "no viable alternative at input " + escapeWSAndQuote(input);
recognizer->notifyErrorListeners(e.getOffendingToken(), msg,
std::make_exception_ptr(e));
}
void DefaultErrorStrategy::reportInputMismatch(
Parser* recognizer, const InputMismatchException& e) {
std::string msg = "mismatched input " +
getTokenErrorDisplay(e.getOffendingToken()) +
" expecting " +
e.getExpectedTokens().toString(recognizer->getVocabulary());
recognizer->notifyErrorListeners(e.getOffendingToken(), msg,
std::make_exception_ptr(e));
}
void DefaultErrorStrategy::reportFailedPredicate(
Parser* recognizer, const FailedPredicateException& e) {
const std::string& ruleName =
recognizer->getRuleNames()[recognizer->getContext()->getRuleIndex()];
std::string msg = "rule " + ruleName + " " + e.what();
recognizer->notifyErrorListeners(e.getOffendingToken(), msg,
std::make_exception_ptr(e));
}
void DefaultErrorStrategy::reportUnwantedToken(Parser* recognizer) {
if (inErrorRecoveryMode(recognizer)) {
return;
}
beginErrorCondition(recognizer);
Token* t = recognizer->getCurrentToken();
std::string tokenName = getTokenErrorDisplay(t);
misc::IntervalSet expecting = getExpectedTokens(recognizer);
std::string msg = "extraneous input " + tokenName + " expecting " +
expecting.toString(recognizer->getVocabulary());
recognizer->notifyErrorListeners(t, msg, nullptr);
}
void DefaultErrorStrategy::reportMissingToken(Parser* recognizer) {
if (inErrorRecoveryMode(recognizer)) {
return;
}
beginErrorCondition(recognizer);
Token* t = recognizer->getCurrentToken();
misc::IntervalSet expecting = getExpectedTokens(recognizer);
std::string expectedText = expecting.toString(recognizer->getVocabulary());
std::string msg =
"missing " + expectedText + " at " + getTokenErrorDisplay(t);
recognizer->notifyErrorListeners(t, msg, nullptr);
}
Token* DefaultErrorStrategy::recoverInline(Parser* recognizer) {
// Single token deletion.
Token* matchedSymbol = singleTokenDeletion(recognizer);
if (matchedSymbol) {
// We have deleted the extra token.
// Now, move past ttype token as if all were ok.
recognizer->consume();
return matchedSymbol;
}
// Single token insertion.
if (singleTokenInsertion(recognizer)) {
return getMissingSymbol(recognizer);
}
// Even that didn't work; must throw the exception.
throw InputMismatchException(recognizer);
}
bool DefaultErrorStrategy::singleTokenInsertion(Parser* recognizer) {
ssize_t currentSymbolType = recognizer->getInputStream()->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
atn::ATNState* currentState = recognizer->getInterpreter<atn::ATNSimulator>()
->atn.states[recognizer->getState()];
atn::ATNState* next = currentState->transitions[0]->target;
const atn::ATN& atn = recognizer->getInterpreter<atn::ATNSimulator>()->atn;
misc::IntervalSet expectingAtLL2 =
atn.nextTokens(next, recognizer->getContext());
if (expectingAtLL2.contains(currentSymbolType)) {
reportMissingToken(recognizer);
return true;
}
return false;
}
Token* DefaultErrorStrategy::singleTokenDeletion(Parser* recognizer) {
size_t nextTokenType = recognizer->getInputStream()->LA(2);
misc::IntervalSet expecting = getExpectedTokens(recognizer);
if (expecting.contains(nextTokenType)) {
reportUnwantedToken(recognizer);
recognizer
->consume(); // simply delete extra token
// we want to return the token we're actually matching
Token* matchedSymbol = recognizer->getCurrentToken();
reportMatch(recognizer); // we know current token is correct
return matchedSymbol;
}
return nullptr;
}
Token* DefaultErrorStrategy::getMissingSymbol(Parser* recognizer) {
Token* currentSymbol = recognizer->getCurrentToken();
misc::IntervalSet expecting = getExpectedTokens(recognizer);
size_t expectedTokenType = expecting.getMinElement(); // get any element
std::string tokenText;
if (expectedTokenType == Token::EOF) {
tokenText = "<missing EOF>";
} else {
tokenText = "<missing " +
recognizer->getVocabulary().getDisplayName(expectedTokenType) +
">";
}
Token* current = currentSymbol;
Token* lookback = recognizer->getTokenStream()->LT(-1);
if (current->getType() == Token::EOF && lookback != nullptr) {
current = lookback;
}
_errorSymbols.push_back(recognizer->getTokenFactory()->create(
{current->getTokenSource(), current->getTokenSource()->getInputStream()},
expectedTokenType, tokenText, Token::DEFAULT_CHANNEL, INVALID_INDEX,
INVALID_INDEX, current->getLine(), current->getCharPositionInLine()));
return _errorSymbols.back().get();
}
misc::IntervalSet DefaultErrorStrategy::getExpectedTokens(Parser* recognizer) {
return recognizer->getExpectedTokens();
}
std::string DefaultErrorStrategy::getTokenErrorDisplay(Token* t) {
if (t == nullptr) {
return "<no Token>";
}
std::string s = getSymbolText(t);
if (s == "") {
if (getSymbolType(t) == Token::EOF) {
s = "<EOF>";
} else {
s = "<" + std::to_string(getSymbolType(t)) + ">";
}
}
return escapeWSAndQuote(s);
}
std::string DefaultErrorStrategy::getSymbolText(Token* symbol) {
return symbol->getText();
}
size_t DefaultErrorStrategy::getSymbolType(Token* symbol) {
return symbol->getType();
}
std::string DefaultErrorStrategy::escapeWSAndQuote(const std::string& s) const {
std::string result = s;
antlrcpp::replaceAll(result, "\n", "\\n");
antlrcpp::replaceAll(result, "\r", "\\r");
antlrcpp::replaceAll(result, "\t", "\\t");
return "'" + result + "'";
}
misc::IntervalSet DefaultErrorStrategy::getErrorRecoverySet(
Parser* recognizer) {
const atn::ATN& atn = recognizer->getInterpreter<atn::ATNSimulator>()->atn;
RuleContext* ctx = recognizer->getContext();
misc::IntervalSet recoverSet;
while (ctx->invokingState != ATNState::INVALID_STATE_NUMBER) {
// compute what follows who invoked us
atn::ATNState* invokingState = atn.states[ctx->invokingState];
atn::RuleTransition* rt =
dynamic_cast<atn::RuleTransition*>(invokingState->transitions[0]);
misc::IntervalSet follow = atn.nextTokens(rt->followState);
recoverSet.addAll(follow);
if (ctx->parent == nullptr) break;
ctx = static_cast<RuleContext*>(ctx->parent);
}
recoverSet.remove(Token::EPSILON);
return recoverSet;
}
void DefaultErrorStrategy::consumeUntil(Parser* recognizer,
const misc::IntervalSet& set) {
size_t ttype = recognizer->getInputStream()->LA(1);
while (ttype != Token::EOF && !set.contains(ttype)) {
recognizer->consume();
ttype = recognizer->getInputStream()->LA(1);
}
}
void DefaultErrorStrategy::InitializeInstanceFields() {
errorRecoveryMode = false;
lastErrorIndex = -1;
}

View File

@ -1,478 +0,0 @@
/* 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.
*/
#pragma once
#include "ANTLRErrorStrategy.h"
#include "misc/IntervalSet.h"
namespace antlr4 {
/**
* This is the default implementation of {@link ANTLRErrorStrategy} used for
* error reporting and recovery in ANTLR parsers.
*/
class ANTLR4CPP_PUBLIC DefaultErrorStrategy : public ANTLRErrorStrategy {
public:
DefaultErrorStrategy();
DefaultErrorStrategy(DefaultErrorStrategy const& other) = delete;
virtual ~DefaultErrorStrategy();
DefaultErrorStrategy& operator=(DefaultErrorStrategy const& other) = delete;
protected:
/**
* Indicates whether the error strategy is currently "recovering from an
* error". This is used to suppress reporting multiple error messages while
* attempting to recover from a detected syntax error.
*
* @see #inErrorRecoveryMode
*/
bool errorRecoveryMode;
/** The index into the input stream where the last error occurred.
* This is used to prevent infinite loops where an error is found
* but no token is consumed during recovery...another error is found,
* ad nauseum. This is a failsafe mechanism to guarantee that at least
* one token/tree node is consumed for two errors.
*/
int lastErrorIndex;
misc::IntervalSet lastErrorStates;
/// <summary>
/// {@inheritDoc}
/// <p/>
/// The default implementation simply calls <seealso
/// cref="#endErrorCondition"/> to ensure that the handler is not in error
/// recovery mode.
/// </summary>
public:
virtual void reset(Parser* recognizer) override;
/// <summary>
/// This method is called to enter error recovery mode when a recognition
/// exception is reported.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
protected:
virtual void beginErrorCondition(Parser* recognizer);
/// <summary>
/// {@inheritDoc}
/// </summary>
public:
virtual bool inErrorRecoveryMode(Parser* recognizer) override;
/// <summary>
/// This method is called to leave error recovery mode after recovering from
/// a recognition exception.
/// </summary>
/// <param name="recognizer"> </param>
protected:
virtual void endErrorCondition(Parser* recognizer);
/// <summary>
/// {@inheritDoc}
/// <p/>
/// The default implementation simply calls <seealso
/// cref="#endErrorCondition"/>.
/// </summary>
public:
virtual void reportMatch(Parser* recognizer) override;
/// {@inheritDoc}
/// <p/>
/// The default implementation returns immediately if the handler is already
/// in error recovery mode. Otherwise, it calls <seealso
/// cref="#beginErrorCondition"/> and dispatches the reporting task based on
/// the runtime type of {@code e} according to the following table.
///
/// <ul>
/// <li><seealso cref="NoViableAltException"/>: Dispatches the call to
/// <seealso cref="#reportNoViableAlternative"/></li>
/// <li><seealso cref="InputMismatchException"/>: Dispatches the call to
/// <seealso cref="#reportInputMismatch"/></li>
/// <li><seealso cref="FailedPredicateException"/>: Dispatches the call to
/// <seealso cref="#reportFailedPredicate"/></li>
/// <li>All other types: calls <seealso cref="Parser#notifyErrorListeners"/>
/// to report the exception</li>
/// </ul>
virtual void reportError(Parser* recognizer,
const RecognitionException& e) override;
/// <summary>
/// {@inheritDoc}
/// <p/>
/// The default implementation resynchronizes the parser by consuming tokens
/// until we find one in the resynchronization set--loosely the set of tokens
/// that can follow the current rule.
/// </summary>
virtual void recover(Parser* recognizer, std::exception_ptr e) override;
/**
* The default implementation of {@link ANTLRErrorStrategy#sync} makes sure
* that the current lookahead symbol is consistent with what were expecting
* at this point in the ATN. You can call this anytime but ANTLR only
* generates code to check before subrules/loops and each iteration.
*
* <p>Implements Jim Idle's magic sync mechanism in closures and optional
* subrules. E.g.,</p>
*
* <pre>
* a : sync ( stuff sync )* ;
* sync : {consume to what can follow sync} ;
* </pre>
*
* At the start of a sub rule upon error, {@link #sync} performs single
* token deletion, if possible. If it can't do that, it bails on the current
* rule and uses the default error recovery, which consumes until the
* resynchronization set of the current rule.
*
* <p>If the sub rule is optional ({@code (...)?}, {@code (...)*}, or block
* with an empty alternative), then the expected set includes what follows
* the subrule.</p>
*
* <p>During loop iteration, it consumes until it sees a token that can start
* a sub rule or what follows loop. Yes, that is pretty aggressive. We opt to
* stay in the loop as long as possible.</p>
*
* <p><strong>ORIGINS</strong></p>
*
* <p>Previous versions of ANTLR did a poor job of their recovery within
* loops. A single mismatch token or missing token would force the parser to
* bail out of the entire rules surrounding the loop. So, for rule</p>
*
* <pre>
* classDef : 'class' ID '{' member* '}'
* </pre>
*
* input with an extra token between members would force the parser to
* consume until it found the next class definition rather than the next
* member definition of the current class.
*
* <p>This functionality cost a little bit of effort because the parser has to
* compare token set at the start of the loop and at each iteration. If for
* some reason speed is suffering for you, you can turn off this
* functionality by simply overriding this method as a blank { }.</p>
*/
virtual void sync(Parser* recognizer) override;
/// <summary>
/// This is called by <seealso cref="#reportError"/> when the exception is a
/// <seealso cref="NoViableAltException"/>.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception </param>
protected:
virtual void reportNoViableAlternative(Parser* recognizer,
const NoViableAltException& e);
/// <summary>
/// This is called by <seealso cref="#reportError"/> when the exception is an
/// <seealso cref="InputMismatchException"/>.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception </param>
virtual void reportInputMismatch(Parser* recognizer,
const InputMismatchException& e);
/// <summary>
/// This is called by <seealso cref="#reportError"/> when the exception is a
/// <seealso cref="FailedPredicateException"/>.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception </param>
virtual void reportFailedPredicate(Parser* recognizer,
const FailedPredicateException& e);
/**
* This method is called to report a syntax error which requires the removal
* of a token from the input stream. At the time this method is called, the
* erroneous symbol is current {@code LT(1)} symbol and has not yet been
* removed from the input stream. When this method returns,
* {@code recognizer} is in error recovery mode.
*
* <p>This method is called when {@link #singleTokenDeletion} identifies
* single-token deletion as a viable recovery strategy for a mismatched
* input error.</p>
*
* <p>The default implementation simply returns if the handler is already in
* error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
* enter error recovery mode, followed by calling
* {@link Parser#notifyErrorListeners}.</p>
*
* @param recognizer the parser instance
*/
virtual void reportUnwantedToken(Parser* recognizer);
/**
* This method is called to report a syntax error which requires the
* insertion of a missing token into the input stream. At the time this
* method is called, the missing token has not yet been inserted. When this
* method returns, {@code recognizer} is in error recovery mode.
*
* <p>This method is called when {@link #singleTokenInsertion} identifies
* single-token insertion as a viable recovery strategy for a mismatched
* input error.</p>
*
* <p>The default implementation simply returns if the handler is already in
* error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
* enter error recovery mode, followed by calling
* {@link Parser#notifyErrorListeners}.</p>
*
* @param recognizer the parser instance
*/
virtual void reportMissingToken(Parser* recognizer);
public:
/**
* {@inheritDoc}
*
* <p>The default implementation attempts to recover from the mismatched input
* by using single token insertion and deletion as described below. If the
* recovery attempt fails, this method throws an
* {@link InputMismatchException}.</p>
*
* <p><strong>EXTRA TOKEN</strong> (single token deletion)</p>
*
* <p>{@code LA(1)} is not what we are looking for. If {@code LA(2)} has the
* right token, however, then assume {@code LA(1)} is some extra spurious
* token and delete it. Then consume and return the next token (which was
* the {@code LA(2)} token) as the successful result of the match
* operation.</p>
*
* <p>This recovery strategy is implemented by {@link
* #singleTokenDeletion}.</p>
*
* <p><strong>MISSING TOKEN</strong> (single token insertion)</p>
*
* <p>If current token (at {@code LA(1)}) is consistent with what could come
* after the expected {@code LA(1)} token, then assume the token is missing
* and use the parser's {@link TokenFactory} to create it on the fly. The
* "insertion" is performed by returning the created token as the successful
* result of the match operation.</p>
*
* <p>This recovery strategy is implemented by {@link
* #singleTokenInsertion}.</p>
*
* <p><strong>EXAMPLE</strong></p>
*
* <p>For example, Input {@code i=(3;} is clearly missing the {@code ')'}.
* When the parser returns from the nested call to {@code expr}, it will have
* call chain:</p>
*
* <pre>
* stat &rarr; expr &rarr; atom
* </pre>
*
* and it will be trying to match the {@code ')'} at this point in the
* derivation:
*
* <pre>
* =&gt; ID '=' '(' INT ')' ('+' atom)* ';'
* ^
* </pre>
*
* The attempt to match {@code ')'} will fail when it sees {@code ';'} and
* call {@link #recoverInline}. To recover, it sees that {@code LA(1)==';'}
* is in the set of tokens that can follow the {@code ')'} token reference
* in rule {@code atom}. It can assume that you forgot the {@code ')'}.
*/
virtual Token* recoverInline(Parser* recognizer) override;
/// <summary>
/// This method implements the single-token insertion inline error recovery
/// strategy. It is called by <seealso cref="#recoverInline"/> if the
/// single-token deletion strategy fails to recover from the mismatched input.
/// If this method returns {@code true}, {@code recognizer} will be in error
/// recovery mode. <p/> This method determines whether or not single-token
/// insertion is viable by checking if the {@code LA(1)} input symbol could be
/// successfully matched if it were instead the {@code LA(2)} symbol. If this
/// method returns
/// {@code true}, the caller is responsible for creating and inserting a
/// token with the correct type to produce this behavior.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <returns> {@code true} if single-token insertion is a viable recovery
/// strategy for the current mismatched input, otherwise {@code false}
/// </returns>
protected:
virtual bool singleTokenInsertion(Parser* recognizer);
/// <summary>
/// This method implements the single-token deletion inline error recovery
/// strategy. It is called by <seealso cref="#recoverInline"/> to attempt to
/// recover from mismatched input. If this method returns null, the parser and
/// error handler state will not have changed. If this method returns
/// non-null,
/// {@code recognizer} will <em>not</em> be in error recovery mode since the
/// returned token was a successful match.
/// <p/>
/// If the single-token deletion is successful, this method calls
/// <seealso cref="#reportUnwantedToken"/> to report the error, followed by
/// <seealso cref="Parser#consume"/> to actually "delete" the extraneous
/// token. Then, before returning <seealso cref="#reportMatch"/> is called to
/// signal a successful match.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <returns> the successfully matched <seealso cref="Token"/> instance if
/// single-token deletion successfully recovers from the mismatched input,
/// otherwise
/// {@code null} </returns>
virtual Token* singleTokenDeletion(Parser* recognizer);
/// <summary>
/// Conjure up a missing token during error recovery.
///
/// The recognizer attempts to recover from single missing
/// symbols. But, actions might refer to that missing symbol.
/// For example, x=ID {f($x);}. The action clearly assumes
/// that there has been an identifier matched previously and that
/// $x points at that token. If that token is missing, but
/// the next token in the stream is what we want we assume that
/// this token is missing and we keep going. Because we
/// have to return some token to replace the missing token,
/// we have to conjure one up. This method gives the user control
/// over the tokens returned for missing tokens. Mostly,
/// you will want to create something special for identifier
/// tokens. For literals such as '{' and ',', the default
/// action in the parser or tree parser works. It simply creates
/// a CommonToken of the appropriate type. The text will be the token.
/// If you change what tokens must be created by the lexer,
/// override this method to create the appropriate tokens.
/// </summary>
virtual Token* getMissingSymbol(Parser* recognizer);
virtual misc::IntervalSet getExpectedTokens(Parser* recognizer);
/// <summary>
/// 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 class.
/// </summary>
virtual std::string getTokenErrorDisplay(Token* t);
virtual std::string getSymbolText(Token* symbol);
virtual size_t getSymbolType(Token* symbol);
virtual std::string escapeWSAndQuote(const std::string& s) const;
/* Compute the error recovery set for the current rule. During
* rule invocation, the parser pushes the set of tokens that can
* follow that rule reference on the stack; this amounts to
* computing FIRST of what follows the rule reference in the
* enclosing rule. See LinearApproximator.FIRST().
* This local follow set only includes tokens
* from within the rule; i.e., the FIRST computation done by
* ANTLR stops at the end of a rule.
*
* EXAMPLE
*
* When you find a "no viable alt exception", the input is not
* consistent with any of the alternatives for rule r. The best
* thing to do is to consume tokens until you see something that
* can legally follow a call to r *or* any rule that called r.
* You don't want the exact set of viable next tokens because the
* input might just be missing a token--you might consume the
* rest of the input looking for one of the missing tokens.
*
* Consider grammar:
*
* a : '[' b ']'
* | '(' b ')'
* ;
* b : c '^' INT ;
* c : ID
* | INT
* ;
*
* At each rule invocation, the set of tokens that could follow
* that rule is pushed on a stack. Here are the various
* context-sensitive follow sets:
*
* FOLLOW(b1_in_a) = FIRST(']') = ']'
* FOLLOW(b2_in_a) = FIRST(')') = ')'
* FOLLOW(c_in_b) = FIRST('^') = '^'
*
* Upon erroneous input "[]", the call chain is
*
* a -> b -> c
*
* and, hence, the follow context stack is:
*
* depth follow set start of rule execution
* 0 <EOF> a (from main())
* 1 ']' b
* 2 '^' c
*
* Notice that ')' is not included, because b would have to have
* been called from a different context in rule a for ')' to be
* included.
*
* For error recovery, we cannot consider FOLLOW(c)
* (context-sensitive or otherwise). We need the combined set of
* all context-sensitive FOLLOW sets--the set of all tokens that
* could follow any reference in the call chain. We need to
* resync to one of those tokens. Note that FOLLOW(c)='^' and if
* we resync'd to that token, we'd consume until EOF. We need to
* sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
* In this case, for input "[]", LA(1) is ']' and in the set, so we would
* not consume anything. After printing an error, rule c would
* return normally. Rule b would not find the required '^' though.
* At this point, it gets a mismatched token error and throws an
* exception (since LA(1) is not in the viable following token
* set). The rule exception handler tries to recover, but finds
* the same recovery set and doesn't consume anything. Rule b
* exits normally returning to rule a. Now it finds the ']' (and
* with the successful match exits errorRecovery mode).
*
* So, you can see that the parser walks up the call chain looking
* for the token that was a member of the recovery set.
*
* Errors are not generated in errorRecovery mode.
*
* ANTLR's error recovery mechanism is based upon original ideas:
*
* "Algorithms + Data Structures = Programs" by Niklaus Wirth
*
* and
*
* "A note on error recovery in recursive descent parsers":
* http://portal.acm.org/citation.cfm?id=947902.947905
*
* Later, Josef Grosch had some good ideas:
*
* "Efficient and Comfortable Error Recovery in Recursive Descent
* Parsers":
* ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
*
* Like Grosch I implement context-sensitive FOLLOW sets that are combined
* at run-time upon error to avoid overhead during parsing.
*/
virtual misc::IntervalSet getErrorRecoverySet(Parser* recognizer);
/// <summary>
/// Consume tokens until one matches the given token set. </summary>
virtual void consumeUntil(Parser* recognizer, const misc::IntervalSet& set);
private:
std::vector<std::unique_ptr<Token>>
_errorSymbols; // Temporarily created token.
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,101 +0,0 @@
/* 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.
*/
#include "Parser.h"
#include "atn/ATNConfig.h"
#include "atn/ATNConfigSet.h"
#include "atn/PredictionContext.h"
#include "dfa/DFA.h"
#include "misc/Interval.h"
#include "DiagnosticErrorListener.h"
using namespace antlr4;
DiagnosticErrorListener::DiagnosticErrorListener()
: DiagnosticErrorListener(true) {}
DiagnosticErrorListener::DiagnosticErrorListener(bool exactOnly_)
: exactOnly(exactOnly_) {}
void DiagnosticErrorListener::reportAmbiguity(Parser* recognizer,
const dfa::DFA& dfa,
size_t startIndex,
size_t stopIndex, bool exact,
const antlrcpp::BitSet& ambigAlts,
atn::ATNConfigSet* configs) {
if (exactOnly && !exact) {
return;
}
std::string decision = getDecisionDescription(recognizer, dfa);
antlrcpp::BitSet conflictingAlts = getConflictingAlts(ambigAlts, configs);
std::string text = recognizer->getTokenStream()->getText(
misc::Interval(startIndex, stopIndex));
std::string message = "reportAmbiguity d=" + decision +
": ambigAlts=" + conflictingAlts.toString() +
", input='" + text + "'";
recognizer->notifyErrorListeners(message);
}
void DiagnosticErrorListener::reportAttemptingFullContext(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet& /*conflictingAlts*/,
atn::ATNConfigSet* /*configs*/) {
std::string decision = getDecisionDescription(recognizer, dfa);
std::string text = recognizer->getTokenStream()->getText(
misc::Interval(startIndex, stopIndex));
std::string message =
"reportAttemptingFullContext d=" + decision + ", input='" + text + "'";
recognizer->notifyErrorListeners(message);
}
void DiagnosticErrorListener::reportContextSensitivity(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, size_t /*prediction*/, atn::ATNConfigSet* /*configs*/) {
std::string decision = getDecisionDescription(recognizer, dfa);
std::string text = recognizer->getTokenStream()->getText(
misc::Interval(startIndex, stopIndex));
std::string message =
"reportContextSensitivity d=" + decision + ", input='" + text + "'";
recognizer->notifyErrorListeners(message);
}
std::string DiagnosticErrorListener::getDecisionDescription(
Parser* recognizer, const dfa::DFA& dfa) {
size_t decision = dfa.decision;
size_t ruleIndex =
(reinterpret_cast<atn::ATNState*>(dfa.atnStartState))->ruleIndex;
const std::vector<std::string>& ruleNames = recognizer->getRuleNames();
if (ruleIndex == INVALID_INDEX || ruleIndex >= ruleNames.size()) {
return std::to_string(decision);
}
std::string ruleName = ruleNames[ruleIndex];
if (ruleName == "" || ruleName.empty()) {
return std::to_string(decision);
}
return std::to_string(decision) + " (" + ruleName + ")";
}
antlrcpp::BitSet DiagnosticErrorListener::getConflictingAlts(
const antlrcpp::BitSet& reportedAlts, atn::ATNConfigSet* configs) {
if (reportedAlts.count() > 0) { // Not exactly like the original Java code,
// but this listener is only used in the
// TestRig (where it never provides a good
// alt set), so it's probably ok so.
return reportedAlts;
}
antlrcpp::BitSet result;
for (auto& config : configs->configs) {
result.set(config->alt);
}
return result;
}

View File

@ -1,89 +0,0 @@
/* 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.
*/
#pragma once
#include "BaseErrorListener.h"
namespace antlr4 {
/// <summary>
/// This implementation of <seealso cref="ANTLRErrorListener"/> can be used to
/// identify certain potential correctness and performance problems in grammars.
/// "Reports" are made by calling <seealso cref="Parser#notifyErrorListeners"/>
/// with the appropriate message.
///
/// <ul>
/// <li><b>Ambiguities</b>: These are cases where more than one path through the
/// grammar can match the input.</li>
/// <li><b>Weak context sensitivity</b>: These are cases where full-context
/// prediction resolved an SLL conflict to a unique alternative which equaled
/// the minimum alternative of the SLL conflict.</li> <li><b>Strong (forced)
/// context sensitivity</b>: These are cases where the full-context prediction
/// resolved an SLL conflict to a unique alternative, <em>and</em> the minimum
/// alternative of the SLL conflict was found to not be a truly viable
/// alternative. Two-stage parsing cannot be used for inputs where this
/// situation occurs.</li>
/// </ul>
///
/// @author Sam Harwell
/// </summary>
class ANTLR4CPP_PUBLIC DiagnosticErrorListener : public BaseErrorListener {
/// <summary>
/// When {@code true}, only exactly known ambiguities are reported.
/// </summary>
protected:
const bool exactOnly;
/// <summary>
/// Initializes a new instance of <seealso cref="DiagnosticErrorListener"/>
/// which only reports exact ambiguities.
/// </summary>
public:
DiagnosticErrorListener();
/// <summary>
/// Initializes a new instance of <seealso cref="DiagnosticErrorListener"/>,
/// specifying whether all ambiguities or only exact ambiguities are reported.
/// </summary>
/// <param name="exactOnly"> {@code true} to report only exact ambiguities,
/// otherwise
/// {@code false} to report all ambiguities. </param>
DiagnosticErrorListener(bool exactOnly);
virtual void reportAmbiguity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet& ambigAlts,
atn::ATNConfigSet* configs) override;
virtual void reportAttemptingFullContext(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet& conflictingAlts,
atn::ATNConfigSet* configs) override;
virtual void reportContextSensitivity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex,
size_t prediction,
atn::ATNConfigSet* configs) override;
protected:
virtual std::string getDecisionDescription(Parser* recognizer,
const dfa::DFA& dfa);
/// <summary>
/// Computes the set of conflicting or ambiguous alternatives from a
/// configuration set, if that information was not already provided by the
/// parser.
/// </summary>
/// <param name="reportedAlts"> The set of conflicting or ambiguous
/// alternatives, as reported by the parser. </param> <param name="configs">
/// The conflicting or ambiguous configuration set. </param> <returns> Returns
/// {@code reportedAlts} if it is not {@code null}, otherwise returns the set
/// of alternatives represented in {@code configs}. </returns>
virtual antlrcpp::BitSet getConflictingAlts(
const antlrcpp::BitSet& reportedAlts, atn::ATNConfigSet* configs);
};
} // namespace antlr4

View File

@ -1,61 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
using namespace antlr4;
RuntimeException::RuntimeException(const std::string& msg)
: std::exception(), _message(msg) {}
const char* RuntimeException::what() const NOEXCEPT { return _message.c_str(); }
//------------------ IOException
//---------------------------------------------------------------------------------------
IOException::IOException(const std::string& msg)
: std::exception(), _message(msg) {}
const char* IOException::what() const NOEXCEPT { return _message.c_str(); }
//------------------ IllegalStateException
//-----------------------------------------------------------------------------
IllegalStateException::~IllegalStateException() {}
//------------------ IllegalArgumentException
//--------------------------------------------------------------------------
IllegalArgumentException::~IllegalArgumentException() {}
//------------------ NullPointerException
//------------------------------------------------------------------------------
NullPointerException::~NullPointerException() {}
//------------------ IndexOutOfBoundsException
//-------------------------------------------------------------------------
IndexOutOfBoundsException::~IndexOutOfBoundsException() {}
//------------------ UnsupportedOperationException
//---------------------------------------------------------------------
UnsupportedOperationException::~UnsupportedOperationException() {}
//------------------ EmptyStackException
//-------------------------------------------------------------------------------
EmptyStackException::~EmptyStackException() {}
//------------------ CancellationException
//-----------------------------------------------------------------------------
CancellationException::~CancellationException() {}
//------------------ ParseCancellationException
//------------------------------------------------------------------------
ParseCancellationException::~ParseCancellationException() {}

View File

@ -1,109 +0,0 @@
/* 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.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
// An exception hierarchy modelled loosely after java.lang.* exceptions.
class ANTLR4CPP_PUBLIC RuntimeException : public std::exception {
private:
std::string _message;
public:
RuntimeException(const std::string& msg = "");
virtual const char* what() const NOEXCEPT override;
};
class ANTLR4CPP_PUBLIC IllegalStateException : public RuntimeException {
public:
IllegalStateException(const std::string& msg = "") : RuntimeException(msg) {}
IllegalStateException(IllegalStateException const&) = default;
~IllegalStateException();
IllegalStateException& operator=(IllegalStateException const&) = default;
};
class ANTLR4CPP_PUBLIC IllegalArgumentException : public RuntimeException {
public:
IllegalArgumentException(IllegalArgumentException const&) = default;
IllegalArgumentException(const std::string& msg = "")
: RuntimeException(msg) {}
~IllegalArgumentException();
IllegalArgumentException& operator=(IllegalArgumentException const&) =
default;
};
class ANTLR4CPP_PUBLIC NullPointerException : public RuntimeException {
public:
NullPointerException(const std::string& msg = "") : RuntimeException(msg) {}
NullPointerException(NullPointerException const&) = default;
~NullPointerException();
NullPointerException& operator=(NullPointerException const&) = default;
};
class ANTLR4CPP_PUBLIC IndexOutOfBoundsException : public RuntimeException {
public:
IndexOutOfBoundsException(const std::string& msg = "")
: RuntimeException(msg) {}
IndexOutOfBoundsException(IndexOutOfBoundsException const&) = default;
~IndexOutOfBoundsException();
IndexOutOfBoundsException& operator=(IndexOutOfBoundsException const&) =
default;
};
class ANTLR4CPP_PUBLIC UnsupportedOperationException : public RuntimeException {
public:
UnsupportedOperationException(const std::string& msg = "")
: RuntimeException(msg) {}
UnsupportedOperationException(UnsupportedOperationException const&) = default;
~UnsupportedOperationException();
UnsupportedOperationException& operator=(
UnsupportedOperationException const&) = default;
};
class ANTLR4CPP_PUBLIC EmptyStackException : public RuntimeException {
public:
EmptyStackException(const std::string& msg = "") : RuntimeException(msg) {}
EmptyStackException(EmptyStackException const&) = default;
~EmptyStackException();
EmptyStackException& operator=(EmptyStackException const&) = default;
};
// IOException is not a runtime exception (in the java hierarchy).
// Hence we have to duplicate the RuntimeException implementation.
class ANTLR4CPP_PUBLIC IOException : public std::exception {
private:
std::string _message;
public:
IOException(const std::string& msg = "");
virtual const char* what() const NOEXCEPT override;
};
class ANTLR4CPP_PUBLIC CancellationException : public IllegalStateException {
public:
CancellationException(const std::string& msg = "")
: IllegalStateException(msg) {}
CancellationException(CancellationException const&) = default;
~CancellationException();
CancellationException& operator=(CancellationException const&) = default;
};
class ANTLR4CPP_PUBLIC ParseCancellationException
: public CancellationException {
public:
ParseCancellationException(const std::string& msg = "")
: CancellationException(msg) {}
ParseCancellationException(ParseCancellationException const&) = default;
~ParseCancellationException();
ParseCancellationException& operator=(ParseCancellationException const&) =
default;
};
} // namespace antlr4

View File

@ -1,51 +0,0 @@
/* 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.
*/
#include "Parser.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "atn/ParserATNSimulator.h"
#include "atn/PredicateTransition.h"
#include "support/CPPUtils.h"
#include "FailedPredicateException.h"
using namespace antlr4;
using namespace antlrcpp;
FailedPredicateException::FailedPredicateException(Parser* recognizer)
: FailedPredicateException(recognizer, "", "") {}
FailedPredicateException::FailedPredicateException(Parser* recognizer,
const std::string& predicate)
: FailedPredicateException(recognizer, predicate, "") {}
FailedPredicateException::FailedPredicateException(Parser* recognizer,
const std::string& predicate,
const std::string& message)
: RecognitionException(
!message.empty() ? message : "failed predicate: " + predicate + "?",
recognizer, recognizer->getInputStream(), recognizer->getContext(),
recognizer->getCurrentToken()) {
atn::ATNState* s = recognizer->getInterpreter<atn::ATNSimulator>()
->atn.states[recognizer->getState()];
atn::Transition* transition = s->transitions[0];
if (is<atn::PredicateTransition*>(transition)) {
_ruleIndex = static_cast<atn::PredicateTransition*>(transition)->ruleIndex;
_predicateIndex =
static_cast<atn::PredicateTransition*>(transition)->predIndex;
} else {
_ruleIndex = 0;
_predicateIndex = 0;
}
_predicate = predicate;
}
size_t FailedPredicateException::getRuleIndex() { return _ruleIndex; }
size_t FailedPredicateException::getPredIndex() { return _predicateIndex; }
std::string FailedPredicateException::getPredicate() { return _predicate; }

View File

@ -1,33 +0,0 @@
/* 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.
*/
#pragma once
#include "RecognitionException.h"
namespace antlr4 {
/// A semantic predicate failed during validation. Validation of predicates
/// occurs when normally parsing the alternative just like matching a token.
/// Disambiguating predicate evaluation occurs when we test a predicate during
/// prediction.
class ANTLR4CPP_PUBLIC FailedPredicateException : public RecognitionException {
public:
FailedPredicateException(Parser* recognizer);
FailedPredicateException(Parser* recognizer, const std::string& predicate);
FailedPredicateException(Parser* recognizer, const std::string& predicate,
const std::string& message);
virtual size_t getRuleIndex();
virtual size_t getPredIndex();
virtual std::string getPredicate();
private:
size_t _ruleIndex;
size_t _predicateIndex;
std::string _predicate;
};
} // namespace antlr4

View File

@ -1,17 +0,0 @@
/* 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.
*/
#include "Parser.h"
#include "InputMismatchException.h"
using namespace antlr4;
InputMismatchException::InputMismatchException(Parser* recognizer)
: RecognitionException(recognizer, recognizer->getInputStream(),
recognizer->getContext(),
recognizer->getCurrentToken()) {}
InputMismatchException::~InputMismatchException() {}

View File

@ -1,24 +0,0 @@
/* 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.
*/
#pragma once
#include "RecognitionException.h"
namespace antlr4 {
/// <summary>
/// This signifies any kind of mismatched input exceptions such as
/// when the current input does not match the expected token.
/// </summary>
class ANTLR4CPP_PUBLIC InputMismatchException : public RecognitionException {
public:
InputMismatchException(Parser* recognizer);
InputMismatchException(InputMismatchException const&) = default;
~InputMismatchException();
InputMismatchException& operator=(InputMismatchException const&) = default;
};
} // namespace antlr4

View File

@ -1,12 +0,0 @@
/* 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.
*/
#include "IntStream.h"
using namespace antlr4;
const std::string IntStream::UNKNOWN_SOURCE_NAME = "<unknown>";
IntStream::~IntStream() = default;

View File

@ -1,222 +0,0 @@
/* 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.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
/// <summary>
/// A simple stream of symbols whose values are represented as integers. This
/// interface provides <em>marked ranges</em> with support for a minimum level
/// of buffering necessary to implement arbitrary lookahead during prediction.
/// For more information on marked ranges, see <seealso cref="#mark"/>.
/// <p/>
/// <strong>Initializing Methods:</strong> Some methods in this interface have
/// unspecified behavior if no call to an initializing method has occurred after
/// the stream was constructed. The following is a list of initializing methods:
///
/// <ul>
/// <li><seealso cref="#LA"/></li>
/// <li><seealso cref="#consume"/></li>
/// <li><seealso cref="#size"/></li>
/// </ul>
/// </summary>
class ANTLR4CPP_PUBLIC IntStream {
public:
static const size_t EOF = static_cast<size_t>(
-1); // std::numeric_limits<size_t>::max(); doesn't work in VS 2013
/// The value returned by <seealso cref="#LA LA()"/> when the end of the
/// stream is reached. No explicit EOF definition. We got EOF on all
/// platforms.
// static const size_t _EOF = std::ios::eofbit;
/// <summary>
/// The value returned by <seealso cref="#getSourceName"/> when the actual
/// name of the underlying source is not known.
/// </summary>
static const std::string UNKNOWN_SOURCE_NAME;
virtual ~IntStream();
/// <summary>
/// Consumes the current symbol in the stream. This method has the following
/// effects:
///
/// <ul>
/// <li><strong>Forward movement:</strong> The value of <seealso
/// cref="#index index()"/>
/// before calling this method is less than the value of {@code
/// index()} after calling this method.</li>
/// <li><strong>Ordered lookahead:</strong> The value of {@code LA(1)}
/// before
/// calling this method becomes the value of {@code LA(-1)} after
/// calling this method.</li>
/// </ul>
///
/// Note that calling this method does not guarantee that {@code index()} is
/// incremented by exactly 1, as that would preclude the ability to implement
/// filtering streams (e.g. <seealso cref="CommonTokenStream"/> which
/// distinguishes between "on-channel" and "off-channel" tokens).
/// </summary>
/// <exception cref="IllegalStateException"> if an attempt is made to consume
/// the the end of the stream (i.e. if {@code LA(1)==}<seealso cref="#EOF
/// EOF"/> before calling
/// {@code consume}). </exception>
virtual void consume() = 0;
/// <summary>
/// Gets the value of the symbol at offset {@code i} from the current
/// position. When {@code i==1}, this method returns the value of the current
/// symbol in the stream (which is the next symbol to be consumed). When
/// {@code i==-1}, this method returns the value of the previously read
/// symbol in the stream. It is not valid to call this method with
/// {@code i==0}, but the specific behavior is unspecified because this
/// method is frequently called from performance-critical code.
/// <p/>
/// This method is guaranteed to succeed if any of the following are true:
///
/// <ul>
/// <li>{@code i>0}</li>
/// <li>{@code i==-1} and <seealso cref="#index index()"/> returns a value
/// greater
/// than the value of {@code index()} after the stream was constructed
/// and {@code LA(1)} was called in that order. Specifying the current
/// {@code index()} relative to the index after the stream was created
/// allows for filtering implementations that do not return every symbol
/// from the underlying source. Specifying the call to {@code LA(1)}
/// allows for lazily initialized streams.</li>
/// <li>{@code LA(i)} refers to a symbol consumed within a marked region
/// that has not yet been released.</li>
/// </ul>
///
/// If {@code i} represents a position at or beyond the end of the stream,
/// this method returns <seealso cref="#EOF"/>.
/// <p/>
/// The return value is unspecified if {@code i<0} and fewer than {@code -i}
/// calls to <seealso cref="#consume consume()"/> have occurred from the
/// beginning of the stream before calling this method.
/// </summary>
/// <exception cref="UnsupportedOperationException"> if the stream does not
/// support retrieving the value of the specified symbol </exception>
virtual size_t LA(ssize_t i) = 0;
/// <summary>
/// A mark provides a guarantee that <seealso cref="#seek seek()"/> operations
/// will be valid over a "marked range" extending from the index where {@code
/// mark()} was called to the current <seealso cref="#index index()"/>. This
/// allows the use of streaming input sources by specifying the minimum
/// buffering requirements to support arbitrary lookahead during prediction.
/// <p/>
/// The returned mark is an opaque handle (type {@code int}) which is passed
/// to <seealso cref="#release release()"/> when the guarantees provided by
/// the marked range are no longer necessary. When calls to
/// {@code mark()}/{@code release()} are nested, the marks must be released
/// in reverse order of which they were obtained. Since marked regions are
/// used during performance-critical sections of prediction, the specific
/// behavior of invalid usage is unspecified (i.e. a mark is not released, or
/// a mark is released twice, or marks are not released in reverse order from
/// which they were created).
/// <p/>
/// The behavior of this method is unspecified if no call to an
/// <seealso cref="IntStream initializing method"/> has occurred after this
/// stream was constructed. <p/> This method does not change the current
/// position in the input stream. <p/> The following example shows the use of
/// <seealso cref="#mark mark()"/>, <seealso cref="#release release(mark)"/>,
/// <seealso cref="#index index()"/>, and <seealso cref="#seek seek(index)"/>
/// as part of an operation to safely work within a marked region, then
/// restore the stream position to its original value and release the mark.
/// <pre>
/// IntStream stream = ...;
/// int index = -1;
/// int mark = stream.mark();
/// try {
/// index = stream.index();
/// // perform work here...
/// } finally {
/// if (index != -1) {
/// stream.seek(index);
/// }
/// stream.release(mark);
/// }
/// </pre>
/// </summary>
/// <returns> An opaque marker which should be passed to
/// <seealso cref="#release release()"/> when the marked range is no longer
/// required. </returns>
virtual ssize_t mark() = 0;
/// <summary>
/// This method releases a marked range created by a call to
/// <seealso cref="#mark mark()"/>. Calls to {@code release()} must appear in
/// the reverse order of the corresponding calls to {@code mark()}. If a mark
/// is released twice, or if marks are not released in reverse order of the
/// corresponding calls to {@code mark()}, the behavior is unspecified.
/// <p/>
/// For more information and an example, see <seealso cref="#mark"/>.
/// </summary>
/// <param name="marker"> A marker returned by a call to {@code mark()}.
/// </param> <seealso cref= #mark </seealso>
virtual void release(ssize_t marker) = 0;
/// <summary>
/// Return the index into the stream of the input symbol referred to by
/// {@code LA(1)}.
/// <p/>
/// The behavior of this method is unspecified if no call to an
/// <seealso cref="IntStream initializing method"/> has occurred after this
/// stream was constructed.
/// </summary>
virtual size_t index() = 0;
/// <summary>
/// Set the input cursor to the position indicated by {@code index}. If the
/// specified index lies past the end of the stream, the operation behaves as
/// though {@code index} was the index of the EOF symbol. After this method
/// returns without throwing an exception, the at least one of the following
/// will be true.
///
/// <ul>
/// <li><seealso cref="#index index()"/> will return the index of the first
/// symbol
/// appearing at or after the specified {@code index}. Specifically,
/// implementations which filter their sources should automatically
/// adjust {@code index} forward the minimum amount required for the
/// operation to target a non-ignored symbol.</li>
/// <li>{@code LA(1)} returns <seealso cref="#EOF"/></li>
/// </ul>
///
/// This operation is guaranteed to not throw an exception if {@code index}
/// lies within a marked region. For more information on marked regions, see
/// <seealso cref="#mark"/>. The behavior of this method is unspecified if no
/// call to an <seealso cref="IntStream initializing method"/> has occurred
/// after this stream was constructed.
/// </summary>
/// <param name="index"> The absolute index to seek to.
/// </param>
/// <exception cref="IllegalArgumentException"> if {@code index} is less than
/// 0 </exception> <exception cref="UnsupportedOperationException"> if the
/// stream does not support seeking to the specified index </exception>
virtual void seek(size_t index) = 0;
/// <summary>
/// Returns the total number of symbols in the stream, including a single EOF
/// symbol.
/// </summary>
/// <exception cref="UnsupportedOperationException"> if the size of the stream
/// is unknown. </exception>
virtual size_t size() = 0;
/// <summary>
/// Gets the name of the underlying symbol source. This method returns a
/// non-null, non-empty string. If such a name is not known, this method
/// returns <seealso cref="#UNKNOWN_SOURCE_NAME"/>.
/// </summary>
virtual std::string getSourceName() const = 0;
};
} // namespace antlr4

View File

@ -1,17 +0,0 @@
/* 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.
*/
#include "InterpreterRuleContext.h"
using namespace antlr4;
InterpreterRuleContext::InterpreterRuleContext() : ParserRuleContext() {}
InterpreterRuleContext::InterpreterRuleContext(ParserRuleContext* parent,
size_t invokingStateNumber,
size_t ruleIndex)
: ParserRuleContext(parent, invokingStateNumber), _ruleIndex(ruleIndex) {}
size_t InterpreterRuleContext::getRuleIndex() const { return _ruleIndex; }

View File

@ -1,46 +0,0 @@
/* 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.
*/
#pragma once
#include "ParserRuleContext.h"
namespace antlr4 {
/**
* This class extends {@link ParserRuleContext} by allowing the value of
* {@link #getRuleIndex} to be explicitly set for the context.
*
* <p>
* {@link ParserRuleContext} does not include field storage for the rule index
* since the context classes created by the code generator override the
* {@link #getRuleIndex} method to return the correct value for that context.
* Since the parser interpreter does not use the context classes generated for a
* parser, this class (with slightly more memory overhead per node) is used to
* provide equivalent functionality.</p>
*/
class ANTLR4CPP_PUBLIC InterpreterRuleContext : public ParserRuleContext {
public:
InterpreterRuleContext();
/**
* Constructs a new {@link InterpreterRuleContext} with the specified
* parent, invoking state, and rule index.
*
* @param parent The parent context.
* @param invokingStateNumber The invoking state number.
* @param ruleIndex The rule index for the current context.
*/
InterpreterRuleContext(ParserRuleContext* parent, size_t invokingStateNumber,
size_t ruleIndex);
virtual size_t getRuleIndex() const override;
protected:
/** This is the backing field for {@link #getRuleIndex}. */
const size_t _ruleIndex = INVALID_INDEX;
};
} // namespace antlr4

View File

@ -1,274 +0,0 @@
/* 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.
*/
#include "ANTLRErrorListener.h"
#include "CommonToken.h"
#include "CommonTokenFactory.h"
#include "Exceptions.h"
#include "LexerNoViableAltException.h"
#include "atn/LexerATNSimulator.h"
#include "misc/Interval.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "Lexer.h"
#define DEBUG_LEXER 0
using namespace antlrcpp;
using namespace antlr4;
Lexer::Lexer() : Recognizer() {
InitializeInstanceFields();
_input = nullptr;
}
Lexer::Lexer(CharStream* input) : Recognizer(), _input(input) {
InitializeInstanceFields();
}
void Lexer::reset() {
// wack Lexer state variables
_input->seek(0); // rewind the input
_syntaxErrors = 0;
token.reset();
type = Token::INVALID_TYPE;
channel = Token::DEFAULT_CHANNEL;
tokenStartCharIndex = INVALID_INDEX;
tokenStartCharPositionInLine = 0;
tokenStartLine = 0;
type = 0;
_text = "";
hitEOF = false;
mode = Lexer::DEFAULT_MODE;
modeStack.clear();
getInterpreter<atn::LexerATNSimulator>()->reset();
}
std::unique_ptr<Token> Lexer::nextToken() {
// Mark start location in char stream so unbuffered streams are
// guaranteed at least have text of current token
ssize_t tokenStartMarker = _input->mark();
auto onExit = finally([this, tokenStartMarker] {
// make sure we release marker after match or
// unbuffered char stream will keep buffering
_input->release(tokenStartMarker);
});
while (true) {
outerContinue:
if (hitEOF) {
emitEOF();
return std::move(token);
}
token.reset();
channel = Token::DEFAULT_CHANNEL;
tokenStartCharIndex = _input->index();
tokenStartCharPositionInLine =
getInterpreter<atn::LexerATNSimulator>()->getCharPositionInLine();
tokenStartLine = getInterpreter<atn::LexerATNSimulator>()->getLine();
_text = "";
do {
type = Token::INVALID_TYPE;
size_t ttype;
try {
ttype = getInterpreter<atn::LexerATNSimulator>()->match(_input, mode);
} catch (LexerNoViableAltException& e) {
notifyListeners(e); // report error
recover(e);
ttype = SKIP;
}
if (_input->LA(1) == EOF) {
hitEOF = true;
}
if (type == Token::INVALID_TYPE) {
type = ttype;
}
if (type == SKIP) {
goto outerContinue;
}
} while (type == MORE);
if (token == nullptr) {
emit();
}
return std::move(token);
}
}
void Lexer::skip() { type = SKIP; }
void Lexer::more() { type = MORE; }
void Lexer::setMode(size_t m) { mode = m; }
void Lexer::pushMode(size_t m) {
#if DEBUG_LEXER == 1
std::cout << "pushMode " << m << std::endl;
#endif
modeStack.push_back(mode);
setMode(m);
}
size_t Lexer::popMode() {
if (modeStack.empty()) {
throw EmptyStackException();
}
#if DEBUG_LEXER == 1
std::cout << std::string("popMode back to ") << modeStack.back() << std::endl;
#endif
setMode(modeStack.back());
modeStack.pop_back();
return mode;
}
Ref<TokenFactory<CommonToken>> Lexer::getTokenFactory() { return _factory; }
void Lexer::setInputStream(IntStream* input) {
reset();
_input = dynamic_cast<CharStream*>(input);
}
std::string Lexer::getSourceName() { return _input->getSourceName(); }
CharStream* Lexer::getInputStream() { return _input; }
void Lexer::emit(std::unique_ptr<Token> newToken) {
token = std::move(newToken);
}
Token* Lexer::emit() {
emit(_factory->create({this, _input}, type, _text, channel,
tokenStartCharIndex, getCharIndex() - 1, tokenStartLine,
tokenStartCharPositionInLine));
return token.get();
}
Token* Lexer::emitEOF() {
size_t cpos = getCharPositionInLine();
size_t line = getLine();
emit(_factory->create({this, _input}, EOF, "", Token::DEFAULT_CHANNEL,
_input->index(), _input->index() - 1, line, cpos));
return token.get();
}
size_t Lexer::getLine() const {
return getInterpreter<atn::LexerATNSimulator>()->getLine();
}
size_t Lexer::getCharPositionInLine() {
return getInterpreter<atn::LexerATNSimulator>()->getCharPositionInLine();
}
void Lexer::setLine(size_t line) {
getInterpreter<atn::LexerATNSimulator>()->setLine(line);
}
void Lexer::setCharPositionInLine(size_t charPositionInLine) {
getInterpreter<atn::LexerATNSimulator>()->setCharPositionInLine(
charPositionInLine);
}
size_t Lexer::getCharIndex() { return _input->index(); }
std::string Lexer::getText() {
if (!_text.empty()) {
return _text;
}
return getInterpreter<atn::LexerATNSimulator>()->getText(_input);
}
void Lexer::setText(const std::string& text) { _text = text; }
std::unique_ptr<Token> Lexer::getToken() { return std::move(token); }
void Lexer::setToken(std::unique_ptr<Token> newToken) {
token = std::move(newToken);
}
void Lexer::setType(size_t ttype) { type = ttype; }
size_t Lexer::getType() { return type; }
void Lexer::setChannel(size_t newChannel) { channel = newChannel; }
size_t Lexer::getChannel() { return channel; }
std::vector<std::unique_ptr<Token>> Lexer::getAllTokens() {
std::vector<std::unique_ptr<Token>> tokens;
std::unique_ptr<Token> t = nextToken();
while (t->getType() != EOF) {
tokens.push_back(std::move(t));
t = nextToken();
}
return tokens;
}
void Lexer::recover(const LexerNoViableAltException& /*e*/) {
if (_input->LA(1) != EOF) {
// skip a char and try again
getInterpreter<atn::LexerATNSimulator>()->consume(_input);
}
}
void Lexer::notifyListeners(const LexerNoViableAltException& /*e*/) {
++_syntaxErrors;
std::string text =
_input->getText(misc::Interval(tokenStartCharIndex, _input->index()));
std::string msg = std::string("token recognition error at: '") +
getErrorDisplay(text) + std::string("'");
ProxyErrorListener& listener = getErrorListenerDispatch();
listener.syntaxError(this, nullptr, tokenStartLine,
tokenStartCharPositionInLine, msg,
std::current_exception());
}
std::string Lexer::getErrorDisplay(const std::string& s) {
std::stringstream ss;
for (auto c : s) {
switch (c) {
case '\n':
ss << "\\n";
break;
case '\t':
ss << "\\t";
break;
case '\r':
ss << "\\r";
break;
default:
ss << c;
break;
}
}
return ss.str();
}
void Lexer::recover(RecognitionException* /*re*/) {
// TO_DO: Do we lose character or line position information?
_input->consume();
}
size_t Lexer::getNumberOfSyntaxErrors() { return _syntaxErrors; }
void Lexer::InitializeInstanceFields() {
_syntaxErrors = 0;
token = nullptr;
_factory = CommonTokenFactory::DEFAULT;
tokenStartCharIndex = INVALID_INDEX;
tokenStartLine = 0;
tokenStartCharPositionInLine = 0;
hitEOF = false;
channel = 0;
type = 0;
mode = Lexer::DEFAULT_MODE;
}

View File

@ -1,198 +0,0 @@
/* 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.
*/
#pragma once
#include "CharStream.h"
#include "Recognizer.h"
#include "Token.h"
#include "TokenSource.h"
namespace antlr4 {
/// A lexer is recognizer that draws input symbols from a character stream.
/// lexer grammars result in a subclass of this object. A Lexer object
/// uses simplified match() and error recovery mechanisms in the interest
/// of speed.
class ANTLR4CPP_PUBLIC Lexer : public Recognizer, public TokenSource {
public:
static const size_t DEFAULT_MODE = 0;
static const size_t MORE = static_cast<size_t>(-2);
static const size_t SKIP = static_cast<size_t>(-3);
static const size_t DEFAULT_TOKEN_CHANNEL = Token::DEFAULT_CHANNEL;
static const size_t HIDDEN = Token::HIDDEN_CHANNEL;
static const size_t MIN_CHAR_VALUE = 0;
static const size_t MAX_CHAR_VALUE = 0x10FFFF;
CharStream*
_input; // Pure reference, usually from statically allocated instance.
protected:
/// How to create token objects.
Ref<TokenFactory<CommonToken>> _factory;
public:
/// The goal of all lexer rules/methods is to create a token object.
/// This is an instance variable as multiple rules may collaborate to
/// create a single token. nextToken will return this object after
/// matching lexer rule(s). If you subclass to allow multiple token
/// emissions, then set this to the last token to be matched or
/// something nonnull so that the auto token emit mechanism will not
/// emit another token.
// Life cycle of a token is this:
// Created by emit() (via the token factory) or by action code, holding
// ownership of it. Ownership is handed over to the token stream when calling
// nextToken().
std::unique_ptr<Token> token;
/// <summary>
/// What character index in the stream did the current token start at?
/// Needed, for example, to get the text for current token. Set at
/// the start of nextToken.
/// </summary>
size_t tokenStartCharIndex;
/// <summary>
/// The line on which the first character of the token resides </summary>
size_t tokenStartLine;
/// The character position of first character within the line.
size_t tokenStartCharPositionInLine;
/// Once we see EOF on char stream, next token will be EOF.
/// If you have DONE : EOF ; then you see DONE EOF.
bool hitEOF;
/// The channel number for the current token.
size_t channel;
/// The token type for the current token.
size_t type;
// Use the vector as a stack.
std::vector<size_t> modeStack;
size_t mode;
Lexer();
Lexer(CharStream* input);
virtual ~Lexer() {}
virtual void reset();
/// Return a token from this source; i.e., match a token on the char stream.
virtual std::unique_ptr<Token> nextToken() override;
/// Instruct the lexer to skip creating a token for current lexer rule
/// and look for another token. nextToken() knows to keep looking when
/// a lexer rule finishes with token set to SKIP_TOKEN. Recall that
/// if token == null at end of any token rule, it creates one for you
/// and emits it.
virtual void skip();
virtual void more();
virtual void setMode(size_t m);
virtual void pushMode(size_t m);
virtual size_t popMode();
template <typename T1>
void setTokenFactory(TokenFactory<T1>* factory) {
this->_factory = factory;
}
virtual Ref<TokenFactory<CommonToken>> getTokenFactory() override;
/// Set the char stream and reset the lexer
virtual void setInputStream(IntStream* input) override;
virtual std::string getSourceName() override;
virtual CharStream* getInputStream() override;
/// By default does not support multiple emits per nextToken invocation
/// for efficiency reasons. Subclasses can override this method, nextToken,
/// and getToken (to push tokens into a list and pull from that list
/// rather than a single variable as this implementation does).
virtual void emit(std::unique_ptr<Token> newToken);
/// The standard method called to automatically emit a token at the
/// outermost lexical rule. The token object should point into the
/// char buffer start..stop. If there is a text override in 'text',
/// use that to set the token's text. Override this method to emit
/// custom Token objects or provide a new factory.
virtual Token* emit();
virtual Token* emitEOF();
virtual size_t getLine() const override;
virtual size_t getCharPositionInLine() override;
virtual void setLine(size_t line);
virtual void setCharPositionInLine(size_t charPositionInLine);
/// What is the index of the current character of lookahead?
virtual size_t getCharIndex();
/// Return the text matched so far for the current token or any
/// text override.
virtual std::string getText();
/// Set the complete text of this token; it wipes any previous
/// changes to the text.
virtual void setText(const std::string& text);
/// Override if emitting multiple tokens.
virtual std::unique_ptr<Token> getToken();
virtual void setToken(std::unique_ptr<Token> newToken);
virtual void setType(size_t ttype);
virtual size_t getType();
virtual void setChannel(size_t newChannel);
virtual size_t getChannel();
virtual const std::vector<std::string>& getChannelNames() const = 0;
virtual const std::vector<std::string>& getModeNames() const = 0;
/// Return a list of all Token objects in input char stream.
/// Forces load of all tokens. Does not include EOF token.
virtual std::vector<std::unique_ptr<Token>> getAllTokens();
virtual void recover(const LexerNoViableAltException& e);
virtual void notifyListeners(const LexerNoViableAltException& e);
virtual std::string getErrorDisplay(const std::string& s);
/// Lexers can normally match any char in it's vocabulary after matching
/// a token, so do the easy thing and just kill a character and hope
/// it all works out. You can instead use the rule invocation stack
/// to do sophisticated error recovery if you are in a fragment rule.
virtual void recover(RecognitionException* re);
/// <summary>
/// Gets the number of syntax errors reported during parsing. This value is
/// incremented each time <seealso cref="#notifyErrorListeners"/> is called.
/// </summary>
/// <seealso cref= #notifyListeners </seealso>
virtual size_t getNumberOfSyntaxErrors();
protected:
/// You can set the text for the current token to override what is in
/// the input char buffer (via setText()).
std::string _text;
private:
size_t _syntaxErrors;
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,82 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "Vocabulary.h"
#include "atn/ATNType.h"
#include "atn/EmptyPredictionContext.h"
#include "atn/LexerATNSimulator.h"
#include "dfa/DFA.h"
#include "LexerInterpreter.h"
using namespace antlr4;
LexerInterpreter::LexerInterpreter(const std::string& grammarFileName,
const std::vector<std::string>& tokenNames,
const std::vector<std::string>& ruleNames,
const std::vector<std::string>& channelNames,
const std::vector<std::string>& modeNames,
const atn::ATN& atn, CharStream* input)
: LexerInterpreter(grammarFileName,
dfa::Vocabulary::fromTokenNames(tokenNames), ruleNames,
channelNames, modeNames, atn, input) {}
LexerInterpreter::LexerInterpreter(const std::string& grammarFileName,
const dfa::Vocabulary& vocabulary,
const std::vector<std::string>& ruleNames,
const std::vector<std::string>& channelNames,
const std::vector<std::string>& modeNames,
const atn::ATN& atn, CharStream* input)
: Lexer(input),
_grammarFileName(grammarFileName),
_atn(atn),
_ruleNames(ruleNames),
_channelNames(channelNames),
_modeNames(modeNames),
_vocabulary(vocabulary) {
if (_atn.grammarType != atn::ATNType::LEXER) {
throw IllegalArgumentException("The ATN must be a lexer ATN.");
}
for (size_t i = 0; i < atn.maxTokenType; i++) {
_tokenNames.push_back(vocabulary.getDisplayName(i));
}
for (size_t i = 0; i < atn.getNumberOfDecisions(); ++i) {
_decisionToDFA.push_back(dfa::DFA(_atn.getDecisionState(i), i));
}
_interpreter = new atn::LexerATNSimulator(
this, _atn, _decisionToDFA,
_sharedContextCache); /* mem-check: deleted in d-tor */
}
LexerInterpreter::~LexerInterpreter() { delete _interpreter; }
const atn::ATN& LexerInterpreter::getATN() const { return _atn; }
std::string LexerInterpreter::getGrammarFileName() const {
return _grammarFileName;
}
const std::vector<std::string>& LexerInterpreter::getTokenNames() const {
return _tokenNames;
}
const std::vector<std::string>& LexerInterpreter::getRuleNames() const {
return _ruleNames;
}
const std::vector<std::string>& LexerInterpreter::getChannelNames() const {
return _channelNames;
}
const std::vector<std::string>& LexerInterpreter::getModeNames() const {
return _modeNames;
}
const dfa::Vocabulary& LexerInterpreter::getVocabulary() const {
return _vocabulary;
}

View File

@ -1,58 +0,0 @@
/* 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.
*/
#pragma once
#include "Lexer.h"
#include "Vocabulary.h"
#include "atn/PredictionContext.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC LexerInterpreter : public Lexer {
public:
// @deprecated
LexerInterpreter(const std::string& grammarFileName,
const std::vector<std::string>& tokenNames,
const std::vector<std::string>& ruleNames,
const std::vector<std::string>& channelNames,
const std::vector<std::string>& modeNames,
const atn::ATN& atn, CharStream* input);
LexerInterpreter(const std::string& grammarFileName,
const dfa::Vocabulary& vocabulary,
const std::vector<std::string>& ruleNames,
const std::vector<std::string>& channelNames,
const std::vector<std::string>& modeNames,
const atn::ATN& atn, CharStream* input);
~LexerInterpreter();
virtual const atn::ATN& getATN() const override;
virtual std::string getGrammarFileName() const override;
virtual const std::vector<std::string>& getTokenNames() const override;
virtual const std::vector<std::string>& getRuleNames() const override;
virtual const std::vector<std::string>& getChannelNames() const override;
virtual const std::vector<std::string>& getModeNames() const override;
virtual const dfa::Vocabulary& getVocabulary() const override;
protected:
const std::string _grammarFileName;
const atn::ATN& _atn;
// @deprecated
std::vector<std::string> _tokenNames;
const std::vector<std::string>& _ruleNames;
const std::vector<std::string>& _channelNames;
const std::vector<std::string>& _modeNames;
std::vector<dfa::DFA> _decisionToDFA;
atn::PredictionContextCache _sharedContextCache;
private:
dfa::Vocabulary _vocabulary;
};
} // namespace antlr4

View File

@ -1,37 +0,0 @@
/* 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.
*/
#include "CharStream.h"
#include "Lexer.h"
#include "misc/Interval.h"
#include "support/CPPUtils.h"
#include "LexerNoViableAltException.h"
using namespace antlr4;
LexerNoViableAltException::LexerNoViableAltException(
Lexer* lexer, CharStream* input, size_t startIndex,
atn::ATNConfigSet* deadEndConfigs)
: RecognitionException(lexer, input, nullptr, nullptr),
_startIndex(startIndex),
_deadEndConfigs(deadEndConfigs) {}
size_t LexerNoViableAltException::getStartIndex() { return _startIndex; }
atn::ATNConfigSet* LexerNoViableAltException::getDeadEndConfigs() {
return _deadEndConfigs;
}
std::string LexerNoViableAltException::toString() {
std::string symbol;
if (_startIndex < getInputStream()->size()) {
symbol = static_cast<CharStream*>(getInputStream())
->getText(misc::Interval(_startIndex, _startIndex));
symbol = antlrcpp::escapeWhitespace(symbol, false);
}
std::string format = "LexerNoViableAltException('" + symbol + "')";
return format;
}

View File

@ -1,31 +0,0 @@
/* 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.
*/
#pragma once
#include "RecognitionException.h"
#include "atn/ATNConfigSet.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC LexerNoViableAltException : public RecognitionException {
public:
LexerNoViableAltException(Lexer* lexer, CharStream* input, size_t startIndex,
atn::ATNConfigSet* deadEndConfigs);
virtual size_t getStartIndex();
virtual atn::ATNConfigSet* getDeadEndConfigs();
virtual std::string toString();
private:
/// Matching attempted at what input index?
const size_t _startIndex;
/// Which configurations did we try at input.index() that couldn't match
/// input.LA(1)?
atn::ATNConfigSet* _deadEndConfigs;
};
} // namespace antlr4

View File

@ -1,95 +0,0 @@
/* 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.
*/
#include "CharStream.h"
#include "CommonToken.h"
#include "Token.h"
#include "ListTokenSource.h"
using namespace antlr4;
ListTokenSource::ListTokenSource(std::vector<std::unique_ptr<Token>> tokens_)
: ListTokenSource(std::move(tokens_), "") {}
ListTokenSource::ListTokenSource(std::vector<std::unique_ptr<Token>> tokens_,
const std::string& sourceName_)
: tokens(std::move(tokens_)), sourceName(sourceName_) {
InitializeInstanceFields();
if (tokens.empty()) {
throw "tokens cannot be null";
}
// Check if there is an eof token and create one if not.
if (tokens.back()->getType() != Token::EOF) {
Token* lastToken = tokens.back().get();
size_t start = INVALID_INDEX;
size_t previousStop = lastToken->getStopIndex();
if (previousStop != INVALID_INDEX) {
start = previousStop + 1;
}
size_t stop = std::max(INVALID_INDEX, start - 1);
tokens.emplace_back((_factory->create(
{this, getInputStream()}, Token::EOF, "EOF", Token::DEFAULT_CHANNEL,
start, stop, static_cast<int>(lastToken->getLine()),
lastToken->getCharPositionInLine())));
}
}
size_t ListTokenSource::getCharPositionInLine() {
if (i < tokens.size()) {
return tokens[i]->getCharPositionInLine();
}
return 0;
}
std::unique_ptr<Token> ListTokenSource::nextToken() {
if (i < tokens.size()) {
return std::move(tokens[i++]);
}
return nullptr;
}
size_t ListTokenSource::getLine() const {
if (i < tokens.size()) {
return tokens[i]->getLine();
}
return 1;
}
CharStream* ListTokenSource::getInputStream() {
if (i < tokens.size()) {
return tokens[i]->getInputStream();
} else if (!tokens.empty()) {
return tokens.back()->getInputStream();
}
// no input stream information is available
return nullptr;
}
std::string ListTokenSource::getSourceName() {
if (sourceName != "") {
return sourceName;
}
CharStream* inputStream = getInputStream();
if (inputStream != nullptr) {
return inputStream->getSourceName();
}
return "List";
}
Ref<TokenFactory<CommonToken>> ListTokenSource::getTokenFactory() {
return _factory;
}
void ListTokenSource::InitializeInstanceFields() {
i = 0;
_factory = CommonTokenFactory::DEFAULT;
}

View File

@ -1,94 +0,0 @@
/* 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.
*/
#pragma once
#include "CommonTokenFactory.h"
#include "TokenSource.h"
namespace antlr4 {
/// Provides an implementation of <seealso cref="TokenSource"/> as a wrapper
/// around a list of <seealso cref="Token"/> objects.
///
/// If the final token in the list is an <seealso cref="Token#EOF"/> token, it
/// will be used as the EOF token for every call to <seealso cref="#nextToken"/>
/// after the end of the list is reached. Otherwise, an EOF token will be
/// created.
class ANTLR4CPP_PUBLIC ListTokenSource : public TokenSource {
protected:
// This list will be emptied token by token as we call nextToken().
// Token streams can be used to buffer tokens for a while.
std::vector<std::unique_ptr<Token>> tokens;
private:
/// <summary>
/// The name of the input source. If this value is {@code null}, a call to
/// <seealso cref="#getSourceName"/> should return the source name used to
/// create the the next token in <seealso cref="#tokens"/> (or the previous
/// token if the end of the input has been reached).
/// </summary>
const std::string sourceName;
protected:
/// The index into <seealso cref="#tokens"/> of token to return by the next
/// call to <seealso cref="#nextToken"/>. The end of the input is indicated by
/// this value being greater than or equal to the number of items in <seealso
/// cref="#tokens"/>.
size_t i;
private:
/// This is the backing field for <seealso cref="#getTokenFactory"/> and
/// <seealso cref="setTokenFactory"/>.
Ref<TokenFactory<CommonToken>> _factory = CommonTokenFactory::DEFAULT;
public:
/// Constructs a new <seealso cref="ListTokenSource"/> instance from the
/// specified collection of <seealso cref="Token"/> objects.
///
/// <param name="tokens"> The collection of <seealso cref="Token"/> objects to
/// provide as a <seealso cref="TokenSource"/>. </param> <exception
/// cref="NullPointerException"> if {@code tokens} is {@code null}
/// </exception>
ListTokenSource(std::vector<std::unique_ptr<Token>> tokens);
ListTokenSource(const ListTokenSource& other) = delete;
ListTokenSource& operator=(const ListTokenSource& other) = delete;
/// <summary>
/// Constructs a new <seealso cref="ListTokenSource"/> instance from the
/// specified collection of <seealso cref="Token"/> objects and source name.
/// </summary>
/// <param name="tokens"> The collection of <seealso cref="Token"/> objects to
/// provide as a <seealso cref="TokenSource"/>. </param> <param
/// name="sourceName"> The name of the <seealso cref="TokenSource"/>. If this
/// value is
/// {@code null}, <seealso cref="#getSourceName"/> will attempt to infer the
/// name from the next <seealso cref="Token"/> (or the previous token if the
/// end of the input has been reached).
/// </param>
/// <exception cref="NullPointerException"> if {@code tokens} is {@code null}
/// </exception>
ListTokenSource(std::vector<std::unique_ptr<Token>> tokens_,
const std::string& sourceName_);
virtual size_t getCharPositionInLine() override;
virtual std::unique_ptr<Token> nextToken() override;
virtual size_t getLine() const override;
virtual CharStream* getInputStream() override;
virtual std::string getSourceName() override;
template <typename T1>
void setTokenFactory(TokenFactory<T1>* factory) {
this->_factory = factory;
}
virtual Ref<TokenFactory<CommonToken>> getTokenFactory() override;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,33 +0,0 @@
/* 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.
*/
#include "Parser.h"
#include "NoViableAltException.h"
using namespace antlr4;
NoViableAltException::NoViableAltException(Parser* recognizer)
: NoViableAltException(recognizer, recognizer->getTokenStream(),
recognizer->getCurrentToken(),
recognizer->getCurrentToken(), nullptr,
recognizer->getContext()) {}
NoViableAltException::NoViableAltException(Parser* recognizer,
TokenStream* input,
Token* startToken,
Token* offendingToken,
atn::ATNConfigSet* deadEndConfigs,
ParserRuleContext* ctx)
: RecognitionException("No viable alternative", recognizer, input, ctx,
offendingToken),
_deadEndConfigs(deadEndConfigs),
_startToken(startToken) {}
Token* NoViableAltException::getStartToken() const { return _startToken; }
atn::ATNConfigSet* NoViableAltException::getDeadEndConfigs() const {
return _deadEndConfigs;
}

View File

@ -1,41 +0,0 @@
/* 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.
*/
#pragma once
#include "RecognitionException.h"
#include "Token.h"
#include "atn/ATNConfigSet.h"
namespace antlr4 {
/// Indicates that the parser could not decide which of two or more paths
/// to take based upon the remaining input. It tracks the starting token
/// of the offending input and also knows where the parser was
/// in the various paths when the error. Reported by reportNoViableAlternative()
class ANTLR4CPP_PUBLIC NoViableAltException : public RecognitionException {
public:
NoViableAltException(Parser* recognizer); // LL(1) error
NoViableAltException(Parser* recognizer, TokenStream* input,
Token* startToken, Token* offendingToken,
atn::ATNConfigSet* deadEndConfigs,
ParserRuleContext* ctx);
virtual Token* getStartToken() const;
virtual atn::ATNConfigSet* getDeadEndConfigs() const;
private:
/// Which configurations did we try at input.index() that couldn't match
/// input.LT(1)?
atn::ATNConfigSet* _deadEndConfigs;
/// The token object at the start index; the input stream might
/// not be buffering tokens so get a reference to it. (At the
/// time the error occurred, of course the stream needs to keep a
/// buffer all of the tokens but later we might not have access to those.)
Token* _startToken;
};
} // namespace antlr4

View File

@ -1,637 +0,0 @@
/* 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.
*/
#include "ANTLRErrorListener.h"
#include "DefaultErrorStrategy.h"
#include "Exceptions.h"
#include "Lexer.h"
#include "ParserRuleContext.h"
#include "atn/ATN.h"
#include "atn/ATNDeserializationOptions.h"
#include "atn/ATNDeserializer.h"
#include "atn/ParserATNSimulator.h"
#include "atn/RuleStartState.h"
#include "atn/RuleTransition.h"
#include "dfa/DFA.h"
#include "misc/IntervalSet.h"
#include "tree/ErrorNodeImpl.h"
#include "tree/TerminalNode.h"
#include "tree/pattern/ParseTreePattern.h"
#include "tree/pattern/ParseTreePatternMatcher.h"
#include "atn/ParseInfo.h"
#include "atn/ProfilingATNSimulator.h"
#include "Parser.h"
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;
std::map<std::vector<uint16_t>, atn::ATN> Parser::bypassAltsAtnCache;
Parser::TraceListener::TraceListener(Parser* outerInstance_)
: outerInstance(outerInstance_) {}
Parser::TraceListener::~TraceListener() {}
void Parser::TraceListener::enterEveryRule(ParserRuleContext* ctx) {
std::cout << "enter " << outerInstance->getRuleNames()[ctx->getRuleIndex()]
<< ", LT(1)=" << outerInstance->_input->LT(1)->getText()
<< std::endl;
}
void Parser::TraceListener::visitTerminal(tree::TerminalNode* node) {
std::cout << "consume " << node->getSymbol() << " rule "
<< outerInstance
->getRuleNames()[outerInstance->getContext()->getRuleIndex()]
<< std::endl;
}
void Parser::TraceListener::visitErrorNode(tree::ErrorNode* /*node*/) {}
void Parser::TraceListener::exitEveryRule(ParserRuleContext* ctx) {
std::cout << "exit " << outerInstance->getRuleNames()[ctx->getRuleIndex()]
<< ", LT(1)=" << outerInstance->_input->LT(1)->getText()
<< std::endl;
}
Parser::TrimToSizeListener Parser::TrimToSizeListener::INSTANCE;
Parser::TrimToSizeListener::~TrimToSizeListener() {}
void Parser::TrimToSizeListener::enterEveryRule(ParserRuleContext* /*ctx*/) {}
void Parser::TrimToSizeListener::visitTerminal(tree::TerminalNode* /*node*/) {}
void Parser::TrimToSizeListener::visitErrorNode(tree::ErrorNode* /*node*/) {}
void Parser::TrimToSizeListener::exitEveryRule(ParserRuleContext* ctx) {
ctx->children.shrink_to_fit();
}
Parser::Parser(TokenStream* input) {
InitializeInstanceFields();
setInputStream(input);
}
Parser::~Parser() {
_tracker.reset();
delete _tracer;
}
void Parser::reset() {
if (getInputStream() != nullptr) {
getInputStream()->seek(0);
}
_errHandler->reset(this); // Watch out, this is not shared_ptr.reset().
_matchedEOF = false;
_syntaxErrors = 0;
setTrace(false);
_precedenceStack.clear();
_precedenceStack.push_back(0);
_ctx = nullptr;
_tracker.reset();
atn::ATNSimulator* interpreter = getInterpreter<atn::ParserATNSimulator>();
if (interpreter != nullptr) {
interpreter->reset();
}
}
Token* Parser::match(size_t ttype) {
Token* t = getCurrentToken();
if (t->getType() == ttype) {
if (ttype == EOF) {
_matchedEOF = true;
}
_errHandler->reportMatch(this);
consume();
} else {
t = _errHandler->recoverInline(this);
if (_buildParseTrees && t->getTokenIndex() == INVALID_INDEX) {
// we must have conjured up a new token during single token insertion
// if it's not the current symbol
_ctx->addChild(createErrorNode(t));
}
}
return t;
}
Token* Parser::matchWildcard() {
Token* t = getCurrentToken();
if (t->getType() > 0) {
_errHandler->reportMatch(this);
consume();
} else {
t = _errHandler->recoverInline(this);
if (_buildParseTrees && t->getTokenIndex() == INVALID_INDEX) {
// we must have conjured up a new token during single token insertion
// if it's not the current symbol
_ctx->addChild(createErrorNode(t));
}
}
return t;
}
void Parser::setBuildParseTree(bool buildParseTrees) {
this->_buildParseTrees = buildParseTrees;
}
bool Parser::getBuildParseTree() { return _buildParseTrees; }
void Parser::setTrimParseTree(bool trimParseTrees) {
if (trimParseTrees) {
if (getTrimParseTree()) {
return;
}
addParseListener(&TrimToSizeListener::INSTANCE);
} else {
removeParseListener(&TrimToSizeListener::INSTANCE);
}
}
bool Parser::getTrimParseTree() {
return std::find(getParseListeners().begin(), getParseListeners().end(),
&TrimToSizeListener::INSTANCE) != getParseListeners().end();
}
std::vector<tree::ParseTreeListener*> Parser::getParseListeners() {
return _parseListeners;
}
void Parser::addParseListener(tree::ParseTreeListener* listener) {
if (!listener) {
throw NullPointerException("listener");
}
this->_parseListeners.push_back(listener);
}
void Parser::removeParseListener(tree::ParseTreeListener* listener) {
if (!_parseListeners.empty()) {
auto it =
std::find(_parseListeners.begin(), _parseListeners.end(), listener);
if (it != _parseListeners.end()) {
_parseListeners.erase(it);
}
}
}
void Parser::removeParseListeners() { _parseListeners.clear(); }
void Parser::triggerEnterRuleEvent() {
for (auto listener : _parseListeners) {
listener->enterEveryRule(_ctx);
_ctx->enterRule(listener);
}
}
void Parser::triggerExitRuleEvent() {
// reverse order walk of listeners
for (auto it = _parseListeners.rbegin(); it != _parseListeners.rend(); ++it) {
_ctx->exitRule(*it);
(*it)->exitEveryRule(_ctx);
}
}
size_t Parser::getNumberOfSyntaxErrors() { return _syntaxErrors; }
Ref<TokenFactory<CommonToken>> Parser::getTokenFactory() {
return _input->getTokenSource()->getTokenFactory();
}
const atn::ATN& Parser::getATNWithBypassAlts() {
std::vector<uint16_t> serializedAtn = getSerializedATN();
if (serializedAtn.empty()) {
throw UnsupportedOperationException(
"The current parser does not support an ATN with bypass alternatives.");
}
std::lock_guard<std::mutex> lck(_mutex);
// XXX: using the entire serialized ATN as key into the map is a big resource
// waste.
// How large can that thing become?
if (bypassAltsAtnCache.find(serializedAtn) == bypassAltsAtnCache.end()) {
atn::ATNDeserializationOptions deserializationOptions;
deserializationOptions.setGenerateRuleBypassTransitions(true);
atn::ATNDeserializer deserializer(deserializationOptions);
bypassAltsAtnCache[serializedAtn] = deserializer.deserialize(serializedAtn);
}
return bypassAltsAtnCache[serializedAtn];
}
tree::pattern::ParseTreePattern Parser::compileParseTreePattern(
const std::string& pattern, int patternRuleIndex) {
if (getTokenStream() != nullptr) {
TokenSource* tokenSource = getTokenStream()->getTokenSource();
if (is<Lexer*>(tokenSource)) {
Lexer* lexer = dynamic_cast<Lexer*>(tokenSource);
return compileParseTreePattern(pattern, patternRuleIndex, lexer);
}
}
throw UnsupportedOperationException("Parser can't discover a lexer to use");
}
tree::pattern::ParseTreePattern Parser::compileParseTreePattern(
const std::string& pattern, int patternRuleIndex, Lexer* lexer) {
tree::pattern::ParseTreePatternMatcher m(lexer, this);
return m.compile(pattern, patternRuleIndex);
}
Ref<ANTLRErrorStrategy> Parser::getErrorHandler() { return _errHandler; }
void Parser::setErrorHandler(Ref<ANTLRErrorStrategy> const& handler) {
_errHandler = handler;
}
IntStream* Parser::getInputStream() { return getTokenStream(); }
void Parser::setInputStream(IntStream* input) {
setTokenStream(static_cast<TokenStream*>(input));
}
TokenStream* Parser::getTokenStream() { return _input; }
void Parser::setTokenStream(TokenStream* input) {
_input = nullptr; // Just a reference we don't own.
reset();
_input = input;
}
Token* Parser::getCurrentToken() { return _input->LT(1); }
void Parser::notifyErrorListeners(const std::string& msg) {
notifyErrorListeners(getCurrentToken(), msg, nullptr);
}
void Parser::notifyErrorListeners(Token* offendingToken, const std::string& msg,
std::exception_ptr e) {
_syntaxErrors++;
size_t line = offendingToken->getLine();
size_t charPositionInLine = offendingToken->getCharPositionInLine();
ProxyErrorListener& listener = getErrorListenerDispatch();
listener.syntaxError(this, offendingToken, line, charPositionInLine, msg, e);
}
Token* Parser::consume() {
Token* o = getCurrentToken();
if (o->getType() != EOF) {
getInputStream()->consume();
}
bool hasListener = _parseListeners.size() > 0 && !_parseListeners.empty();
if (_buildParseTrees || hasListener) {
if (_errHandler->inErrorRecoveryMode(this)) {
tree::ErrorNode* node = createErrorNode(o);
_ctx->addChild(node);
if (_parseListeners.size() > 0) {
for (auto listener : _parseListeners) {
listener->visitErrorNode(node);
}
}
} else {
tree::TerminalNode* node = _ctx->addChild(createTerminalNode(o));
if (_parseListeners.size() > 0) {
for (auto listener : _parseListeners) {
listener->visitTerminal(node);
}
}
}
}
return o;
}
void Parser::addContextToParseTree() {
// Add current context to parent if we have a parent.
if (_ctx->parent == nullptr) return;
ParserRuleContext* parent = dynamic_cast<ParserRuleContext*>(_ctx->parent);
parent->addChild(_ctx);
}
void Parser::enterRule(ParserRuleContext* localctx, size_t state,
size_t /*ruleIndex*/) {
setState(state);
_ctx = localctx;
_ctx->start = _input->LT(1);
if (_buildParseTrees) {
addContextToParseTree();
}
if (_parseListeners.size() > 0) {
triggerEnterRuleEvent();
}
}
void Parser::exitRule() {
if (_matchedEOF) {
// if we have matched EOF, it cannot consume past EOF so we use LT(1) here
_ctx->stop = _input->LT(1); // LT(1) will be end of file
} else {
_ctx->stop = _input->LT(-1); // stop node is what we just matched
}
// trigger event on ctx, before it reverts to parent
if (_parseListeners.size() > 0) {
triggerExitRuleEvent();
}
setState(_ctx->invokingState);
_ctx = dynamic_cast<ParserRuleContext*>(_ctx->parent);
}
void Parser::enterOuterAlt(ParserRuleContext* localctx, size_t altNum) {
localctx->setAltNumber(altNum);
// if we have new localctx, make sure we replace existing ctx
// that is previous child of parse tree
if (_buildParseTrees && _ctx != localctx) {
if (_ctx->parent != nullptr) {
ParserRuleContext* parent =
dynamic_cast<ParserRuleContext*>(_ctx->parent);
parent->removeLastChild();
parent->addChild(localctx);
}
}
_ctx = localctx;
}
int Parser::getPrecedence() const {
if (_precedenceStack.empty()) {
return -1;
}
return _precedenceStack.back();
}
void Parser::enterRecursionRule(ParserRuleContext* localctx, size_t ruleIndex) {
enterRecursionRule(localctx,
getATN().ruleToStartState[ruleIndex]->stateNumber,
ruleIndex, 0);
}
void Parser::enterRecursionRule(ParserRuleContext* localctx, size_t state,
size_t /*ruleIndex*/, int precedence) {
setState(state);
_precedenceStack.push_back(precedence);
_ctx = localctx;
_ctx->start = _input->LT(1);
if (!_parseListeners.empty()) {
triggerEnterRuleEvent(); // simulates rule entry for left-recursive rules
}
}
void Parser::pushNewRecursionContext(ParserRuleContext* localctx, size_t state,
size_t /*ruleIndex*/) {
ParserRuleContext* previous = _ctx;
previous->parent = localctx;
previous->invokingState = state;
previous->stop = _input->LT(-1);
_ctx = localctx;
_ctx->start = previous->start;
if (_buildParseTrees) {
_ctx->addChild(previous);
}
if (_parseListeners.size() > 0) {
triggerEnterRuleEvent(); // simulates rule entry for left-recursive rules
}
}
void Parser::unrollRecursionContexts(ParserRuleContext* parentctx) {
_precedenceStack.pop_back();
_ctx->stop = _input->LT(-1);
ParserRuleContext* retctx = _ctx; // save current ctx (return value)
// unroll so ctx is as it was before call to recursive method
if (_parseListeners.size() > 0) {
while (_ctx != parentctx) {
triggerExitRuleEvent();
_ctx = dynamic_cast<ParserRuleContext*>(_ctx->parent);
}
} else {
_ctx = parentctx;
}
// hook into tree
retctx->parent = parentctx;
if (_buildParseTrees && parentctx != nullptr) {
// add return ctx into invoking rule's tree
parentctx->addChild(retctx);
}
}
ParserRuleContext* Parser::getInvokingContext(size_t ruleIndex) {
ParserRuleContext* p = _ctx;
while (p) {
if (p->getRuleIndex() == ruleIndex) {
return p;
}
if (p->parent == nullptr) break;
p = dynamic_cast<ParserRuleContext*>(p->parent);
}
return nullptr;
}
ParserRuleContext* Parser::getContext() { return _ctx; }
void Parser::setContext(ParserRuleContext* ctx) { _ctx = ctx; }
bool Parser::precpred(RuleContext* /*localctx*/, int precedence) {
return precedence >= _precedenceStack.back();
}
bool Parser::inContext(const std::string& /*context*/) {
// TO_DO: useful in parser?
return false;
}
bool Parser::isExpectedToken(size_t symbol) {
const atn::ATN& atn = getInterpreter<atn::ParserATNSimulator>()->atn;
ParserRuleContext* ctx = _ctx;
atn::ATNState* s = atn.states[getState()];
misc::IntervalSet following = atn.nextTokens(s);
if (following.contains(symbol)) {
return true;
}
if (!following.contains(Token::EPSILON)) {
return false;
}
while (ctx && ctx->invokingState != ATNState::INVALID_STATE_NUMBER &&
following.contains(Token::EPSILON)) {
atn::ATNState* invokingState = atn.states[ctx->invokingState];
atn::RuleTransition* rt =
static_cast<atn::RuleTransition*>(invokingState->transitions[0]);
following = atn.nextTokens(rt->followState);
if (following.contains(symbol)) {
return true;
}
ctx = dynamic_cast<ParserRuleContext*>(ctx->parent);
}
if (following.contains(Token::EPSILON) && symbol == EOF) {
return true;
}
return false;
}
bool Parser::isMatchedEOF() const { return _matchedEOF; }
misc::IntervalSet Parser::getExpectedTokens() {
return getATN().getExpectedTokens(getState(), getContext());
}
misc::IntervalSet Parser::getExpectedTokensWithinCurrentRule() {
const atn::ATN& atn = getInterpreter<atn::ParserATNSimulator>()->atn;
atn::ATNState* s = atn.states[getState()];
return atn.nextTokens(s);
}
size_t Parser::getRuleIndex(const std::string& ruleName) {
const std::map<std::string, size_t>& m = getRuleIndexMap();
auto iterator = m.find(ruleName);
if (iterator == m.end()) {
return INVALID_INDEX;
}
return iterator->second;
}
ParserRuleContext* Parser::getRuleContext() { return _ctx; }
std::vector<std::string> Parser::getRuleInvocationStack() {
return getRuleInvocationStack(_ctx);
}
std::vector<std::string> Parser::getRuleInvocationStack(RuleContext* p) {
std::vector<std::string> const& ruleNames = getRuleNames();
std::vector<std::string> stack;
RuleContext* run = p;
while (run != nullptr) {
// compute what follows who invoked us
size_t ruleIndex = run->getRuleIndex();
if (ruleIndex == INVALID_INDEX) {
stack.push_back("n/a");
} else {
stack.push_back(ruleNames[ruleIndex]);
}
if (p->parent == nullptr) break;
run = dynamic_cast<RuleContext*>(run->parent);
}
return stack;
}
std::vector<std::string> Parser::getDFAStrings() {
atn::ParserATNSimulator* simulator =
getInterpreter<atn::ParserATNSimulator>();
if (!simulator->decisionToDFA.empty()) {
std::lock_guard<std::mutex> lck(_mutex);
std::vector<std::string> s;
for (size_t d = 0; d < simulator->decisionToDFA.size(); d++) {
dfa::DFA& dfa = simulator->decisionToDFA[d];
s.push_back(dfa.toString(getVocabulary()));
}
return s;
}
return std::vector<std::string>();
}
void Parser::dumpDFA() {
atn::ParserATNSimulator* simulator =
getInterpreter<atn::ParserATNSimulator>();
if (!simulator->decisionToDFA.empty()) {
std::lock_guard<std::mutex> lck(_mutex);
bool seenOne = false;
for (size_t d = 0; d < simulator->decisionToDFA.size(); d++) {
dfa::DFA& dfa = simulator->decisionToDFA[d];
if (!dfa.states.empty()) {
if (seenOne) {
std::cout << std::endl;
}
std::cout << "Decision " << dfa.decision << ":" << std::endl;
std::cout << dfa.toString(getVocabulary());
seenOne = true;
}
}
}
}
std::string Parser::getSourceName() { return _input->getSourceName(); }
atn::ParseInfo Parser::getParseInfo() const {
atn::ProfilingATNSimulator* interp =
getInterpreter<atn::ProfilingATNSimulator>();
return atn::ParseInfo(interp);
}
void Parser::setProfile(bool profile) {
atn::ParserATNSimulator* interp =
getInterpreter<atn::ProfilingATNSimulator>();
atn::PredictionMode saveMode =
interp != nullptr ? interp->getPredictionMode() : atn::PredictionMode::LL;
if (profile) {
if (!is<atn::ProfilingATNSimulator*>(interp)) {
setInterpreter(
new atn::ProfilingATNSimulator(this)); /* mem-check: replacing
existing interpreter which
gets deleted. */
}
} else if (is<atn::ProfilingATNSimulator*>(interp)) {
/* mem-check: replacing existing interpreter which gets deleted. */
atn::ParserATNSimulator* sim = new atn::ParserATNSimulator(
this, getATN(), interp->decisionToDFA, interp->getSharedContextCache());
setInterpreter(sim);
}
getInterpreter<atn::ParserATNSimulator>()->setPredictionMode(saveMode);
}
void Parser::setTrace(bool trace) {
if (!trace) {
if (_tracer) removeParseListener(_tracer);
delete _tracer;
_tracer = nullptr;
} else {
if (_tracer)
removeParseListener(
_tracer); // Just in case this is triggered multiple times.
_tracer = new TraceListener(this);
addParseListener(_tracer);
}
}
bool Parser::isTrace() const { return _tracer != nullptr; }
tree::TerminalNode* Parser::createTerminalNode(Token* t) {
return _tracker.createInstance<tree::TerminalNodeImpl>(t);
}
tree::ErrorNode* Parser::createErrorNode(Token* t) {
return _tracker.createInstance<tree::ErrorNodeImpl>(t);
}
void Parser::InitializeInstanceFields() {
_errHandler = std::make_shared<DefaultErrorStrategy>();
_precedenceStack.clear();
_precedenceStack.push_back(0);
_buildParseTrees = true;
_syntaxErrors = 0;
_matchedEOF = false;
_input = nullptr;
_tracer = nullptr;
_ctx = nullptr;
}

View File

@ -1,489 +0,0 @@
/* 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.
*/
#pragma once
#include "Recognizer.h"
#include "TokenSource.h"
#include "TokenStream.h"
#include "misc/Interval.h"
#include "tree/ParseTree.h"
#include "tree/ParseTreeListener.h"
namespace antlr4 {
/// This is all the parsing support code essentially; most of it is error
/// recovery stuff.
class ANTLR4CPP_PUBLIC Parser : public Recognizer {
public:
class TraceListener : public tree::ParseTreeListener {
public:
TraceListener(Parser* outerInstance);
virtual ~TraceListener();
virtual void enterEveryRule(ParserRuleContext* ctx) override;
virtual void visitTerminal(tree::TerminalNode* node) override;
virtual void visitErrorNode(tree::ErrorNode* node) override;
virtual void exitEveryRule(ParserRuleContext* ctx) override;
private:
Parser* const outerInstance;
};
class TrimToSizeListener : public tree::ParseTreeListener {
public:
static TrimToSizeListener INSTANCE;
virtual ~TrimToSizeListener();
virtual void enterEveryRule(ParserRuleContext* ctx) override;
virtual void visitTerminal(tree::TerminalNode* node) override;
virtual void visitErrorNode(tree::ErrorNode* node) override;
virtual void exitEveryRule(ParserRuleContext* ctx) override;
};
Parser(TokenStream* input);
virtual ~Parser();
/// reset the parser's state
virtual void reset();
/// <summary>
/// Match current input symbol against {@code ttype}. If the symbol type
/// matches, <seealso cref="ANTLRErrorStrategy#reportMatch"/> and <seealso
/// cref="#consume"/> are called to complete the match process.
///
/// If the symbol type does not match,
/// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is called on the
/// current error strategy to attempt recovery. If <seealso
/// cref="#getBuildParseTree"/> is
/// {@code true} and the token index of the symbol returned by
/// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is -1, the symbol is
/// added to the parse tree by calling {@link
/// #createErrorNode(ParserRuleContext, Token)} then
/// {@link ParserRuleContext#addErrorNode(ErrorNode)}.
/// </summary>
/// <param name="ttype"> the token type to match </param>
/// <returns> the matched symbol </returns>
/// <exception cref="RecognitionException"> if the current input symbol did
/// not match
/// {@code ttype} and the error strategy could not recover from the
/// mismatched symbol </exception>
virtual Token* match(size_t ttype);
/// <summary>
/// Match current input symbol as a wildcard. If the symbol type matches
/// (i.e. has a value greater than 0), <seealso
/// cref="ANTLRErrorStrategy#reportMatch"/> and <seealso cref="#consume"/> are
/// called to complete the match process. <p/> If the symbol type does not
/// match, <seealso cref="ANTLRErrorStrategy#recoverInline"/> is called on the
/// current error strategy to attempt recovery. If <seealso
/// cref="#getBuildParseTree"/> is
/// {@code true} and the token index of the symbol returned by
/// <seealso cref="ANTLRErrorStrategy#recoverInline"/> is -1, the symbol is
/// added to the parse tree by calling <seealso
/// cref="ParserRuleContext#addErrorNode"/>.
/// </summary>
/// <returns> the matched symbol </returns>
/// <exception cref="RecognitionException"> if the current input symbol did
/// not match a wildcard and the error strategy could not recover from the
/// mismatched symbol </exception>
virtual Token* matchWildcard();
/// <summary>
/// Track the <seealso cref="ParserRuleContext"/> objects during the parse and
/// hook them up using the <seealso cref="ParserRuleContext#children"/> list
/// so that it forms a parse tree. The <seealso cref="ParserRuleContext"/>
/// returned from the start rule represents the root of the parse tree. <p/>
/// Note that if we are not building parse trees, rule contexts only point
/// upwards. When a rule exits, it returns the context but that gets garbage
/// collected if nobody holds a reference. It points upwards but nobody
/// points at it.
/// <p/>
/// When we build parse trees, we are adding all of these contexts to
/// <seealso cref="ParserRuleContext#children"/> list. Contexts are then not
/// candidates for garbage collection.
/// </summary>
virtual void setBuildParseTree(bool buildParseTrees);
/// <summary>
/// Gets whether or not a complete parse tree will be constructed while
/// parsing. This property is {@code true} for a newly constructed parser.
/// </summary>
/// <returns> {@code true} if a complete parse tree will be constructed while
/// parsing, otherwise {@code false} </returns>
virtual bool getBuildParseTree();
/// <summary>
/// Trim the internal lists of the parse tree during parsing to conserve
/// memory. This property is set to {@code false} by default for a newly
/// constructed parser.
/// </summary>
/// <param name="trimParseTrees"> {@code true} to trim the capacity of the
/// <seealso cref="ParserRuleContext#children"/> list to its size after a rule
/// is parsed. </param>
virtual void setTrimParseTree(bool trimParseTrees);
/// <returns> {@code true} if the <seealso cref="ParserRuleContext#children"/>
/// list is trimmed using the default <seealso
/// cref="Parser.TrimToSizeListener"/> during the parse process. </returns>
virtual bool getTrimParseTree();
virtual std::vector<tree::ParseTreeListener*> getParseListeners();
/// <summary>
/// Registers {@code listener} to receive events during the parsing process.
/// <p/>
/// To support output-preserving grammar transformations (including but not
/// limited to left-recursion removal, automated left-factoring, and
/// optimized code generation), calls to listener methods during the parse
/// may differ substantially from calls made by
/// <seealso cref="ParseTreeWalker#DEFAULT"/> used after the parse is
/// complete. In particular, rule entry and exit events may occur in a
/// different order during the parse than after the parser. In addition, calls
/// to certain rule entry methods may be omitted. <p/> With the following
/// specific exceptions, calls to listener events are <em>deterministic</em>,
/// i.e. for identical input the calls to listener methods will be the same.
///
/// <ul>
/// <li>Alterations to the grammar used to generate code may change the
/// behavior of the listener calls.</li>
/// <li>Alterations to the command line options passed to ANTLR 4 when
/// generating the parser may change the behavior of the listener calls.</li>
/// <li>Changing the version of the ANTLR Tool used to generate the parser
/// may change the behavior of the listener calls.</li>
/// </ul>
/// </summary>
/// <param name="listener"> the listener to add
/// </param>
/// <exception cref="NullPointerException"> if {@code} listener is {@code
/// null} </exception>
virtual void addParseListener(tree::ParseTreeListener* listener);
/// <summary>
/// Remove {@code listener} from the list of parse listeners.
/// <p/>
/// If {@code listener} is {@code null} or has not been added as a parse
/// listener, this method does nothing.
/// </summary>
/// <seealso cref= #addParseListener
/// </seealso>
/// <param name="listener"> the listener to remove </param>
virtual void removeParseListener(tree::ParseTreeListener* listener);
/// <summary>
/// Remove all parse listeners.
/// </summary>
/// <seealso cref= #addParseListener </seealso>
virtual void removeParseListeners();
/// <summary>
/// Notify any parse listeners of an enter rule event.
/// </summary>
/// <seealso cref= #addParseListener </seealso>
virtual void triggerEnterRuleEvent();
/// <summary>
/// Notify any parse listeners of an exit rule event.
/// </summary>
/// <seealso cref= #addParseListener </seealso>
virtual void triggerExitRuleEvent();
/// <summary>
/// Gets the number of syntax errors reported during parsing. This value is
/// incremented each time <seealso cref="#notifyErrorListeners"/> is called.
/// </summary>
/// <seealso cref= #notifyErrorListeners </seealso>
virtual size_t getNumberOfSyntaxErrors();
virtual Ref<TokenFactory<CommonToken>> getTokenFactory() override;
/// <summary>
/// Tell our token source and error strategy about a new way to create tokens.
/// </summary>
template <typename T1>
void setTokenFactory(TokenFactory<T1>* factory) {
_input->getTokenSource()->setTokenFactory(factory);
}
/// The ATN with bypass alternatives is expensive to create so we create it
/// lazily. The ATN is owned by us.
virtual const atn::ATN& getATNWithBypassAlts();
/// <summary>
/// The preferred method of getting a tree pattern. For example, here's a
/// sample use:
///
/// <pre>
/// ParseTree t = parser.expr();
/// ParseTreePattern p = parser.compileParseTreePattern("<ID>+0",
/// MyParser.RULE_expr); ParseTreeMatch m = p.match(t); String id =
/// m.get("ID");
/// </pre>
/// </summary>
virtual tree::pattern::ParseTreePattern compileParseTreePattern(
const std::string& pattern, int patternRuleIndex);
/// <summary>
/// The same as <seealso cref="#compileParseTreePattern(String, int)"/> but
/// specify a <seealso cref="Lexer"/> rather than trying to deduce it from
/// this parser.
/// </summary>
virtual tree::pattern::ParseTreePattern compileParseTreePattern(
const std::string& pattern, int patternRuleIndex, Lexer* lexer);
virtual Ref<ANTLRErrorStrategy> getErrorHandler();
virtual void setErrorHandler(Ref<ANTLRErrorStrategy> const& handler);
virtual IntStream* getInputStream() override;
void setInputStream(IntStream* input) override;
virtual TokenStream* getTokenStream();
/// Set the token stream and reset the parser.
virtual void setTokenStream(TokenStream* input);
/// <summary>
/// Match needs to return the current input symbol, which gets put
/// into the label for the associated token ref; e.g., x=ID.
/// </summary>
virtual Token* getCurrentToken();
void notifyErrorListeners(const std::string& msg);
virtual void notifyErrorListeners(Token* offendingToken,
const std::string& msg,
std::exception_ptr e);
/// Consume and return the <seealso cref="#getCurrentToken current symbol"/>.
/// <p/>
/// E.g., given the following input with {@code A} being the current
/// lookahead symbol, this function moves the cursor to {@code B} and returns
/// {@code A}.
///
/// <pre>
/// A B
/// ^
/// </pre>
///
/// If the parser is not in error recovery mode, the consumed symbol is added
/// to the parse tree using <seealso
/// cref="ParserRuleContext#addChild(TerminalNode)"/>, and <seealso
/// cref="ParseTreeListener#visitTerminal"/> is called on any parse listeners.
/// If the parser <em>is</em> in error recovery mode, the consumed symbol is
/// added to the parse tree using {@link #createErrorNode(ParserRuleContext,
/// Token)} then
/// {@link ParserRuleContext#addErrorNode(ErrorNode)} and
/// <seealso cref="ParseTreeListener#visitErrorNode"/> is called on any parse
/// listeners.
virtual Token* consume();
/// Always called by generated parsers upon entry to a rule. Access field
/// <seealso cref="#_ctx"/> get the current context.
virtual void enterRule(ParserRuleContext* localctx, size_t state,
size_t ruleIndex);
virtual void exitRule();
virtual void enterOuterAlt(ParserRuleContext* localctx, size_t altNum);
/**
* Get the precedence level for the top-most precedence rule.
*
* @return The precedence level for the top-most precedence rule, or -1 if
* the parser context is not nested within a precedence rule.
*/
int getPrecedence() const;
/// @deprecated Use
/// <seealso cref="#enterRecursionRule(ParserRuleContext, int, int, int)"/>
/// instead.
virtual void enterRecursionRule(ParserRuleContext* localctx,
size_t ruleIndex);
virtual void enterRecursionRule(ParserRuleContext* localctx, size_t state,
size_t ruleIndex, int precedence);
/** Like {@link #enterRule} but for recursive rules.
* Make the current context the child of the incoming localctx.
*/
virtual void pushNewRecursionContext(ParserRuleContext* localctx,
size_t state, size_t ruleIndex);
virtual void unrollRecursionContexts(ParserRuleContext* parentctx);
virtual ParserRuleContext* getInvokingContext(size_t ruleIndex);
virtual ParserRuleContext* getContext();
virtual void setContext(ParserRuleContext* ctx);
virtual bool precpred(RuleContext* localctx, int precedence) override;
virtual bool inContext(const std::string& context);
/// <summary>
/// Checks whether or not {@code symbol} can follow the current state in the
/// ATN. The behavior of this method is equivalent to the following, but is
/// implemented such that the complete context-sensitive follow set does not
/// need to be explicitly constructed.
///
/// <pre>
/// return getExpectedTokens().contains(symbol);
/// </pre>
/// </summary>
/// <param name="symbol"> the symbol type to check </param>
/// <returns> {@code true} if {@code symbol} can follow the current state in
/// the ATN, otherwise {@code false}. </returns>
virtual bool isExpectedToken(size_t symbol);
bool isMatchedEOF() const;
/// <summary>
/// Computes the set of input symbols which could follow the current parser
/// state and context, as given by <seealso cref="#getState"/> and <seealso
/// cref="#getContext"/>, respectively.
/// </summary>
/// <seealso cref= ATN#getExpectedTokens(int, RuleContext) </seealso>
virtual misc::IntervalSet getExpectedTokens();
virtual misc::IntervalSet getExpectedTokensWithinCurrentRule();
/// Get a rule's index (i.e., {@code RULE_ruleName} field) or INVALID_INDEX if
/// not found.
virtual size_t getRuleIndex(const std::string& ruleName);
virtual ParserRuleContext* getRuleContext();
/// <summary>
/// Return List&lt;String&gt; of the rule names in your parser instance
/// leading up to a call to the current rule. You could override if
/// you want more details such as the file/line info of where
/// in the ATN a rule is invoked.
///
/// This is very useful for error messages.
/// </summary>
virtual std::vector<std::string> getRuleInvocationStack();
virtual std::vector<std::string> getRuleInvocationStack(RuleContext* p);
/// <summary>
/// For debugging and other purposes. </summary>
virtual std::vector<std::string> getDFAStrings();
/// <summary>
/// For debugging and other purposes. </summary>
virtual void dumpDFA();
virtual std::string getSourceName();
atn::ParseInfo getParseInfo() const;
/**
* @since 4.3
*/
void setProfile(bool profile);
/// <summary>
/// During a parse is sometimes useful to listen in on the rule entry and exit
/// events as well as token matches. This is for quick and dirty debugging.
/// </summary>
virtual void setTrace(bool trace);
/**
* Gets whether a {@link TraceListener} is registered as a parse listener
* for the parser.
*
* @see #setTrace(boolean)
*/
bool isTrace() const;
tree::ParseTreeTracker& getTreeTracker() { return _tracker; }
/** How to create a token leaf node associated with a parent.
* Typically, the terminal node to create is not a function of the parent
* but this method must still set the parent pointer of the terminal node
* returned. I would prefer having {@link
* ParserRuleContext#addAnyChild(ParseTree)} set the parent pointer, but the
* parent pointer is implementation dependent and currently there is no
* setParent() in {@link TerminalNode} (and can't add method in Java 1.7
* without breaking backward compatibility).
*
* @since 4.7
*/
tree::TerminalNode* createTerminalNode(Token* t);
/** How to create an error node, given a token, associated with a parent.
* Typically, the error node to create is not a function of the parent
* but this method must still set the parent pointer of the terminal node
* returned. I would prefer having {@link
* ParserRuleContext#addAnyChild(ParseTree)} set the parent pointer, but the
* parent pointer is implementation dependent and currently there is no
* setParent() in {@link ErrorNode} (and can't add method in Java 1.7 without
* breaking backward compatibility).
*
* @since 4.7
*/
tree::ErrorNode* createErrorNode(Token* t);
protected:
/// The ParserRuleContext object for the currently executing rule.
/// This is always non-null during the parsing process.
// ml: this is one of the contexts tracked in _allocatedContexts.
ParserRuleContext* _ctx;
/// The error handling strategy for the parser. The default is
/// DefaultErrorStrategy. See also getErrorHandler.
Ref<ANTLRErrorStrategy> _errHandler;
/// <summary>
/// The input stream.
/// </summary>
/// <seealso cref= #getInputStream </seealso>
/// <seealso cref= #setInputStream </seealso>
TokenStream* _input;
std::vector<int> _precedenceStack;
/// <summary>
/// Specifies whether or not the parser should construct a parse tree during
/// the parsing process. The default value is {@code true}.
/// </summary>
/// <seealso cref= #getBuildParseTree </seealso>
/// <seealso cref= #setBuildParseTree </seealso>
bool _buildParseTrees;
/// The list of <seealso cref="ParseTreeListener"/> listeners registered to
/// receive events during the parse. <seealso cref= #addParseListener
/// </seealso>
std::vector<tree::ParseTreeListener*> _parseListeners;
/// <summary>
/// The number of syntax errors reported during parsing. This value is
/// incremented each time <seealso cref="#notifyErrorListeners"/> is called.
/// </summary>
size_t _syntaxErrors;
/** Indicates parser has match()ed EOF token. See {@link #exitRule()}. */
bool _matchedEOF;
virtual void addContextToParseTree();
// All rule contexts created during a parse run. This is cleared when calling
// reset().
tree::ParseTreeTracker _tracker;
private:
/// This field maps from the serialized ATN string to the deserialized
/// <seealso cref="ATN"/> with bypass alternatives.
///
/// <seealso cref= ATNDeserializationOptions#isGenerateRuleBypassTransitions()
/// </seealso>
static std::map<std::vector<uint16_t>, atn::ATN> bypassAltsAtnCache;
/// When setTrace(true) is called, a reference to the
/// TraceListener is stored here so it can be easily removed in a
/// later call to setTrace(false). The listener itself is
/// implemented as a parser listener so this field is not directly used by
/// other parser methods.
TraceListener* _tracer;
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,340 +0,0 @@
/* 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.
*/
#include "ANTLRErrorStrategy.h"
#include "CommonToken.h"
#include "FailedPredicateException.h"
#include "InputMismatchException.h"
#include "InterpreterRuleContext.h"
#include "Lexer.h"
#include "Token.h"
#include "Vocabulary.h"
#include "atn/ATN.h"
#include "atn/ActionTransition.h"
#include "atn/AtomTransition.h"
#include "atn/LoopEndState.h"
#include "atn/ParserATNSimulator.h"
#include "atn/PrecedencePredicateTransition.h"
#include "atn/PredicateTransition.h"
#include "atn/RuleStartState.h"
#include "atn/RuleStopState.h"
#include "atn/RuleTransition.h"
#include "atn/StarLoopEntryState.h"
#include "dfa/DFA.h"
#include "tree/ErrorNode.h"
#include "support/CPPUtils.h"
#include "ParserInterpreter.h"
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlr4::misc;
using namespace antlrcpp;
ParserInterpreter::ParserInterpreter(const std::string& grammarFileName,
const std::vector<std::string>& tokenNames,
const std::vector<std::string>& ruleNames,
const atn::ATN& atn, TokenStream* input)
: ParserInterpreter(grammarFileName,
dfa::Vocabulary::fromTokenNames(tokenNames), ruleNames,
atn, input) {}
ParserInterpreter::ParserInterpreter(const std::string& grammarFileName,
const dfa::Vocabulary& vocabulary,
const std::vector<std::string>& ruleNames,
const atn::ATN& atn, TokenStream* input)
: Parser(input),
_grammarFileName(grammarFileName),
_atn(atn),
_ruleNames(ruleNames),
_vocabulary(vocabulary) {
for (size_t i = 0; i < atn.maxTokenType; ++i) {
_tokenNames.push_back(vocabulary.getDisplayName(i));
}
// init decision DFA
for (size_t i = 0; i < atn.getNumberOfDecisions(); ++i) {
atn::DecisionState* decisionState = atn.getDecisionState(i);
_decisionToDFA.push_back(dfa::DFA(decisionState, i));
}
// get atn simulator that knows how to do predictions
_interpreter = new atn::ParserATNSimulator(
this, atn, _decisionToDFA,
_sharedContextCache); /* mem-check: deleted in d-tor */
}
ParserInterpreter::~ParserInterpreter() { delete _interpreter; }
void ParserInterpreter::reset() {
Parser::reset();
_overrideDecisionReached = false;
_overrideDecisionRoot = nullptr;
}
const atn::ATN& ParserInterpreter::getATN() const { return _atn; }
const std::vector<std::string>& ParserInterpreter::getTokenNames() const {
return _tokenNames;
}
const dfa::Vocabulary& ParserInterpreter::getVocabulary() const {
return _vocabulary;
}
const std::vector<std::string>& ParserInterpreter::getRuleNames() const {
return _ruleNames;
}
std::string ParserInterpreter::getGrammarFileName() const {
return _grammarFileName;
}
ParserRuleContext* ParserInterpreter::parse(size_t startRuleIndex) {
atn::RuleStartState* startRuleStartState =
_atn.ruleToStartState[startRuleIndex];
_rootContext = createInterpreterRuleContext(
nullptr, atn::ATNState::INVALID_STATE_NUMBER, startRuleIndex);
if (startRuleStartState->isLeftRecursiveRule) {
enterRecursionRule(_rootContext, startRuleStartState->stateNumber,
startRuleIndex, 0);
} else {
enterRule(_rootContext, startRuleStartState->stateNumber, startRuleIndex);
}
while (true) {
atn::ATNState* p = getATNState();
switch (p->getStateType()) {
case atn::ATNState::RULE_STOP:
// pop; return from rule
if (_ctx->isEmpty()) {
if (startRuleStartState->isLeftRecursiveRule) {
ParserRuleContext* result = _ctx;
auto parentContext = _parentContextStack.top();
_parentContextStack.pop();
unrollRecursionContexts(parentContext.first);
return result;
} else {
exitRule();
return _rootContext;
}
}
visitRuleStopState(p);
break;
default:
try {
visitState(p);
} catch (RecognitionException& e) {
setState(_atn.ruleToStopState[p->ruleIndex]->stateNumber);
getErrorHandler()->reportError(this, e);
getContext()->exception = std::current_exception();
recover(e);
}
break;
}
}
}
void ParserInterpreter::enterRecursionRule(ParserRuleContext* localctx,
size_t state, size_t ruleIndex,
int precedence) {
_parentContextStack.push({_ctx, localctx->invokingState});
Parser::enterRecursionRule(localctx, state, ruleIndex, precedence);
}
void ParserInterpreter::addDecisionOverride(int decision, int tokenIndex,
int forcedAlt) {
_overrideDecision = decision;
_overrideDecisionInputIndex = tokenIndex;
_overrideDecisionAlt = forcedAlt;
}
Ref<InterpreterRuleContext> ParserInterpreter::getOverrideDecisionRoot() const {
return _overrideDecisionRoot;
}
InterpreterRuleContext* ParserInterpreter::getRootContext() {
return _rootContext;
}
atn::ATNState* ParserInterpreter::getATNState() {
return _atn.states[getState()];
}
void ParserInterpreter::visitState(atn::ATNState* p) {
size_t predictedAlt = 1;
if (is<DecisionState*>(p)) {
predictedAlt = visitDecisionState(dynamic_cast<DecisionState*>(p));
}
atn::Transition* transition = p->transitions[predictedAlt - 1];
switch (transition->getSerializationType()) {
case atn::Transition::EPSILON:
if (p->getStateType() == ATNState::STAR_LOOP_ENTRY &&
(dynamic_cast<StarLoopEntryState*>(p))->isPrecedenceDecision &&
!is<LoopEndState*>(transition->target)) {
// We are at the start of a left recursive rule's (...)* loop
// and we're not taking the exit branch of loop.
InterpreterRuleContext* localctx = createInterpreterRuleContext(
_parentContextStack.top().first, _parentContextStack.top().second,
static_cast<int>(_ctx->getRuleIndex()));
pushNewRecursionContext(
localctx, _atn.ruleToStartState[p->ruleIndex]->stateNumber,
static_cast<int>(_ctx->getRuleIndex()));
}
break;
case atn::Transition::ATOM:
match(static_cast<int>(
static_cast<atn::AtomTransition*>(transition)->_label));
break;
case atn::Transition::RANGE:
case atn::Transition::SET:
case atn::Transition::NOT_SET:
if (!transition->matches(static_cast<int>(_input->LA(1)),
Token::MIN_USER_TOKEN_TYPE,
Lexer::MAX_CHAR_VALUE)) {
recoverInline();
}
matchWildcard();
break;
case atn::Transition::WILDCARD:
matchWildcard();
break;
case atn::Transition::RULE: {
atn::RuleStartState* ruleStartState =
static_cast<atn::RuleStartState*>(transition->target);
size_t ruleIndex = ruleStartState->ruleIndex;
InterpreterRuleContext* newctx =
createInterpreterRuleContext(_ctx, p->stateNumber, ruleIndex);
if (ruleStartState->isLeftRecursiveRule) {
enterRecursionRule(
newctx, ruleStartState->stateNumber, ruleIndex,
static_cast<atn::RuleTransition*>(transition)->precedence);
} else {
enterRule(newctx, transition->target->stateNumber, ruleIndex);
}
} break;
case atn::Transition::PREDICATE: {
atn::PredicateTransition* predicateTransition =
static_cast<atn::PredicateTransition*>(transition);
if (!sempred(_ctx, predicateTransition->ruleIndex,
predicateTransition->predIndex)) {
throw FailedPredicateException(this);
}
} break;
case atn::Transition::ACTION: {
atn::ActionTransition* actionTransition =
static_cast<atn::ActionTransition*>(transition);
action(_ctx, actionTransition->ruleIndex, actionTransition->actionIndex);
} break;
case atn::Transition::PRECEDENCE: {
if (!precpred(_ctx,
static_cast<atn::PrecedencePredicateTransition*>(transition)
->precedence)) {
throw FailedPredicateException(
this,
"precpred(_ctx, " +
std::to_string(
static_cast<atn::PrecedencePredicateTransition*>(transition)
->precedence) +
")");
}
} break;
default:
throw UnsupportedOperationException("Unrecognized ATN transition type.");
}
setState(transition->target->stateNumber);
}
size_t ParserInterpreter::visitDecisionState(DecisionState* p) {
size_t predictedAlt = 1;
if (p->transitions.size() > 1) {
getErrorHandler()->sync(this);
int decision = p->decision;
if (decision == _overrideDecision &&
_input->index() == _overrideDecisionInputIndex &&
!_overrideDecisionReached) {
predictedAlt = _overrideDecisionAlt;
_overrideDecisionReached = true;
} else {
predictedAlt = getInterpreter<ParserATNSimulator>()->adaptivePredict(
_input, decision, _ctx);
}
}
return predictedAlt;
}
InterpreterRuleContext* ParserInterpreter::createInterpreterRuleContext(
ParserRuleContext* parent, size_t invokingStateNumber, size_t ruleIndex) {
return _tracker.createInstance<InterpreterRuleContext>(
parent, invokingStateNumber, ruleIndex);
}
void ParserInterpreter::visitRuleStopState(atn::ATNState* p) {
atn::RuleStartState* ruleStartState = _atn.ruleToStartState[p->ruleIndex];
if (ruleStartState->isLeftRecursiveRule) {
std::pair<ParserRuleContext*, size_t> parentContext =
_parentContextStack.top();
_parentContextStack.pop();
unrollRecursionContexts(parentContext.first);
setState(parentContext.second);
} else {
exitRule();
}
atn::RuleTransition* ruleTransition = static_cast<atn::RuleTransition*>(
_atn.states[getState()]->transitions[0]);
setState(ruleTransition->followState->stateNumber);
}
void ParserInterpreter::recover(RecognitionException& e) {
size_t i = _input->index();
getErrorHandler()->recover(this, std::make_exception_ptr(e));
if (_input->index() == i) {
// no input consumed, better add an error node
if (is<InputMismatchException*>(&e)) {
InputMismatchException& ime = static_cast<InputMismatchException&>(e);
Token* tok = e.getOffendingToken();
size_t expectedTokenType =
ime.getExpectedTokens().getMinElement(); // get any element
_errorToken = getTokenFactory()->create(
{tok->getTokenSource(), tok->getTokenSource()->getInputStream()},
expectedTokenType, tok->getText(), Token::DEFAULT_CHANNEL,
INVALID_INDEX, INVALID_INDEX, // invalid start/stop
tok->getLine(), tok->getCharPositionInLine());
_ctx->addChild(createErrorNode(_errorToken.get()));
} else { // NoViableAlt
Token* tok = e.getOffendingToken();
_errorToken = getTokenFactory()->create(
{tok->getTokenSource(), tok->getTokenSource()->getInputStream()},
Token::INVALID_TYPE, tok->getText(), Token::DEFAULT_CHANNEL,
INVALID_INDEX, INVALID_INDEX, // invalid start/stop
tok->getLine(), tok->getCharPositionInLine());
_ctx->addChild(createErrorNode(_errorToken.get()));
}
}
}
Token* ParserInterpreter::recoverInline() {
return _errHandler->recoverInline(this);
}

View File

@ -1,186 +0,0 @@
/* 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.
*/
#pragma once
#include "Parser.h"
#include "Vocabulary.h"
#include "atn/ATN.h"
#include "atn/PredictionContext.h"
#include "support/BitSet.h"
namespace antlr4 {
/// <summary>
/// A parser simulator that mimics what ANTLR's generated
/// parser code does. A ParserATNSimulator is used to make
/// predictions via adaptivePredict but this class moves a pointer through the
/// ATN to simulate parsing. ParserATNSimulator just
/// makes us efficient rather than having to backtrack, for example.
///
/// This properly creates parse trees even for left recursive rules.
///
/// We rely on the left recursive rule invocation and special predicate
/// transitions to make left recursive rules work.
///
/// See TestParserInterpreter for examples.
/// </summary>
class ANTLR4CPP_PUBLIC ParserInterpreter : public Parser {
public:
// @deprecated
ParserInterpreter(const std::string& grammarFileName,
const std::vector<std::string>& tokenNames,
const std::vector<std::string>& ruleNames,
const atn::ATN& atn, TokenStream* input);
ParserInterpreter(const std::string& grammarFileName,
const dfa::Vocabulary& vocabulary,
const std::vector<std::string>& ruleNames,
const atn::ATN& atn, TokenStream* input);
~ParserInterpreter();
virtual void reset() override;
virtual const atn::ATN& getATN() const override;
// @deprecated
virtual const std::vector<std::string>& getTokenNames() const override;
virtual const dfa::Vocabulary& getVocabulary() const override;
virtual const std::vector<std::string>& getRuleNames() const override;
virtual std::string getGrammarFileName() const override;
/// Begin parsing at startRuleIndex
virtual ParserRuleContext* parse(size_t startRuleIndex);
virtual void enterRecursionRule(ParserRuleContext* localctx, size_t state,
size_t ruleIndex, int precedence) override;
/** Override this parser interpreters normal decision-making process
* at a particular decision and input token index. Instead of
* allowing the adaptive prediction mechanism to choose the
* first alternative within a block that leads to a successful parse,
* force it to take the alternative, 1..n for n alternatives.
*
* As an implementation limitation right now, you can only specify one
* override. This is sufficient to allow construction of different
* parse trees for ambiguous input. It means re-parsing the entire input
* in general because you're never sure where an ambiguous sequence would
* live in the various parse trees. For example, in one interpretation,
* an ambiguous input sequence would be matched completely in expression
* but in another it could match all the way back to the root.
*
* s : e '!'? ;
* e : ID
* | ID '!'
* ;
*
* Here, x! can be matched as (s (e ID) !) or (s (e ID !)). In the first
* case, the ambiguous sequence is fully contained only by the root.
* In the second case, the ambiguous sequences fully contained within just
* e, as in: (e ID !).
*
* Rather than trying to optimize this and make
* some intelligent decisions for optimization purposes, I settled on
* just re-parsing the whole input and then using
* {link Trees#getRootOfSubtreeEnclosingRegion} to find the minimal
* subtree that contains the ambiguous sequence. I originally tried to
* record the call stack at the point the parser detected and ambiguity but
* left recursive rules create a parse tree stack that does not reflect
* the actual call stack. That impedance mismatch was enough to make
* it it challenging to restart the parser at a deeply nested rule
* invocation.
*
* Only parser interpreters can override decisions so as to avoid inserting
* override checking code in the critical ALL(*) prediction execution path.
*
* @since 4.5.1
*/
void addDecisionOverride(int decision, int tokenIndex, int forcedAlt);
Ref<InterpreterRuleContext> getOverrideDecisionRoot() const;
/** Return the root of the parse, which can be useful if the parser
* bails out. You still can access the top node. Note that,
* because of the way left recursive rules add children, it's possible
* that the root will not have any children if the start rule immediately
* called and left recursive rule that fails.
*
* @since 4.5.1
*/
InterpreterRuleContext* getRootContext();
protected:
const std::string _grammarFileName;
std::vector<std::string> _tokenNames;
const atn::ATN& _atn;
std::vector<std::string> _ruleNames;
std::vector<dfa::DFA>
_decisionToDFA; // not shared like it is for generated parsers
atn::PredictionContextCache _sharedContextCache;
/** This stack corresponds to the _parentctx, _parentState pair of locals
* that would exist on call stack frames with a recursive descent parser;
* in the generated function for a left-recursive rule you'd see:
*
* private EContext e(int _p) throws RecognitionException {
* ParserRuleContext _parentctx = _ctx; // Pair.a
* int _parentState = getState(); // Pair.b
* ...
* }
*
* Those values are used to create new recursive rule invocation contexts
* associated with left operand of an alt like "expr '*' expr".
*/
std::stack<std::pair<ParserRuleContext*, size_t>> _parentContextStack;
/** We need a map from (decision,inputIndex)->forced alt for computing
* ambiguous parse trees. For now, we allow exactly one override.
*/
int _overrideDecision = -1;
size_t _overrideDecisionInputIndex = INVALID_INDEX;
size_t _overrideDecisionAlt = INVALID_INDEX;
bool _overrideDecisionReached =
false; // latch and only override once; error might trigger infinite loop
/** What is the current context when we override a decision? This tells
* us what the root of the parse tree is when using override
* for an ambiguity/lookahead check.
*/
Ref<InterpreterRuleContext> _overrideDecisionRoot;
InterpreterRuleContext* _rootContext;
virtual atn::ATNState* getATNState();
virtual void visitState(atn::ATNState* p);
/** Method visitDecisionState() is called when the interpreter reaches
* a decision state (instance of DecisionState). It gives an opportunity
* for subclasses to track interesting things.
*/
size_t visitDecisionState(atn::DecisionState* p);
/** Provide simple "factory" for InterpreterRuleContext's.
* @since 4.5.1
*/
InterpreterRuleContext* createInterpreterRuleContext(
ParserRuleContext* parent, size_t invokingStateNumber, size_t ruleIndex);
virtual void visitRuleStopState(atn::ATNState* p);
/** Rely on the error handler for this parser but, if no tokens are consumed
* to recover, add an error node. Otherwise, nothing is seen in the parse
* tree.
*/
void recover(RecognitionException& e);
Token* recoverInline();
private:
const dfa::Vocabulary& _vocabulary;
std::unique_ptr<Token> _errorToken;
};
} // namespace antlr4

View File

@ -1,138 +0,0 @@
/* 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.
*/
#include "Parser.h"
#include "Token.h"
#include "misc/Interval.h"
#include "tree/ErrorNode.h"
#include "tree/TerminalNode.h"
#include "support/CPPUtils.h"
#include "ParserRuleContext.h"
using namespace antlr4;
using namespace antlr4::tree;
using namespace antlrcpp;
ParserRuleContext ParserRuleContext::EMPTY;
ParserRuleContext::ParserRuleContext() : start(nullptr), stop(nullptr) {}
ParserRuleContext::ParserRuleContext(ParserRuleContext* parent,
size_t invokingStateNumber)
: RuleContext(parent, invokingStateNumber), start(nullptr), stop(nullptr) {}
void ParserRuleContext::copyFrom(ParserRuleContext* ctx) {
// from RuleContext
this->parent = ctx->parent;
this->invokingState = ctx->invokingState;
this->start = ctx->start;
this->stop = ctx->stop;
// copy any error nodes to alt label node
if (!ctx->children.empty()) {
for (auto child : ctx->children) {
auto errorNode = dynamic_cast<ErrorNode*>(child);
if (errorNode != nullptr) {
errorNode->setParent(this);
children.push_back(errorNode);
}
}
// Remove the just reparented error nodes from the source context.
ctx->children.erase(
std::remove_if(ctx->children.begin(), ctx->children.end(),
[this](tree::ParseTree* e) -> bool {
return std::find(children.begin(), children.end(),
e) != children.end();
}),
ctx->children.end());
}
}
void ParserRuleContext::enterRule(tree::ParseTreeListener* /*listener*/) {}
void ParserRuleContext::exitRule(tree::ParseTreeListener* /*listener*/) {}
tree::TerminalNode* ParserRuleContext::addChild(tree::TerminalNode* t) {
t->setParent(this);
children.push_back(t);
return t;
}
RuleContext* ParserRuleContext::addChild(RuleContext* ruleInvocation) {
children.push_back(ruleInvocation);
return ruleInvocation;
}
void ParserRuleContext::removeLastChild() {
if (!children.empty()) {
children.pop_back();
}
}
tree::TerminalNode* ParserRuleContext::getToken(size_t ttype, size_t i) {
if (i >= children.size()) {
return nullptr;
}
size_t j = 0; // what token with ttype have we found?
for (auto o : children) {
if (is<tree::TerminalNode*>(o)) {
tree::TerminalNode* tnode = dynamic_cast<tree::TerminalNode*>(o);
Token* symbol = tnode->getSymbol();
if (symbol->getType() == ttype) {
if (j++ == i) {
return tnode;
}
}
}
}
return nullptr;
}
std::vector<tree::TerminalNode*> ParserRuleContext::getTokens(size_t ttype) {
std::vector<tree::TerminalNode*> tokens;
for (auto& o : children) {
if (is<tree::TerminalNode*>(o)) {
tree::TerminalNode* tnode = dynamic_cast<tree::TerminalNode*>(o);
Token* symbol = tnode->getSymbol();
if (symbol->getType() == ttype) {
tokens.push_back(tnode);
}
}
}
return tokens;
}
misc::Interval ParserRuleContext::getSourceInterval() {
if (start == nullptr) {
return misc::Interval::INVALID;
}
if (stop == nullptr || stop->getTokenIndex() < start->getTokenIndex()) {
return misc::Interval(start->getTokenIndex(),
start->getTokenIndex() - 1); // empty
}
return misc::Interval(start->getTokenIndex(), stop->getTokenIndex());
}
Token* ParserRuleContext::getStart() { return start; }
Token* ParserRuleContext::getStop() { return stop; }
std::string ParserRuleContext::toInfoString(Parser* recognizer) {
std::vector<std::string> rules = recognizer->getRuleInvocationStack(this);
std::reverse(rules.begin(), rules.end());
std::string rulesStr = antlrcpp::arrayToString(rules);
return "ParserRuleContext" + rulesStr +
"{start=" + std::to_string(start->getTokenIndex()) +
", stop=" + std::to_string(stop->getTokenIndex()) + '}';
}

View File

@ -1,149 +0,0 @@
/* 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.
*/
#pragma once
#include "RuleContext.h"
#include "support/CPPUtils.h"
namespace antlr4 {
/// <summary>
/// A rule invocation record for parsing.
///
/// Contains all of the information about the current rule not stored in the
/// RuleContext. It handles parse tree children list, Any ATN state
/// tracing, and the default values available for rule invocatons:
/// start, stop, rule index, current alt number.
///
/// Subclasses made for each rule and grammar track the parameters,
/// return values, locals, and labels specific to that rule. These
/// are the objects that are returned from rules.
///
/// Note text is not an actual field of a rule return value; it is computed
/// from start and stop using the input stream's toString() method. I
/// could add a ctor to this so that we can pass in and store the input
/// stream, but I'm not sure we want to do that. It would seem to be undefined
/// to get the .text property anyway if the rule matches tokens from multiple
/// input streams.
///
/// I do not use getters for fields of objects that are used simply to
/// group values such as this aggregate. The getters/setters are there to
/// satisfy the superclass interface.
/// </summary>
class ANTLR4CPP_PUBLIC ParserRuleContext : public RuleContext {
public:
static ParserRuleContext EMPTY;
/// <summary>
/// For debugging/tracing purposes, we want to track all of the nodes in
/// the ATN traversed by the parser for a particular rule.
/// This list indicates the sequence of ATN nodes used to match
/// the elements of the children list. This list does not include
/// ATN nodes and other rules used to match rule invocations. It
/// traces the rule invocation node itself but nothing inside that
/// other rule's ATN submachine.
///
/// There is NOT a one-to-one correspondence between the children and
/// states list. There are typically many nodes in the ATN traversed
/// for each element in the children list. For example, for a rule
/// invocation there is the invoking state and the following state.
///
/// The parser setState() method updates field s and adds it to this list
/// if we are debugging/tracing.
///
/// This does not trace states visited during prediction.
/// </summary>
// public List<Integer> states;
Token* start;
Token* stop;
/// The exception that forced this rule to return. If the rule successfully
/// completed, this is "null exception pointer".
std::exception_ptr exception;
ParserRuleContext();
ParserRuleContext(ParserRuleContext* parent, size_t invokingStateNumber);
virtual ~ParserRuleContext() {}
/** COPY a ctx (I'm deliberately not using copy constructor) to avoid
* confusion with creating node with parent. Does not copy children
* (except error leaves).
*/
virtual void copyFrom(ParserRuleContext* ctx);
// Double dispatch methods for listeners
virtual void enterRule(tree::ParseTreeListener* listener);
virtual void exitRule(tree::ParseTreeListener* listener);
/** Add a token leaf node child and force its parent to be this node. */
tree::TerminalNode* addChild(tree::TerminalNode* t);
RuleContext* addChild(RuleContext* ruleInvocation);
/// Used by enterOuterAlt to toss out a RuleContext previously added as
/// we entered a rule. If we have # label, we will need to remove
/// generic ruleContext object.
virtual void removeLastChild();
virtual tree::TerminalNode* getToken(size_t ttype, std::size_t i);
virtual std::vector<tree::TerminalNode*> getTokens(size_t ttype);
template <typename T>
T* getRuleContext(size_t i) {
if (children.empty()) {
return nullptr;
}
size_t j = 0; // what element have we found with ctxType?
for (auto& child : children) {
if (antlrcpp::is<T*>(child)) {
if (j++ == i) {
return dynamic_cast<T*>(child);
}
}
}
return nullptr;
}
template <typename T>
std::vector<T*> getRuleContexts() {
std::vector<T*> contexts;
for (auto child : children) {
if (antlrcpp::is<T*>(child)) {
contexts.push_back(dynamic_cast<T*>(child));
}
}
return contexts;
}
virtual misc::Interval getSourceInterval() override;
/**
* Get the initial token in this context.
* Note that the range from start to stop is inclusive, so for rules that do
* not consume anything (for example, zero length or error productions) this
* token may exceed stop.
*/
virtual Token* getStart();
/**
* Get the final token in this context.
* Note that the range from start to stop is inclusive, so for rules that do
* not consume anything (for example, zero length or error productions) this
* token may precede start.
*/
virtual Token* getStop();
/// <summary>
/// Used for rule context info debugging during parse-time, not so much for
/// ATN debugging </summary>
virtual std::string toInfoString(Parser* recognizer);
};
} // namespace antlr4

View File

@ -1,63 +0,0 @@
/* 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.
*/
#include "ProxyErrorListener.h"
using namespace antlr4;
void ProxyErrorListener::addErrorListener(ANTLRErrorListener* listener) {
if (listener == nullptr) {
throw "listener cannot be null.";
}
_delegates.insert(listener);
}
void ProxyErrorListener::removeErrorListener(ANTLRErrorListener* listener) {
_delegates.erase(listener);
}
void ProxyErrorListener::removeErrorListeners() { _delegates.clear(); }
void ProxyErrorListener::syntaxError(Recognizer* recognizer,
Token* offendingSymbol, size_t line,
size_t charPositionInLine,
const std::string& msg,
std::exception_ptr e) {
for (auto listener : _delegates) {
listener->syntaxError(recognizer, offendingSymbol, line, charPositionInLine,
msg, e);
}
}
void ProxyErrorListener::reportAmbiguity(Parser* recognizer,
const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, bool exact,
const antlrcpp::BitSet& ambigAlts,
atn::ATNConfigSet* configs) {
for (auto listener : _delegates) {
listener->reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact,
ambigAlts, configs);
}
}
void ProxyErrorListener::reportAttemptingFullContext(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet& conflictingAlts,
atn::ATNConfigSet* configs) {
for (auto listener : _delegates) {
listener->reportAttemptingFullContext(recognizer, dfa, startIndex,
stopIndex, conflictingAlts, configs);
}
}
void ProxyErrorListener::reportContextSensitivity(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, size_t prediction, atn::ATNConfigSet* configs) {
for (auto listener : _delegates) {
listener->reportContextSensitivity(recognizer, dfa, startIndex, stopIndex,
prediction, configs);
}
}

View File

@ -1,45 +0,0 @@
/* 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.
*/
#pragma once
#include "ANTLRErrorListener.h"
#include "Exceptions.h"
namespace antlr4 {
/// This implementation of ANTLRErrorListener dispatches all calls to a
/// collection of delegate listeners. This reduces the effort required to
/// support multiple listeners.
class ANTLR4CPP_PUBLIC ProxyErrorListener : public ANTLRErrorListener {
private:
std::set<ANTLRErrorListener*> _delegates; // Not owned.
public:
void addErrorListener(ANTLRErrorListener* listener);
void removeErrorListener(ANTLRErrorListener* listener);
void removeErrorListeners();
void syntaxError(Recognizer* recognizer, Token* offendingSymbol, size_t line,
size_t charPositionInLine, const std::string& msg,
std::exception_ptr e) override;
virtual void reportAmbiguity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet& ambigAlts,
atn::ATNConfigSet* configs) override;
virtual void reportAttemptingFullContext(
Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet& conflictingAlts,
atn::ATNConfigSet* configs) override;
virtual void reportContextSensitivity(Parser* recognizer, const dfa::DFA& dfa,
size_t startIndex, size_t stopIndex,
size_t prediction,
atn::ATNConfigSet* configs) override;
};
} // namespace antlr4

View File

@ -1,67 +0,0 @@
/* 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.
*/
#include "ParserRuleContext.h"
#include "Recognizer.h"
#include "atn/ATN.h"
#include "misc/IntervalSet.h"
#include "support/StringUtils.h"
#include "RecognitionException.h"
using namespace antlr4;
RecognitionException::RecognitionException(Recognizer* recognizer,
IntStream* input,
ParserRuleContext* ctx,
Token* offendingToken)
: RecognitionException("", recognizer, input, ctx, offendingToken) {}
RecognitionException::RecognitionException(const std::string& message,
Recognizer* recognizer,
IntStream* input,
ParserRuleContext* ctx,
Token* offendingToken)
: RuntimeException(message),
_recognizer(recognizer),
_input(input),
_ctx(ctx),
_offendingToken(offendingToken) {
InitializeInstanceFields();
if (recognizer != nullptr) {
_offendingState = recognizer->getState();
}
}
RecognitionException::~RecognitionException() {}
size_t RecognitionException::getOffendingState() const {
return _offendingState;
}
void RecognitionException::setOffendingState(size_t offendingState) {
_offendingState = offendingState;
}
misc::IntervalSet RecognitionException::getExpectedTokens() const {
if (_recognizer) {
return _recognizer->getATN().getExpectedTokens(_offendingState, _ctx);
}
return misc::IntervalSet::EMPTY_SET;
}
RuleContext* RecognitionException::getCtx() const { return _ctx; }
IntStream* RecognitionException::getInputStream() const { return _input; }
Token* RecognitionException::getOffendingToken() const {
return _offendingToken;
}
Recognizer* RecognitionException::getRecognizer() const { return _recognizer; }
void RecognitionException::InitializeInstanceFields() {
_offendingState = INVALID_INDEX;
}

View File

@ -1,100 +0,0 @@
/* 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.
*/
#pragma once
#include "Exceptions.h"
namespace antlr4 {
/// The root of the ANTLR exception hierarchy. In general, ANTLR tracks just
/// 3 kinds of errors: prediction errors, failed predicate errors, and
/// mismatched input errors. In each case, the parser knows where it is
/// in the input, where it is in the ATN, the rule invocation stack,
/// and what kind of problem occurred.
class ANTLR4CPP_PUBLIC RecognitionException : public RuntimeException {
private:
/// The Recognizer where this exception originated.
Recognizer* _recognizer;
IntStream* _input;
ParserRuleContext* _ctx;
/// The current Token when an error occurred. Since not all streams
/// support accessing symbols by index, we have to track the Token
/// instance itself.
Token* _offendingToken;
size_t _offendingState;
public:
RecognitionException(Recognizer* recognizer, IntStream* input,
ParserRuleContext* ctx, Token* offendingToken = nullptr);
RecognitionException(const std::string& message, Recognizer* recognizer,
IntStream* input, ParserRuleContext* ctx,
Token* offendingToken = nullptr);
RecognitionException(RecognitionException const&) = default;
~RecognitionException();
RecognitionException& operator=(RecognitionException const&) = default;
/// Get the ATN state number the parser was in at the time the error
/// occurred. For NoViableAltException and
/// LexerNoViableAltException exceptions, this is the
/// DecisionState number. For others, it is the state whose outgoing
/// edge we couldn't match.
///
/// If the state number is not known, this method returns -1.
virtual size_t getOffendingState() const;
protected:
void setOffendingState(size_t offendingState);
/// Gets the set of input symbols which could potentially follow the
/// previously matched symbol at the time this exception was thrown.
///
/// If the set of expected tokens is not known and could not be computed,
/// this method returns an empty set.
///
/// @returns The set of token types that could potentially follow the current
/// state in the ATN, or an empty set if the information is not available.
public:
virtual misc::IntervalSet getExpectedTokens() const;
/// <summary>
/// Gets the <seealso cref="RuleContext"/> at the time this exception was
/// thrown. <p/> If the context is not available, this method returns {@code
/// null}.
/// </summary>
/// <returns> The <seealso cref="RuleContext"/> at the time this exception was
/// thrown. If the context is not available, this method returns {@code null}.
/// </returns>
virtual RuleContext* getCtx() const;
/// <summary>
/// Gets the input stream which is the symbol source for the recognizer where
/// this exception was thrown.
/// <p/>
/// If the input stream is not available, this method returns {@code null}.
/// </summary>
/// <returns> The input stream which is the symbol source for the recognizer
/// where this exception was thrown, or {@code null} if the stream is not
/// available. </returns>
virtual IntStream* getInputStream() const;
virtual Token* getOffendingToken() const;
/// <summary>
/// Gets the <seealso cref="Recognizer"/> where this exception occurred.
/// <p/>
/// If the recognizer is not available, this method returns {@code null}.
/// </summary>
/// <returns> The recognizer where this exception occurred, or {@code null} if
/// the recognizer is not available. </returns>
virtual Recognizer* getRecognizer() const;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,163 +0,0 @@
/* 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.
*/
#include "ConsoleErrorListener.h"
#include "RecognitionException.h"
#include "Token.h"
#include "atn/ATN.h"
#include "atn/ATNSimulator.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "Vocabulary.h"
#include "Recognizer.h"
using namespace antlr4;
using namespace antlr4::atn;
std::map<const dfa::Vocabulary*, std::map<std::string, size_t>>
Recognizer::_tokenTypeMapCache;
std::map<std::vector<std::string>, std::map<std::string, size_t>>
Recognizer::_ruleIndexMapCache;
Recognizer::Recognizer() {
InitializeInstanceFields();
_proxListener.addErrorListener(&ConsoleErrorListener::INSTANCE);
}
Recognizer::~Recognizer() {}
dfa::Vocabulary const& Recognizer::getVocabulary() const {
static dfa::Vocabulary vocabulary =
dfa::Vocabulary::fromTokenNames(getTokenNames());
return vocabulary;
}
std::map<std::string, size_t> Recognizer::getTokenTypeMap() {
const dfa::Vocabulary& vocabulary = getVocabulary();
std::lock_guard<std::mutex> lck(_mutex);
std::map<std::string, size_t> result;
auto iterator = _tokenTypeMapCache.find(&vocabulary);
if (iterator != _tokenTypeMapCache.end()) {
result = iterator->second;
} else {
for (size_t i = 0; i <= getATN().maxTokenType; ++i) {
std::string literalName = vocabulary.getLiteralName(i);
if (!literalName.empty()) {
result[literalName] = i;
}
std::string symbolicName = vocabulary.getSymbolicName(i);
if (!symbolicName.empty()) {
result[symbolicName] = i;
}
}
result["EOF"] = EOF;
_tokenTypeMapCache[&vocabulary] = result;
}
return result;
}
std::map<std::string, size_t> Recognizer::getRuleIndexMap() {
const std::vector<std::string>& ruleNames = getRuleNames();
if (ruleNames.empty()) {
throw "The current recognizer does not provide a list of rule names.";
}
std::lock_guard<std::mutex> lck(_mutex);
std::map<std::string, size_t> result;
auto iterator = _ruleIndexMapCache.find(ruleNames);
if (iterator != _ruleIndexMapCache.end()) {
result = iterator->second;
} else {
result = antlrcpp::toMap(ruleNames);
_ruleIndexMapCache[ruleNames] = result;
}
return result;
}
size_t Recognizer::getTokenType(const std::string& tokenName) {
const std::map<std::string, size_t>& map = getTokenTypeMap();
auto iterator = map.find(tokenName);
if (iterator == map.end()) return Token::INVALID_TYPE;
return iterator->second;
}
void Recognizer::setInterpreter(atn::ATNSimulator* interpreter) {
// Usually the interpreter is set by the descendant (lexer or parser
// (simulator), but can also be exchanged by the profiling ATN simulator.
delete _interpreter;
_interpreter = interpreter;
}
std::string Recognizer::getErrorHeader(RecognitionException* e) {
// We're having issues with cross header dependencies, these two classes will
// need to be rewritten to remove that.
size_t line = e->getOffendingToken()->getLine();
size_t charPositionInLine = e->getOffendingToken()->getCharPositionInLine();
return std::string("line ") + std::to_string(line) + ":" +
std::to_string(charPositionInLine);
}
std::string Recognizer::getTokenErrorDisplay(Token* t) {
if (t == nullptr) {
return "<no Token>";
}
std::string s = t->getText();
if (s == "") {
if (t->getType() == EOF) {
s = "<EOF>";
} else {
s = std::string("<") + std::to_string(t->getType()) + std::string(">");
}
}
antlrcpp::replaceAll(s, "\n", "\\n");
antlrcpp::replaceAll(s, "\r", "\\r");
antlrcpp::replaceAll(s, "\t", "\\t");
return "'" + s + "'";
}
void Recognizer::addErrorListener(ANTLRErrorListener* listener) {
_proxListener.addErrorListener(listener);
}
void Recognizer::removeErrorListener(ANTLRErrorListener* listener) {
_proxListener.removeErrorListener(listener);
}
void Recognizer::removeErrorListeners() {
_proxListener.removeErrorListeners();
}
ProxyErrorListener& Recognizer::getErrorListenerDispatch() {
return _proxListener;
}
bool Recognizer::sempred(RuleContext* /*localctx*/, size_t /*ruleIndex*/,
size_t /*actionIndex*/) {
return true;
}
bool Recognizer::precpred(RuleContext* /*localctx*/, int /*precedence*/) {
return true;
}
void Recognizer::action(RuleContext* /*localctx*/, size_t /*ruleIndex*/,
size_t /*actionIndex*/) {}
size_t Recognizer::getState() const { return _stateNumber; }
void Recognizer::setState(size_t atnState) { _stateNumber = atnState; }
void Recognizer::InitializeInstanceFields() {
_stateNumber = ATNState::INVALID_STATE_NUMBER;
_interpreter = nullptr;
}

View File

@ -1,171 +0,0 @@
/* 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.
*/
#pragma once
#include "ProxyErrorListener.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC Recognizer {
public:
static const size_t EOF = static_cast<size_t>(
-1); // std::numeric_limits<size_t>::max(); doesn't work in VS 2013.
Recognizer();
Recognizer(Recognizer const&) = delete;
virtual ~Recognizer();
Recognizer& operator=(Recognizer const&) = delete;
/** 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.
*
* @deprecated Use {@link #getVocabulary()} instead.
*/
virtual std::vector<std::string> const& getTokenNames() const = 0;
virtual std::vector<std::string> const& getRuleNames() const = 0;
/**
* Get the vocabulary used by the recognizer.
*
* @return A {@link Vocabulary} instance providing information about the
* vocabulary used by the grammar.
*/
virtual dfa::Vocabulary const& getVocabulary() const;
/// <summary>
/// Get a map from token names to token types.
/// <p/>
/// Used for XPath and tree pattern compilation.
/// </summary>
virtual std::map<std::string, size_t> getTokenTypeMap();
/// <summary>
/// Get a map from rule names to rule indexes.
/// <p/>
/// Used for XPath and tree pattern compilation.
/// </summary>
virtual std::map<std::string, size_t> getRuleIndexMap();
virtual size_t getTokenType(const std::string& tokenName);
/// <summary>
/// If this recognizer was generated, it will have a serialized ATN
/// representation of the grammar.
/// <p/>
/// For interpreters, we don't know their serialized ATN despite having
/// created the interpreter from it.
/// </summary>
virtual const std::vector<uint16_t> getSerializedATN() const {
throw "there is no serialized ATN";
}
/// <summary>
/// For debugging and other purposes, might want the grammar name.
/// Have ANTLR generate an implementation for this method.
/// </summary>
virtual std::string getGrammarFileName() const = 0;
/// Get the ATN interpreter (in fact one of it's descendants) used by the
/// recognizer for prediction.
/// @returns The ATN interpreter used by the recognizer for prediction.
template <class T>
T* getInterpreter() const {
return dynamic_cast<T*>(_interpreter);
}
/**
* Set the ATN interpreter used by the recognizer for prediction.
*
* @param interpreter The ATN interpreter used by the recognizer for
* prediction.
*/
void setInterpreter(atn::ATNSimulator* interpreter);
/// What is the error header, normally line/character position information?
virtual std::string getErrorHeader(RecognitionException* e);
/** 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.
*
* @deprecated This method is not called by the ANTLR 4 Runtime. Specific
* implementations of {@link ANTLRErrorStrategy} may provide a similar
* feature when necessary. For example, see
* {@link DefaultErrorStrategy#getTokenErrorDisplay}.
*/
virtual std::string getTokenErrorDisplay(Token* t);
/// <exception cref="NullPointerException"> if {@code listener} is {@code
/// null}. </exception>
virtual void addErrorListener(ANTLRErrorListener* listener);
virtual void removeErrorListener(ANTLRErrorListener* listener);
virtual void removeErrorListeners();
virtual ProxyErrorListener& getErrorListenerDispatch();
// subclass needs to override these if there are sempreds or actions
// that the ATN interp needs to execute
virtual bool sempred(RuleContext* localctx, size_t ruleIndex,
size_t actionIndex);
virtual bool precpred(RuleContext* localctx, int precedence);
virtual void action(RuleContext* localctx, size_t ruleIndex,
size_t actionIndex);
virtual size_t getState() const;
// Get the ATN used by the recognizer for prediction.
virtual const atn::ATN& getATN() const = 0;
/// <summary>
/// Indicate that the recognizer has changed internal state that is
/// consistent with the ATN state passed in. This way we always know
/// where we are in the ATN as the parser goes along. The rule
/// context objects form a stack that lets us see the stack of
/// invoking rules. Combine this and we have complete ATN
/// configuration information.
/// </summary>
void setState(size_t atnState);
virtual IntStream* getInputStream() = 0;
virtual void setInputStream(IntStream* input) = 0;
virtual Ref<TokenFactory<CommonToken>> getTokenFactory() = 0;
template <typename T1>
void setTokenFactory(TokenFactory<T1>* input);
protected:
atn::ATNSimulator*
_interpreter; // Set and deleted in descendants (or the profiler).
// Mutex to manage synchronized access for multithreading.
std::mutex _mutex;
private:
static std::map<const dfa::Vocabulary*, std::map<std::string, size_t>>
_tokenTypeMapCache;
static std::map<std::vector<std::string>, std::map<std::string, size_t>>
_ruleIndexMapCache;
ProxyErrorListener _proxListener; // Manages a collection of listeners.
size_t _stateNumber;
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,133 +0,0 @@
/* 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.
*/
#include "Parser.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "misc/Interval.h"
#include "tree/ParseTreeVisitor.h"
#include "tree/Trees.h"
#include "RuleContext.h"
using namespace antlr4;
using namespace antlr4::atn;
RuleContext::RuleContext() { InitializeInstanceFields(); }
RuleContext::RuleContext(RuleContext* parent_, size_t invokingState_) {
InitializeInstanceFields();
this->parent = parent_;
this->invokingState = invokingState_;
}
int RuleContext::depth() {
int n = 1;
RuleContext* p = this;
while (true) {
if (p->parent == nullptr) break;
p = static_cast<RuleContext*>(p->parent);
n++;
}
return n;
}
bool RuleContext::isEmpty() {
return invokingState == ATNState::INVALID_STATE_NUMBER;
}
misc::Interval RuleContext::getSourceInterval() {
return misc::Interval::INVALID;
}
std::string RuleContext::getText() {
if (children.empty()) {
return "";
}
std::stringstream ss;
for (size_t i = 0; i < children.size(); i++) {
ParseTree* tree = children[i];
if (tree != nullptr) ss << tree->getText();
}
return ss.str();
}
size_t RuleContext::getRuleIndex() const { return INVALID_INDEX; }
size_t RuleContext::getAltNumber() const {
return atn::ATN::INVALID_ALT_NUMBER;
}
void RuleContext::setAltNumber(size_t /*altNumber*/) {}
antlrcpp::Any RuleContext::accept(tree::ParseTreeVisitor* visitor) {
return visitor->visitChildren(this);
}
std::string RuleContext::toStringTree(Parser* recog) {
return tree::Trees::toStringTree(this, recog);
}
std::string RuleContext::toStringTree(std::vector<std::string>& ruleNames) {
return tree::Trees::toStringTree(this, ruleNames);
}
std::string RuleContext::toStringTree() { return toStringTree(nullptr); }
std::string RuleContext::toString(const std::vector<std::string>& ruleNames) {
return toString(ruleNames, nullptr);
}
std::string RuleContext::toString(const std::vector<std::string>& ruleNames,
RuleContext* stop) {
std::stringstream ss;
RuleContext* currentParent = this;
ss << "[";
while (currentParent != stop) {
if (ruleNames.empty()) {
if (!currentParent->isEmpty()) {
ss << currentParent->invokingState;
}
} else {
size_t ruleIndex = currentParent->getRuleIndex();
std::string ruleName = (ruleIndex < ruleNames.size())
? ruleNames[ruleIndex]
: std::to_string(ruleIndex);
ss << ruleName;
}
if (currentParent->parent == nullptr) // No parent anymore.
break;
currentParent = static_cast<RuleContext*>(currentParent->parent);
if (!ruleNames.empty() || !currentParent->isEmpty()) {
ss << " ";
}
}
ss << "]";
return ss.str();
}
std::string RuleContext::toString() { return toString(nullptr); }
std::string RuleContext::toString(Recognizer* recog) {
return toString(recog, &ParserRuleContext::EMPTY);
}
std::string RuleContext::toString(Recognizer* recog, RuleContext* stop) {
if (recog == nullptr)
return toString(std::vector<std::string>(), stop); // Don't use an
// initializer {} here
// or we end up calling
// ourselve recursivly.
return toString(recog->getRuleNames(), stop);
}
void RuleContext::InitializeInstanceFields() { invokingState = INVALID_INDEX; }

View File

@ -1,143 +0,0 @@
/* 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.
*/
#pragma once
#include "tree/ParseTree.h"
namespace antlr4 {
/** A rule context is a record of a single rule invocation.
*
* We form a stack of these context objects using the parent
* pointer. A parent pointer of null indicates that the current
* context is the bottom of the stack. The ParserRuleContext subclass
* as a children list so that we can turn this data structure into a
* tree.
*
* The root node always has a null pointer and invokingState of -1.
*
* Upon entry to parsing, the first invoked rule function creates a
* context object (asubclass specialized for that rule such as
* SContext) and makes it the root of a parse tree, recorded by field
* Parser._ctx.
*
* public final SContext s() throws RecognitionException {
* SContext _localctx = new SContext(_ctx, getState()); <-- create new node
* enterRule(_localctx, 0, RULE_s); <-- push it
* ...
* exitRule(); <-- pop back to
* _localctx return _localctx;
* }
*
* A subsequent rule invocation of r from the start rule s pushes a
* new context object for r whose parent points at s and use invoking
* state is the state with r emanating as edge label.
*
* The invokingState fields from a context object to the root
* together form a stack of rule indication states where the root
* (bottom of the stack) has a -1 sentinel value. If we invoke start
* symbol s then call r1, which calls r2, the would look like
* this:
*
* SContext[-1] <- root node (bottom of the stack)
* R1Context[p] <- p in rule s called r1
* R2Context[q] <- q in rule r1 called r2
*
* So the top of the stack, _ctx, represents a call to the current
* rule and it holds the return address from another rule that invoke
* to this rule. To invoke a rule, we must always have a current context.
*
* The parent contexts are useful for computing lookahead sets and
* getting error information.
*
* These objects are used during parsing and prediction.
* For the special case of parsers, we use the subclass
* ParserRuleContext.
*
* @see ParserRuleContext
*/
class ANTLR4CPP_PUBLIC RuleContext : public tree::ParseTree {
public:
/// 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 and this context object represents
/// the start rule.
size_t invokingState;
RuleContext();
RuleContext(RuleContext* parent, size_t invokingState);
virtual int depth();
/// A context is empty if there is no invoking state; meaning nobody called
/// current context.
virtual bool isEmpty();
// satisfy the ParseTree / SyntaxTree interface
virtual misc::Interval getSourceInterval() override;
virtual std::string getText() override;
virtual size_t getRuleIndex() const;
/** For rule associated with this parse tree internal node, return
* the outer alternative number used to match the input. Default
* implementation does not compute nor store this alt num. Create
* a subclass of ParserRuleContext with backing field and set
* option contextSuperClass.
* to set it.
*
* @since 4.5.3
*/
virtual size_t getAltNumber() const;
/** Set the outer alternative number for this context node. Default
* implementation does nothing to avoid backing field overhead for
* trees that don't need it. Create
* a subclass of ParserRuleContext with backing field and set
* option contextSuperClass.
*
* @since 4.5.3
*/
virtual void setAltNumber(size_t altNumber);
virtual antlrcpp::Any accept(tree::ParseTreeVisitor* visitor) override;
/// <summary>
/// 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.
/// </summary>
virtual std::string toStringTree(Parser* recog) override;
/// <summary>
/// Print out a whole tree, not just a node, in LISP format
/// (root child1 .. childN). Print just a node if this is a leaf.
/// </summary>
virtual std::string toStringTree(std::vector<std::string>& ruleNames);
virtual std::string toStringTree() override;
virtual std::string toString() override;
std::string toString(Recognizer* recog);
std::string toString(const std::vector<std::string>& ruleNames);
// recog null unless ParserRuleContext, in which case we use subclass
// toString(...)
std::string toString(Recognizer* recog, RuleContext* stop);
virtual std::string toString(const std::vector<std::string>& ruleNames,
RuleContext* stop);
bool operator==(const RuleContext& other) {
return this == &other;
} // Simple address comparison.
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,23 +0,0 @@
/* 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.
*/
#include "atn/ATN.h"
#include "RuleContextWithAltNum.h"
using namespace antlr4;
using namespace antlr4::atn;
RuleContextWithAltNum::RuleContextWithAltNum() : ParserRuleContext() {
altNum = ATN::INVALID_ALT_NUMBER;
}
RuleContextWithAltNum::RuleContextWithAltNum(ParserRuleContext* parent,
int invokingStateNumber)
: ParserRuleContext(parent, invokingStateNumber) {}
size_t RuleContextWithAltNum::getAltNumber() const { return altNum; }
void RuleContextWithAltNum::setAltNumber(size_t number) { altNum = number; }

View File

@ -1,32 +0,0 @@
/* 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.
*/
#pragma once
#include "ParserRuleContext.h"
namespace antlr4 {
/// A handy class for use with
///
/// options {contextSuperClass=org.antlr.v4.runtime.RuleContextWithAltNum;}
///
/// that provides a backing field / impl for the outer alternative number
/// matched for an internal parse tree node.
///
/// I'm only putting into Java runtime as I'm certain I'm the only one that
/// will really every use this.
class ANTLR4CPP_PUBLIC RuleContextWithAltNum : public ParserRuleContext {
public:
size_t altNum = 0;
RuleContextWithAltNum();
RuleContextWithAltNum(ParserRuleContext* parent, int invokingStateNumber);
virtual size_t getAltNumber() const override;
virtual void setAltNumber(size_t altNum) override;
};
} // namespace antlr4

View File

@ -1,62 +0,0 @@
/* 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.
*/
#include "RuntimeMetaData.h"
using namespace antlr4;
const std::string RuntimeMetaData::VERSION = "4.7.1";
std::string RuntimeMetaData::getRuntimeVersion() { return VERSION; }
void RuntimeMetaData::checkVersion(const std::string& generatingToolVersion,
const std::string& compileTimeVersion) {
std::string runtimeVersion = VERSION;
bool runtimeConflictsWithGeneratingTool = false;
bool runtimeConflictsWithCompileTimeTool = false;
if (generatingToolVersion != "") {
runtimeConflictsWithGeneratingTool =
runtimeVersion != generatingToolVersion &&
getMajorMinorVersion(runtimeVersion) !=
getMajorMinorVersion(generatingToolVersion);
}
runtimeConflictsWithCompileTimeTool =
runtimeVersion != compileTimeVersion &&
getMajorMinorVersion(runtimeVersion) !=
getMajorMinorVersion(compileTimeVersion);
if (runtimeConflictsWithGeneratingTool) {
std::cerr << "ANTLR Tool version " << generatingToolVersion
<< " used for code generation does not match "
"the current runtime version "
<< runtimeVersion << std::endl;
}
if (runtimeConflictsWithCompileTimeTool) {
std::cerr << "ANTLR Runtime version " << compileTimeVersion
<< " used for parser compilation does not match "
"the current runtime version "
<< runtimeVersion << std::endl;
}
}
std::string RuntimeMetaData::getMajorMinorVersion(const std::string& version) {
size_t firstDot = version.find('.');
size_t secondDot = firstDot != std::string::npos
? version.find('.', firstDot + 1)
: std::string::npos;
size_t firstDash = version.find('-');
size_t referenceLength = version.size();
if (secondDot != std::string::npos) {
referenceLength = std::min(referenceLength, secondDot);
}
if (firstDash != std::string::npos) {
referenceLength = std::min(referenceLength, firstDash);
}
return version.substr(0, referenceLength);
}

View File

@ -1,159 +0,0 @@
/* 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.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
/// <summary>
/// This class provides access to the current version of the ANTLR 4 runtime
/// library as compile-time and runtime constants, along with methods for
/// checking for matching version numbers and notifying listeners in the case
/// where a version mismatch is detected.
///
/// <para>
/// The runtime version information is provided by <seealso cref="#VERSION"/>
/// and <seealso cref="#getRuntimeVersion()"/>. Detailed information about these
/// values is provided in the documentation for each member.</para>
///
/// <para>
/// The runtime version check is implemented by <seealso cref="#checkVersion"/>.
/// Detailed information about incorporating this call into user code, as well
/// as its use in generated code, is provided in the documentation for the
/// method.</para>
///
/// <para>
/// Version strings x.y and x.y.z are considered "compatible" and no error
/// would be generated. Likewise, version strings x.y-SNAPSHOT and x.y.z are
/// considered "compatible" because the major and minor components x.y
/// are the same in each.</para>
///
/// <para>
/// To trap any error messages issued by this code, use System.setErr()
/// in your main() startup code.
/// </para>
///
/// @since 4.3
/// </summary>
class ANTLR4CPP_PUBLIC RuntimeMetaData {
public:
/// A compile-time constant containing the current version of the ANTLR 4
/// runtime library.
///
/// <para>
/// This compile-time constant value allows generated parsers and other
/// libraries to include a literal reference to the version of the ANTLR 4
/// runtime library the code was compiled against. At each release, we
/// change this value.</para>
///
/// <para>Version numbers are assumed to have the form
///
/// <em>major</em>.<em>minor</em>.<em>patch</em>.<em>revision</em>-<em>suffix</em>,
///
/// with the individual components defined as follows.</para>
///
/// <ul>
/// <li><em>major</em> is a required non-negative integer, and is equal to
/// {@code 4} for ANTLR 4.</li>
/// <li><em>minor</em> is a required non-negative integer.</li>
/// <li><em>patch</em> is an optional non-negative integer. When
/// <em>patch</em> is omitted, the {@code .} (dot) appearing before it is
/// also omitted.</li>
/// <li><em>revision</em> is an optional non-negative integer, and may only
/// be included when <em>patch</em> is also included. When <em>revision</em>
/// is omitted, the {@code .} (dot) appearing before it is also omitted.</li>
/// <li><em>suffix</em> is an optional string. When <em>suffix</em> is
/// omitted, the {@code -} (hyphen-minus) appearing before it is also
/// omitted.</li>
/// </ul>
static const std::string VERSION;
/// <summary>
/// Gets the currently executing version of the ANTLR 4 runtime library.
///
/// <para>
/// This method provides runtime access to the <seealso cref="#VERSION"/>
/// field, as opposed to directly referencing the field as a compile-time
/// constant.</para>
/// </summary>
/// <returns> The currently executing version of the ANTLR 4 library
/// </returns>
static std::string getRuntimeVersion();
/// <summary>
/// This method provides the ability to detect mismatches between the version
/// of ANTLR 4 used to generate a parser, the version of the ANTLR runtime a
/// parser was compiled against, and the version of the ANTLR runtime which
/// is currently executing.
///
/// <para>
/// The version check is designed to detect the following two specific
/// scenarios.</para>
///
/// <ul>
/// <li>The ANTLR Tool version used for code generation does not match the
/// currently executing runtime version.</li>
/// <li>The ANTLR Runtime version referenced at the time a parser was
/// compiled does not match the currently executing runtime version.</li>
/// </ul>
///
/// <para>
/// Starting with ANTLR 4.3, the code generator emits a call to this method
/// using two constants in each generated lexer and parser: a hard-coded
/// constant indicating the version of the tool used to generate the parser
/// and a reference to the compile-time constant <seealso cref="#VERSION"/>.
/// At runtime, this method is called during the initialization of the
/// generated parser to detect mismatched versions, and notify the registered
/// listeners prior to creating instances of the parser.</para>
///
/// <para>
/// This method does not perform any detection or filtering of semantic
/// changes between tool and runtime versions. It simply checks for a
/// version match and emits an error to stderr if a difference
/// is detected.</para>
///
/// <para>
/// Note that some breaking changes between releases could result in other
/// types of runtime exceptions, such as a <seealso cref="LinkageError"/>,
/// prior to calling this method. In these cases, the underlying version
/// mismatch will not be reported here. This method is primarily intended to
/// notify users of potential semantic changes between releases that do not
/// result in binary compatibility problems which would be detected by the
/// class loader. As with semantic changes, changes that break binary
/// compatibility between releases are mentioned in the release notes
/// accompanying the affected release.</para>
///
/// <para>
/// <strong>Additional note for target developers:</strong> The version check
/// implemented by this class is designed to address specific compatibility
/// concerns that may arise during the execution of Java applications. Other
/// targets should consider the implementation of this method in the context
/// of that target's known execution environment, which may or may not
/// resemble the design provided for the Java target.</para>
/// </summary>
/// <param name="generatingToolVersion"> The version of the tool used to
/// generate a parser. This value may be null when called from user code that
/// was not generated by, and does not reference, the ANTLR 4 Tool itself.
/// </param> <param name="compileTimeVersion"> The version of the runtime the
/// parser was compiled against. This should always be passed using a direct
/// reference to <seealso cref="#VERSION"/>. </param>
static void checkVersion(const std::string& generatingToolVersion,
const std::string& compileTimeVersion);
/// <summary>
/// Gets the major and minor version numbers from a version string. For
/// details about the syntax of the input {@code version}.
/// E.g., from x.y.z return x.y.
/// </summary>
/// <param name="version"> The complete version string. </param>
/// <returns> A string of the form <em>major</em>.<em>minor</em> containing
/// only the major and minor components of the version string. </returns>
static std::string getMajorMinorVersion(const std::string& version);
};
} // namespace antlr4

View File

@ -1,8 +0,0 @@
/* 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.
*/
#include "Token.h"
antlr4::Token::~Token() {}

View File

@ -1,93 +0,0 @@
/* 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.
*/
#pragma once
#include "IntStream.h"
namespace antlr4 {
/// A token has properties: text, type, line, character position in the line
/// (so we can ignore tabs), token channel, index, and source from which
/// we obtained this token.
class ANTLR4CPP_PUBLIC Token {
public:
static const size_t INVALID_TYPE = 0;
/// During lookahead operations, this "token" signifies we hit rule end ATN
/// state and did not follow it despite needing to.
static const size_t EPSILON = static_cast<size_t>(-2);
static const size_t MIN_USER_TOKEN_TYPE = 1;
static const size_t EOF = IntStream::EOF;
virtual ~Token();
/// All tokens go to the parser (unless skip() is called in that rule)
/// on a particular "channel". The parser tunes to a particular channel
/// so that whitespace etc... can go to the parser on a "hidden" channel.
static const size_t DEFAULT_CHANNEL = 0;
/// Anything on different channel than DEFAULT_CHANNEL is not parsed
/// by parser.
static const size_t HIDDEN_CHANNEL = 1;
/**
* This is the minimum constant value which can be assigned to a
* user-defined token channel.
*
* <p>
* The non-negative numbers less than {@link #MIN_USER_CHANNEL_VALUE} are
* assigned to the predefined channels {@link #DEFAULT_CHANNEL} and
* {@link #HIDDEN_CHANNEL}.</p>
*
* @see Token#getChannel()
*/
static const size_t MIN_USER_CHANNEL_VALUE = 2;
/// Get the text of the token.
virtual std::string getText() const = 0;
/// Get the token type of the token
virtual size_t getType() const = 0;
/// The line number on which the 1st character of this token was matched,
/// line=1..n
virtual size_t getLine() const = 0;
/// The index of the first character of this token relative to the
/// beginning of the line at which it occurs, 0..n-1
virtual size_t getCharPositionInLine() const = 0;
/// Return the channel this token. Each token can arrive at the parser
/// on a different channel, but the parser only "tunes" to a single channel.
/// The parser ignores everything not on DEFAULT_CHANNEL.
virtual size_t getChannel() const = 0;
/// An index from 0..n-1 of the token object in the input stream.
/// This must be valid in order to print token streams and
/// use TokenRewriteStream.
///
/// Return INVALID_INDEX to indicate that this token was conjured up since
/// it doesn't have a valid index.
virtual size_t getTokenIndex() const = 0;
/// The starting character index of the token
/// This method is optional; return INVALID_INDEX if not implemented.
virtual size_t getStartIndex() const = 0;
/// The last character index of the token.
/// This method is optional; return INVALID_INDEX if not implemented.
virtual size_t getStopIndex() const = 0;
/// Gets the <seealso cref="TokenSource"/> which created this token.
virtual TokenSource* getTokenSource() const = 0;
/// Gets the <seealso cref="CharStream"/> from which this token was derived.
virtual CharStream* getInputStream() const = 0;
virtual std::string toString() const = 0;
};
} // namespace antlr4

View File

@ -1,34 +0,0 @@
/* 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.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
/// The default mechanism for creating tokens. It's used by default in Lexer and
/// 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.
template <typename Symbol>
class ANTLR4CPP_PUBLIC TokenFactory {
public:
virtual ~TokenFactory() {}
/// This is the method used to create tokens in the lexer and in the
/// 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.
virtual std::unique_ptr<Symbol> create(
std::pair<TokenSource*, CharStream*> source, size_t type,
const std::string& text, size_t channel, size_t start, size_t stop,
size_t line, size_t charPositionInLine) = 0;
/// Generically useful
virtual std::unique_ptr<Symbol> create(size_t type,
const std::string& text) = 0;
};
} // namespace antlr4

View File

@ -1,8 +0,0 @@
/* 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.
*/
#include "TokenSource.h"
antlr4::TokenSource::~TokenSource() {}

View File

@ -1,87 +0,0 @@
/* 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.
*/
#pragma once
#include "TokenFactory.h"
namespace antlr4 {
/// <summary>
/// A source of tokens must provide a sequence of tokens via <seealso
/// cref="#nextToken()"/> and also must reveal it's source of characters;
/// <seealso cref="CommonToken"/>'s text is computed from a <seealso
/// cref="CharStream"/>; it only store indices into the char stream. <p/> Errors
/// from the lexer are never passed to the parser. Either you want to keep going
/// or you do not upon token recognition error. If you do not want to continue
/// lexing then you do not want to continue parsing. Just throw an exception not
/// under <seealso cref="RecognitionException"/> and Java will naturally toss
/// you all the way out of the recognizers. If you want to continue lexing then
/// you should not throw an exception to the parser--it has already requested a
/// token. Keep lexing until you get a valid one. Just report errors and keep
/// going, looking for a valid token.
/// </summary>
class ANTLR4CPP_PUBLIC TokenSource {
public:
virtual ~TokenSource();
/// Return a <seealso cref="Token"/> object from your input stream (usually a
/// <seealso cref="CharStream"/>). Do not fail/return upon lexing error; keep
/// chewing on the characters until you get a good one; errors are not passed
/// through to the parser.
virtual std::unique_ptr<Token> nextToken() = 0;
/// <summary>
/// Get the line number for the current position in the input stream. The
/// first line in the input is line 1.
/// </summary>
/// <returns> The line number for the current position in the input stream, or
/// 0 if the current token source does not track line numbers. </returns>
virtual size_t getLine() const = 0;
/// <summary>
/// Get the index into the current line for the current position in the input
/// stream. The first character on a line has position 0.
/// </summary>
/// <returns> The line number for the current position in the input stream, or
/// (sze_t)-1 if the current token source does not track character positions.
/// </returns>
virtual size_t getCharPositionInLine() = 0;
/// <summary>
/// Get the <seealso cref="CharStream"/> from which this token source is
/// currently providing tokens.
/// </summary>
/// <returns> The <seealso cref="CharStream"/> associated with the current
/// position in the input, or {@code null} if no input stream is available for
/// the token source. </returns>
virtual CharStream* getInputStream() = 0;
/// <summary>
/// Gets the name of the underlying input source. This method returns a
/// non-null, non-empty string. If such a name is not known, this method
/// returns <seealso cref="IntStream#UNKNOWN_SOURCE_NAME"/>.
/// </summary>
virtual std::string getSourceName() = 0;
/// <summary>
/// Set the <seealso cref="TokenFactory"/> this token source should use for
/// creating <seealso cref="Token"/> objects from the input.
/// </summary>
/// <param name="factory"> The <seealso cref="TokenFactory"/> to use for
/// creating tokens. </param>
template <typename T1>
void setTokenFactory(TokenFactory<T1>* /*factory*/) {}
/// <summary>
/// Gets the <seealso cref="TokenFactory"/> this token source is currently
/// using for creating <seealso cref="Token"/> objects from the input.
/// </summary>
/// <returns> The <seealso cref="TokenFactory"/> currently used by this token
/// source. </returns>
virtual Ref<TokenFactory<CommonToken>> getTokenFactory() = 0;
};
} // namespace antlr4

View File

@ -1,10 +0,0 @@
/* 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.
*/
#include "TokenStream.h"
using namespace antlr4;
TokenStream::~TokenStream() {}

View File

@ -1,138 +0,0 @@
/* 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.
*/
#pragma once
#include "IntStream.h"
namespace antlr4 {
/// <summary>
/// An <seealso cref="IntStream"/> whose symbols are <seealso cref="Token"/>
/// instances.
/// </summary>
class ANTLR4CPP_PUBLIC TokenStream : public IntStream {
/// <summary>
/// Get the <seealso cref="Token"/> instance associated with the value
/// returned by <seealso cref="#LA LA(k)"/>. This method has the same pre- and
/// post-conditions as <seealso cref="IntStream#LA"/>. In addition, when the
/// preconditions of this method are met, the return value is non-null and the
/// value of
/// {@code LT(k).getType()==LA(k)}.
/// </summary>
/// <seealso cref= IntStream#LA </seealso>
public:
virtual ~TokenStream();
virtual Token* LT(ssize_t k) = 0;
/// <summary>
/// Gets the <seealso cref="Token"/> at the specified {@code index} in the
/// stream. When the preconditions of this method are met, the return value is
/// non-null. <p/> The preconditions for this method are the same as the
/// preconditions of <seealso cref="IntStream#seek"/>. If the behavior of
/// {@code seek(index)} is unspecified for the current state and given {@code
/// index}, then the behavior of this method is also unspecified. <p/> The
/// symbol referred to by {@code index} differs from {@code seek()} only in
/// the case of filtering streams where {@code index} lies before the end of
/// the stream. Unlike {@code seek()}, this method does not adjust
/// {@code index} to point to a non-ignored symbol.
/// </summary>
/// <exception cref="IllegalArgumentException"> if {code index} is less than 0
/// </exception> <exception cref="UnsupportedOperationException"> if the
/// stream does not support retrieving the token at the specified index
/// </exception>
virtual Token* get(size_t index) const = 0;
/// Gets the underlying TokenSource which provides tokens for this stream.
virtual TokenSource* getTokenSource() const = 0;
/// <summary>
/// Return the text of all tokens within the specified {@code interval}. This
/// method behaves like the following code (including potential exceptions
/// for violating preconditions of <seealso cref="#get"/>, but may be
/// optimized by the specific implementation.
///
/// <pre>
/// TokenStream stream = ...;
/// String text = "";
/// for (int i = interval.a; i <= interval.b; i++) {
/// text += stream.get(i).getText();
/// }
/// </pre>
/// </summary>
/// <param name="interval"> The interval of tokens within this stream to get
/// text for. </param> <returns> The text of all tokens within the specified
/// interval in this stream.
/// </returns>
/// <exception cref="NullPointerException"> if {@code interval} is {@code
/// null} </exception>
virtual std::string getText(const misc::Interval& interval) = 0;
/// <summary>
/// Return the text of all tokens in the stream. This method behaves like the
/// following code, including potential exceptions from the calls to
/// <seealso cref="IntStream#size"/> and <seealso cref="#getText(Interval)"/>,
/// but may be optimized by the specific implementation.
///
/// <pre>
/// TokenStream stream = ...;
/// String text = stream.getText(new Interval(0, stream.size()));
/// </pre>
/// </summary>
/// <returns> The text of all tokens in the stream. </returns>
virtual std::string getText() = 0;
/// <summary>
/// Return the text of all tokens in the source interval of the specified
/// context. This method behaves like the following code, including potential
/// exceptions from the call to <seealso cref="#getText(Interval)"/>, but may
/// be optimized by the specific implementation.
/// </p>
/// If {@code ctx.getSourceInterval()} does not return a valid interval of
/// tokens provided by this stream, the behavior is unspecified.
///
/// <pre>
/// TokenStream stream = ...;
/// String text = stream.getText(ctx.getSourceInterval());
/// </pre>
/// </summary>
/// <param name="ctx"> The context providing the source interval of tokens to
/// get text for. </param> <returns> The text of all tokens within the source
/// interval of {@code ctx}. </returns>
virtual std::string getText(RuleContext* ctx) = 0;
/// <summary>
/// Return the text of all tokens in this stream between {@code start} and
/// {@code stop} (inclusive).
/// <p/>
/// If the specified {@code start} or {@code stop} token was not provided by
/// this stream, or if the {@code stop} occurred before the {@code start}
/// token, the behavior is unspecified.
/// <p/>
/// For streams which ensure that the <seealso cref="Token#getTokenIndex"/>
/// method is accurate for all of its provided tokens, this method behaves
/// like the following code. Other streams may implement this method in other
/// ways provided the behavior is consistent with this at a high level.
///
/// <pre>
/// TokenStream stream = ...;
/// String text = "";
/// for (int i = start.getTokenIndex(); i <= stop.getTokenIndex(); i++) {
/// text += stream.get(i).getText();
/// }
/// </pre>
/// </summary>
/// <param name="start"> The first token in the interval to get text for.
/// </param> <param name="stop"> The last token in the interval to get text
/// for (inclusive). </param> <returns> The text of all tokens lying between
/// the specified {@code start} and {@code stop} tokens.
/// </returns>
/// <exception cref="UnsupportedOperationException"> if this stream does not
/// support this method for the specified tokens </exception>
virtual std::string getText(Token* start, Token* stop) = 0;
};
} // namespace antlr4

View File

@ -1,463 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "Token.h"
#include "TokenStream.h"
#include "misc/Interval.h"
#include "TokenStreamRewriter.h"
using namespace antlr4;
using antlr4::misc::Interval;
TokenStreamRewriter::RewriteOperation::RewriteOperation(
TokenStreamRewriter* outerInstance_, size_t index_)
: outerInstance(outerInstance_) {
InitializeInstanceFields();
this->index = index_;
}
TokenStreamRewriter::RewriteOperation::RewriteOperation(
TokenStreamRewriter* outerInstance_, size_t index_,
const std::string& text_)
: outerInstance(outerInstance_) {
InitializeInstanceFields();
this->index = index_;
this->text = text_;
}
TokenStreamRewriter::RewriteOperation::~RewriteOperation() {}
size_t TokenStreamRewriter::RewriteOperation::execute(std::string* /*buf*/) {
return index;
}
std::string TokenStreamRewriter::RewriteOperation::toString() {
std::string opName = "TokenStreamRewriter";
size_t dollarIndex = opName.find('$');
opName = opName.substr(dollarIndex + 1, opName.length() - (dollarIndex + 1));
return "<" + opName + "@" +
outerInstance->tokens->get(dollarIndex)->getText() + ":\"" + text +
"\">";
}
void TokenStreamRewriter::RewriteOperation::InitializeInstanceFields() {
instructionIndex = 0;
index = 0;
}
TokenStreamRewriter::InsertBeforeOp::InsertBeforeOp(
TokenStreamRewriter* outerInstance_, size_t index_,
const std::string& text_)
: RewriteOperation(outerInstance_, index_, text_),
outerInstance(outerInstance_) {}
size_t TokenStreamRewriter::InsertBeforeOp::execute(std::string* buf) {
buf->append(text);
if (outerInstance->tokens->get(index)->getType() != Token::EOF) {
buf->append(outerInstance->tokens->get(index)->getText());
}
return index + 1;
}
TokenStreamRewriter::ReplaceOp::ReplaceOp(TokenStreamRewriter* outerInstance_,
size_t from, size_t to,
const std::string& text)
: RewriteOperation(outerInstance_, from, text),
outerInstance(outerInstance_) {
InitializeInstanceFields();
lastIndex = to;
}
size_t TokenStreamRewriter::ReplaceOp::execute(std::string* buf) {
buf->append(text);
return lastIndex + 1;
}
std::string TokenStreamRewriter::ReplaceOp::toString() {
if (text.empty()) {
return "<DeleteOp@" + outerInstance->tokens->get(index)->getText() + ".." +
outerInstance->tokens->get(lastIndex)->getText() + ">";
}
return "<ReplaceOp@" + outerInstance->tokens->get(index)->getText() + ".." +
outerInstance->tokens->get(lastIndex)->getText() + ":\"" + text +
"\">";
}
void TokenStreamRewriter::ReplaceOp::InitializeInstanceFields() {
lastIndex = 0;
}
//------------------ TokenStreamRewriter
//-------------------------------------------------------------------------------
const std::string TokenStreamRewriter::DEFAULT_PROGRAM_NAME = "default";
TokenStreamRewriter::TokenStreamRewriter(TokenStream* tokens_)
: tokens(tokens_) {
_programs[DEFAULT_PROGRAM_NAME].reserve(PROGRAM_INIT_SIZE);
}
TokenStreamRewriter::~TokenStreamRewriter() {
for (auto program : _programs) {
for (auto operation : program.second) {
delete operation;
}
}
}
TokenStream* TokenStreamRewriter::getTokenStream() { return tokens; }
void TokenStreamRewriter::rollback(size_t instructionIndex) {
rollback(DEFAULT_PROGRAM_NAME, instructionIndex);
}
void TokenStreamRewriter::rollback(const std::string& programName,
size_t instructionIndex) {
std::vector<RewriteOperation*> is = _programs[programName];
if (is.size() > 0) {
_programs.insert({programName, std::vector<RewriteOperation*>(
is.begin() + MIN_TOKEN_INDEX,
is.begin() + instructionIndex)});
}
}
void TokenStreamRewriter::deleteProgram() {
deleteProgram(DEFAULT_PROGRAM_NAME);
}
void TokenStreamRewriter::deleteProgram(const std::string& programName) {
rollback(programName, MIN_TOKEN_INDEX);
}
void TokenStreamRewriter::insertAfter(Token* t, const std::string& text) {
insertAfter(DEFAULT_PROGRAM_NAME, t, text);
}
void TokenStreamRewriter::insertAfter(size_t index, const std::string& text) {
insertAfter(DEFAULT_PROGRAM_NAME, index, text);
}
void TokenStreamRewriter::insertAfter(const std::string& programName, Token* t,
const std::string& text) {
insertAfter(programName, t->getTokenIndex(), text);
}
void TokenStreamRewriter::insertAfter(const std::string& programName,
size_t index, const std::string& text) {
// to insert after, just insert before next index (even if past end)
insertBefore(programName, index + 1, text);
}
void TokenStreamRewriter::insertBefore(Token* t, const std::string& text) {
insertBefore(DEFAULT_PROGRAM_NAME, t, text);
}
void TokenStreamRewriter::insertBefore(size_t index, const std::string& text) {
insertBefore(DEFAULT_PROGRAM_NAME, index, text);
}
void TokenStreamRewriter::insertBefore(const std::string& programName, Token* t,
const std::string& text) {
insertBefore(programName, t->getTokenIndex(), text);
}
void TokenStreamRewriter::insertBefore(const std::string& programName,
size_t index, const std::string& text) {
RewriteOperation* op =
new InsertBeforeOp(this, index, text); /* mem-check: deleted in d-tor */
std::vector<RewriteOperation*>& rewrites = getProgram(programName);
op->instructionIndex = rewrites.size();
rewrites.push_back(op);
}
void TokenStreamRewriter::replace(size_t index, const std::string& text) {
replace(DEFAULT_PROGRAM_NAME, index, index, text);
}
void TokenStreamRewriter::replace(size_t from, size_t to,
const std::string& text) {
replace(DEFAULT_PROGRAM_NAME, from, to, text);
}
void TokenStreamRewriter::replace(Token* indexT, const std::string& text) {
replace(DEFAULT_PROGRAM_NAME, indexT, indexT, text);
}
void TokenStreamRewriter::replace(Token* from, Token* to,
const std::string& text) {
replace(DEFAULT_PROGRAM_NAME, from, to, text);
}
void TokenStreamRewriter::replace(const std::string& programName, size_t from,
size_t to, const std::string& text) {
if (from > to || to >= tokens->size()) {
throw IllegalArgumentException(
"replace: range invalid: " + std::to_string(from) + ".." +
std::to_string(to) + "(size = " + std::to_string(tokens->size()) + ")");
}
RewriteOperation* op =
new ReplaceOp(this, from, to, text); /* mem-check: deleted in d-tor */
std::vector<RewriteOperation*>& rewrites = getProgram(programName);
op->instructionIndex = rewrites.size();
rewrites.push_back(op);
}
void TokenStreamRewriter::replace(const std::string& programName, Token* from,
Token* to, const std::string& text) {
replace(programName, from->getTokenIndex(), to->getTokenIndex(), text);
}
void TokenStreamRewriter::Delete(size_t index) {
Delete(DEFAULT_PROGRAM_NAME, index, index);
}
void TokenStreamRewriter::Delete(size_t from, size_t to) {
Delete(DEFAULT_PROGRAM_NAME, from, to);
}
void TokenStreamRewriter::Delete(Token* indexT) {
Delete(DEFAULT_PROGRAM_NAME, indexT, indexT);
}
void TokenStreamRewriter::Delete(Token* from, Token* to) {
Delete(DEFAULT_PROGRAM_NAME, from, to);
}
void TokenStreamRewriter::Delete(const std::string& programName, size_t from,
size_t to) {
std::string nullString;
replace(programName, from, to, nullString);
}
void TokenStreamRewriter::Delete(const std::string& programName, Token* from,
Token* to) {
std::string nullString;
replace(programName, from, to, nullString);
}
size_t TokenStreamRewriter::getLastRewriteTokenIndex() {
return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
}
size_t TokenStreamRewriter::getLastRewriteTokenIndex(
const std::string& programName) {
if (_lastRewriteTokenIndexes.find(programName) ==
_lastRewriteTokenIndexes.end()) {
return INVALID_INDEX;
}
return _lastRewriteTokenIndexes[programName];
}
void TokenStreamRewriter::setLastRewriteTokenIndex(
const std::string& programName, size_t i) {
_lastRewriteTokenIndexes.insert({programName, i});
}
std::vector<TokenStreamRewriter::RewriteOperation*>&
TokenStreamRewriter::getProgram(const std::string& name) {
auto iterator = _programs.find(name);
if (iterator == _programs.end()) {
return initializeProgram(name);
}
return iterator->second;
}
std::vector<TokenStreamRewriter::RewriteOperation*>&
TokenStreamRewriter::initializeProgram(const std::string& name) {
_programs[name].reserve(PROGRAM_INIT_SIZE);
return _programs[name];
}
std::string TokenStreamRewriter::getText() {
return getText(DEFAULT_PROGRAM_NAME, Interval(0UL, tokens->size() - 1));
}
std::string TokenStreamRewriter::getText(std::string programName) {
return getText(programName, Interval(0UL, tokens->size() - 1));
}
std::string TokenStreamRewriter::getText(const Interval& interval) {
return getText(DEFAULT_PROGRAM_NAME, interval);
}
std::string TokenStreamRewriter::getText(const std::string& programName,
const Interval& interval) {
std::vector<TokenStreamRewriter::RewriteOperation*>& rewrites =
_programs[programName];
size_t start = interval.a;
size_t stop = interval.b;
// ensure start/end are in range
if (stop > tokens->size() - 1) {
stop = tokens->size() - 1;
}
if (start == INVALID_INDEX) {
start = 0;
}
if (rewrites.empty() || rewrites.empty()) {
return tokens->getText(interval); // no instructions to execute
}
std::string buf;
// First, optimize instruction stream
std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> indexToOp =
reduceToSingleOperationPerIndex(rewrites);
// Walk buffer, executing instructions and emitting tokens
size_t i = start;
while (i <= stop && i < tokens->size()) {
RewriteOperation* op = indexToOp[i];
indexToOp.erase(i); // remove so any left have index size-1
Token* t = tokens->get(i);
if (op == nullptr) {
// no operation at that index, just dump token
if (t->getType() != Token::EOF) {
buf.append(t->getText());
}
i++; // move to next token
} else {
i = op->execute(&buf); // execute operation and skip
}
}
// include stuff after end if it's last index in buffer
// So, if they did an insertAfter(lastValidIndex, "foo"), include
// foo if end==lastValidIndex.
if (stop == tokens->size() - 1) {
// Scan any remaining operations after last token
// should be included (they will be inserts).
for (auto op : indexToOp) {
if (op.second->index >= tokens->size() - 1) {
buf.append(op.second->text);
}
}
}
return buf;
}
std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*>
TokenStreamRewriter::reduceToSingleOperationPerIndex(
std::vector<TokenStreamRewriter::RewriteOperation*>& rewrites) {
// WALK REPLACES
for (size_t i = 0; i < rewrites.size(); ++i) {
TokenStreamRewriter::RewriteOperation* op = rewrites[i];
ReplaceOp* rop = dynamic_cast<ReplaceOp*>(op);
if (rop == nullptr) continue;
// Wipe prior inserts within range
std::vector<InsertBeforeOp*> inserts =
getKindOfOps<InsertBeforeOp>(rewrites, i);
for (auto iop : inserts) {
if (iop->index == rop->index) {
// E.g., insert before 2, delete 2..2; update replace
// text to include insert before, kill insert
delete rewrites[iop->instructionIndex];
rewrites[iop->instructionIndex] = nullptr;
rop->text = iop->text + (!rop->text.empty() ? rop->text : "");
} else if (iop->index > rop->index && iop->index <= rop->lastIndex) {
// delete insert as it's a no-op.
delete rewrites[iop->instructionIndex];
rewrites[iop->instructionIndex] = nullptr;
}
}
// Drop any prior replaces contained within
std::vector<ReplaceOp*> prevReplaces = getKindOfOps<ReplaceOp>(rewrites, i);
for (auto prevRop : prevReplaces) {
if (prevRop->index >= rop->index &&
prevRop->lastIndex <= rop->lastIndex) {
// delete replace as it's a no-op.
delete rewrites[prevRop->instructionIndex];
rewrites[prevRop->instructionIndex] = nullptr;
continue;
}
// throw exception unless disjoint or identical
bool disjoint =
prevRop->lastIndex < rop->index || prevRop->index > rop->lastIndex;
bool same =
prevRop->index == rop->index && prevRop->lastIndex == rop->lastIndex;
// Delete special case of replace (text==null):
// D.i-j.u D.x-y.v | boundaries overlap combine to
// max(min)..max(right)
if (prevRop->text.empty() && rop->text.empty() && !disjoint) {
delete rewrites[prevRop->instructionIndex];
rewrites[prevRop->instructionIndex] = nullptr; // kill first delete
rop->index = std::min(prevRop->index, rop->index);
rop->lastIndex = std::max(prevRop->lastIndex, rop->lastIndex);
std::cout << "new rop " << rop << std::endl;
} else if (!disjoint && !same) {
throw IllegalArgumentException(
"replace op boundaries of " + rop->toString() +
" overlap with previous " + prevRop->toString());
}
}
}
// WALK INSERTS
for (size_t i = 0; i < rewrites.size(); i++) {
InsertBeforeOp* iop = dynamic_cast<InsertBeforeOp*>(rewrites[i]);
if (iop == nullptr) continue;
// combine current insert with prior if any at same index
std::vector<InsertBeforeOp*> prevInserts =
getKindOfOps<InsertBeforeOp>(rewrites, i);
for (auto prevIop : prevInserts) {
if (prevIop->index == iop->index) { // combine objects
// convert to strings...we're in
// process of toString'ing whole
// token buffer so no lazy eval issue
// with any templates
iop->text = catOpText(&iop->text, &prevIop->text);
// delete redundant prior insert
delete rewrites[prevIop->instructionIndex];
rewrites[prevIop->instructionIndex] = nullptr;
}
}
// look for replaces where iop.index is in range; error
std::vector<ReplaceOp*> prevReplaces = getKindOfOps<ReplaceOp>(rewrites, i);
for (auto rop : prevReplaces) {
if (iop->index == rop->index) {
rop->text = catOpText(&iop->text, &rop->text);
delete rewrites[i];
rewrites[i] = nullptr; // delete current insert
continue;
}
if (iop->index >= rop->index && iop->index <= rop->lastIndex) {
throw IllegalArgumentException("insert op " + iop->toString() +
" within boundaries of previous " +
rop->toString());
}
}
}
std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> m;
for (TokenStreamRewriter::RewriteOperation* op : rewrites) {
if (op == nullptr) { // ignore deleted ops
continue;
}
if (m.count(op->index) > 0) {
throw RuntimeException("should only be one op per index");
}
m[op->index] = op;
}
return m;
}
std::string TokenStreamRewriter::catOpText(std::string* a, std::string* b) {
std::string x = "";
std::string y = "";
if (a != nullptr) {
x = *a;
}
if (b != nullptr) {
y = *b;
}
return x + y;
}

View File

@ -1,307 +0,0 @@
/* 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.
*/
#pragma once
namespace antlr4 {
/**
* Useful for rewriting out a buffered input token stream after doing some
* augmentation or other manipulations on it.
*
* <p>
* You can insert stuff, replace, and delete chunks. Note that the operations
* are done lazily--only if you convert the buffer to a {@link String} with
* {@link TokenStream#getText()}. This is very efficient because you are not
* moving data around all the time. As the buffer of tokens is converted to
* strings, the {@link #getText()} method(s) scan the input token stream and
* check to see if there is an operation at the current index. If so, the
* operation is done and then normal {@link String} rendering continues on the
* buffer. This is like having multiple Turing machine instruction streams
* (programs) operating on a single input tape. :)</p>
*
* <p>
* This rewriter makes no modifications to the token stream. It does not ask the
* stream to fill itself up nor does it advance the input cursor. The token
* stream {@link TokenStream#index()} will return the same value before and
* after any {@link #getText()} call.</p>
*
* <p>
* The rewriter only works on tokens that you have in the buffer and ignores the
* current input cursor. If you are buffering tokens on-demand, calling
* {@link #getText()} halfway through the input will only do rewrites for those
* tokens in the first half of the file.</p>
*
* <p>
* Since the operations are done lazily at {@link #getText}-time, operations do
* not screw up the token index values. That is, an insert operation at token
* index {@code i} does not change the index values for tokens
* {@code i}+1..n-1.</p>
*
* <p>
* Because operations never actually alter the buffer, you may always get the
* original token stream back without undoing anything. Since the instructions
* are queued up, you can easily simulate transactions and roll back any changes
* if there is an error just by removing instructions. For example,</p>
*
* <pre>
* CharStream input = new ANTLRFileStream("input");
* TLexer lex = new TLexer(input);
* CommonTokenStream tokens = new CommonTokenStream(lex);
* T parser = new T(tokens);
* TokenStreamRewriter rewriter = new TokenStreamRewriter(tokens);
* parser.startRule();
* </pre>
*
* <p>
* Then in the rules, you can execute (assuming rewriter is visible):</p>
*
* <pre>
* Token t,u;
* ...
* rewriter.insertAfter(t, "text to put after t");}
* rewriter.insertAfter(u, "text after u");}
* System.out.println(rewriter.getText());
* </pre>
*
* <p>
* You can also have multiple "instruction streams" and get multiple rewrites
* from a single pass over the input. Just name the instruction streams and use
* that name again when printing the buffer. This could be useful for generating
* a C file and also its header file--all from the same buffer:</p>
*
* <pre>
* rewriter.insertAfter("pass1", t, "text to put after t");}
* rewriter.insertAfter("pass2", u, "text after u");}
* System.out.println(rewriter.getText("pass1"));
* System.out.println(rewriter.getText("pass2"));
* </pre>
*
* <p>
* If you don't use named rewrite streams, a "default" stream is used as the
* first example shows.</p>
*/
class ANTLR4CPP_PUBLIC TokenStreamRewriter {
public:
static const std::string DEFAULT_PROGRAM_NAME;
static const size_t PROGRAM_INIT_SIZE = 100;
static const size_t MIN_TOKEN_INDEX = 0;
TokenStreamRewriter(TokenStream* tokens);
virtual ~TokenStreamRewriter();
TokenStream* getTokenStream();
virtual void rollback(size_t instructionIndex);
/// Rollback the instruction stream for a program so that
/// the indicated instruction (via instructionIndex) is no
/// longer in the stream. UNTESTED!
virtual void rollback(const std::string& programName,
size_t instructionIndex);
virtual void deleteProgram();
/// Reset the program so that no instructions exist.
virtual void deleteProgram(const std::string& programName);
virtual void insertAfter(Token* t, const std::string& text);
virtual void insertAfter(size_t index, const std::string& text);
virtual void insertAfter(const std::string& programName, Token* t,
const std::string& text);
virtual void insertAfter(const std::string& programName, size_t index,
const std::string& text);
virtual void insertBefore(Token* t, const std::string& text);
virtual void insertBefore(size_t index, const std::string& text);
virtual void insertBefore(const std::string& programName, Token* t,
const std::string& text);
virtual void insertBefore(const std::string& programName, size_t index,
const std::string& text);
virtual void replace(size_t index, const std::string& text);
virtual void replace(size_t from, size_t to, const std::string& text);
virtual void replace(Token* indexT, const std::string& text);
virtual void replace(Token* from, Token* to, const std::string& text);
virtual void replace(const std::string& programName, size_t from, size_t to,
const std::string& text);
virtual void replace(const std::string& programName, Token* from, Token* to,
const std::string& text);
virtual void Delete(size_t index);
virtual void Delete(size_t from, size_t to);
virtual void Delete(Token* indexT);
virtual void Delete(Token* from, Token* to);
virtual void Delete(const std::string& programName, size_t from, size_t to);
virtual void Delete(const std::string& programName, Token* from, Token* to);
virtual size_t getLastRewriteTokenIndex();
/// Return the text from the original tokens altered per the
/// instructions given to this rewriter.
virtual std::string getText();
/** Return the text from the original tokens altered per the
* instructions given to this rewriter in programName.
*/
std::string getText(std::string programName);
/// Return the text associated with the tokens in the interval from the
/// original token stream but with the alterations given to this rewriter.
/// The interval refers to the indexes in the original token stream.
/// We do not alter the token stream in any way, so the indexes
/// and intervals are still consistent. Includes any operations done
/// to the first and last token in the interval. So, if you did an
/// insertBefore on the first token, you would get that insertion.
/// The same is true if you do an insertAfter the stop token.
virtual std::string getText(const misc::Interval& interval);
virtual std::string getText(const std::string& programName,
const misc::Interval& interval);
protected:
class RewriteOperation {
public:
/// What index into rewrites List are we?
size_t index;
std::string text;
/// Token buffer index.
size_t instructionIndex;
RewriteOperation(TokenStreamRewriter* outerInstance, size_t index);
RewriteOperation(TokenStreamRewriter* outerInstance, size_t index,
const std::string& text);
virtual ~RewriteOperation();
/// Execute the rewrite operation by possibly adding to the buffer.
/// Return the index of the next token to operate on.
virtual size_t execute(std::string* buf);
virtual std::string toString();
private:
TokenStreamRewriter* const outerInstance;
void InitializeInstanceFields();
};
class InsertBeforeOp : public RewriteOperation {
private:
TokenStreamRewriter* const outerInstance;
public:
InsertBeforeOp(TokenStreamRewriter* outerInstance, size_t index,
const std::string& text);
virtual size_t execute(std::string* buf) override;
};
class ReplaceOp : public RewriteOperation {
private:
TokenStreamRewriter* const outerInstance;
public:
size_t lastIndex;
ReplaceOp(TokenStreamRewriter* outerInstance, size_t from, size_t to,
const std::string& text);
virtual size_t execute(std::string* buf) override;
virtual std::string toString() override;
private:
void InitializeInstanceFields();
};
/// Our source stream
TokenStream* const tokens;
/// You may have multiple, named streams of rewrite operations.
/// I'm calling these things "programs."
/// Maps String (name) -> rewrite (List)
std::map<std::string, std::vector<RewriteOperation*>> _programs;
/// <summary>
/// Map String (program name) -> Integer index </summary>
std::map<std::string, size_t> _lastRewriteTokenIndexes;
virtual size_t getLastRewriteTokenIndex(const std::string& programName);
virtual void setLastRewriteTokenIndex(const std::string& programName,
size_t i);
virtual std::vector<RewriteOperation*>& getProgram(const std::string& name);
/// <summary>
/// We need to combine operations and report invalid operations (like
/// overlapping replaces that are not completed nested). Inserts to
/// same index need to be combined etc... Here are the cases:
///
/// I.i.u I.j.v leave alone, nonoverlapping
/// I.i.u I.i.v combine: Iivu
///
/// R.i-j.u R.x-y.v | i-j in x-y delete first R
/// R.i-j.u R.i-j.v delete first R
/// R.i-j.u R.x-y.v | x-y in i-j ERROR
/// R.i-j.u R.x-y.v | boundaries overlap ERROR
///
/// Delete special case of replace (text==null):
/// D.i-j.u D.x-y.v | boundaries overlap combine to
/// max(min)..max(right)
///
/// I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before
/// we're not deleting i)
/// I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping
/// R.x-y.v I.i.u | i in x-y ERROR
/// R.x-y.v I.x.u R.x-y.uv (combine, delete I)
/// R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping
///
/// I.i.u = insert u before op @ index i
/// R.x-y.u = replace x-y indexed tokens with u
///
/// First we need to examine replaces. For any replace op:
///
/// 1. wipe out any insertions before op within that range.
/// 2. Drop any replace op before that is contained completely within
/// that range.
/// 3. Throw exception upon boundary overlap with any previous replace.
///
/// Then we can deal with inserts:
///
/// 1. for any inserts to same index, combine even if not adjacent.
/// 2. for any prior replace with same left boundary, combine this
/// insert with replace and delete this replace.
/// 3. throw exception if index in same range as previous replace
///
/// Don't actually delete; make op null in list. Easier to walk list.
/// Later we can throw as we add to index -> op map.
///
/// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
/// inserted stuff would be before the replace range. But, if you
/// add tokens in front of a method body '{' and then delete the method
/// body, I think the stuff before the '{' you added should disappear too.
///
/// Return a map from token index to operation.
/// </summary>
virtual std::unordered_map<size_t, RewriteOperation*>
reduceToSingleOperationPerIndex(std::vector<RewriteOperation*>& rewrites);
virtual std::string catOpText(std::string* a, std::string* b);
/// Get all operations before an index of a particular kind.
template <typename T>
std::vector<T*> getKindOfOps(std::vector<RewriteOperation*> rewrites,
size_t before) {
std::vector<T*> ops;
for (size_t i = 0; i < before && i < rewrites.size(); i++) {
T* op = dynamic_cast<T*>(rewrites[i]);
if (op == nullptr) { // ignore deleted or non matching entries
continue;
}
ops.push_back(op);
}
return ops;
}
private:
std::vector<RewriteOperation*>& initializeProgram(const std::string& name);
};
} // namespace antlr4

View File

@ -1,215 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "misc/Interval.h"
#include "support/StringUtils.h"
#include "UnbufferedCharStream.h"
using namespace antlrcpp;
using namespace antlr4;
using namespace antlr4::misc;
UnbufferedCharStream::UnbufferedCharStream(std::wistream& input)
: _input(input) {
InitializeInstanceFields();
// The vector's size is what used to be n in Java code.
fill(1); // prime
}
void UnbufferedCharStream::consume() {
if (LA(1) == EOF) {
throw IllegalStateException("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 == _data.size() - 1 && _numMarkers == 0) {
size_t capacity = _data.capacity();
_data.clear();
_data.reserve(capacity);
_p = 0;
_lastCharBufferStart = _lastChar;
} else {
_p++;
}
_currentCharIndex++;
sync(1);
}
void UnbufferedCharStream::sync(size_t want) {
if (_p + want <= _data.size()) // Already enough data loaded?
return;
fill(_p + want - _data.size());
}
size_t UnbufferedCharStream::fill(size_t n) {
for (size_t i = 0; i < n; i++) {
if (_data.size() > 0 && _data.back() == 0xFFFF) {
return i;
}
try {
char32_t c = nextChar();
add(c);
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
} catch (IOException& ioe) {
// throw_with_nested is not available before VS 2015.
throw ioe;
#else
} catch (IOException& /*ioe*/) {
std::throw_with_nested(RuntimeException());
#endif
}
}
return n;
}
char32_t UnbufferedCharStream::nextChar() {
wchar_t result = 0;
_input >> result;
return result;
}
void UnbufferedCharStream::add(char32_t c) { _data += c; }
size_t UnbufferedCharStream::LA(ssize_t i) {
if (i == -1) { // special case
return _lastChar;
}
// We can look back only as many chars as we have buffered.
ssize_t index = static_cast<ssize_t>(_p) + i - 1;
if (index < 0) {
throw IndexOutOfBoundsException();
}
if (i > 0) {
sync(static_cast<size_t>(i)); // No need to sync if we look back.
}
if (static_cast<size_t>(index) >= _data.size()) {
return EOF;
}
if (_data[static_cast<size_t>(index)] == 0xFFFF) {
return EOF;
}
return _data[static_cast<size_t>(index)];
}
ssize_t UnbufferedCharStream::mark() {
if (_numMarkers == 0) {
_lastCharBufferStart = _lastChar;
}
ssize_t mark = -static_cast<ssize_t>(_numMarkers) - 1;
_numMarkers++;
return mark;
}
void UnbufferedCharStream::release(ssize_t marker) {
ssize_t expectedMark = -static_cast<ssize_t>(_numMarkers);
if (marker != expectedMark) {
throw IllegalStateException("release() called with an invalid marker.");
}
_numMarkers--;
if (_numMarkers == 0 && _p > 0) {
_data.erase(0, _p);
_p = 0;
_lastCharBufferStart = _lastChar;
}
}
size_t UnbufferedCharStream::index() { return _currentCharIndex; }
void UnbufferedCharStream::seek(size_t index) {
if (index == _currentCharIndex) {
return;
}
if (index > _currentCharIndex) {
sync(index - _currentCharIndex);
index = std::min(index, getBufferStartIndex() + _data.size() - 1);
}
// index == to bufferStartIndex should set p to 0
ssize_t i =
static_cast<ssize_t>(index) - static_cast<ssize_t>(getBufferStartIndex());
if (i < 0) {
throw IllegalArgumentException(
std::string("cannot seek to negative index ") + std::to_string(index));
} else if (i >= static_cast<ssize_t>(_data.size())) {
throw UnsupportedOperationException(
"Seek to index outside buffer: " + std::to_string(index) + " not in " +
std::to_string(getBufferStartIndex()) + ".." +
std::to_string(getBufferStartIndex() + _data.size()));
}
_p = static_cast<size_t>(i);
_currentCharIndex = index;
if (_p == 0) {
_lastChar = _lastCharBufferStart;
} else {
_lastChar = _data[_p - 1];
}
}
size_t UnbufferedCharStream::size() {
throw UnsupportedOperationException("Unbuffered stream cannot know its size");
}
std::string UnbufferedCharStream::getSourceName() const {
if (name.empty()) {
return UNKNOWN_SOURCE_NAME;
}
return name;
}
std::string UnbufferedCharStream::getText(const misc::Interval& interval) {
if (interval.a < 0 || interval.b >= interval.a - 1) {
throw IllegalArgumentException("invalid interval");
}
size_t bufferStartIndex = getBufferStartIndex();
if (!_data.empty() && _data.back() == 0xFFFF) {
if (interval.a + interval.length() > bufferStartIndex + _data.size()) {
throw IllegalArgumentException(
"the interval extends past the end of the stream");
}
}
if (interval.a < static_cast<ssize_t>(bufferStartIndex) ||
interval.b >= ssize_t(bufferStartIndex + _data.size())) {
throw UnsupportedOperationException(
"interval " + interval.toString() +
" outside buffer: " + std::to_string(bufferStartIndex) + ".." +
std::to_string(bufferStartIndex + _data.size() - 1));
}
// convert from absolute to local index
size_t i = interval.a - bufferStartIndex;
return utf32_to_utf8(_data.substr(i, interval.length()));
}
size_t UnbufferedCharStream::getBufferStartIndex() const {
return _currentCharIndex - _p;
}
void UnbufferedCharStream::InitializeInstanceFields() {
_p = 0;
_numMarkers = 0;
_lastChar = 0;
_lastCharBufferStart = 0;
_currentCharIndex = 0;
}

View File

@ -1,125 +0,0 @@
/* 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.
*/
#pragma once
#include "CharStream.h"
namespace antlr4 {
/// 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.
class ANTLR4CPP_PUBLIC UnbufferedCharStream : public CharStream {
public:
/// The name or source of this char stream.
std::string name;
UnbufferedCharStream(std::wistream& input);
virtual void consume() override;
virtual size_t LA(ssize_t i) override;
/// <summary>
/// Return a marker that we can release later.
/// <p/>
/// 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.
/// </summary>
virtual ssize_t mark() override;
/// <summary>
/// Decrement number of markers, resetting buffer if we hit 0. </summary>
/// <param name="marker"> </param>
virtual void release(ssize_t marker) override;
virtual size_t index() override;
/// <summary>
/// Seek to absolute character index, which might not be in the current
/// sliding window. Move {@code p} to {@code index-bufferStartIndex}.
/// </summary>
virtual void seek(size_t index) override;
virtual size_t size() override;
virtual std::string getSourceName() const override;
virtual std::string getText(const misc::Interval& interval) override;
protected:
/// A moving window buffer of the data being scanned. While there's a marker,
/// we keep adding to buffer. Otherwise, <seealso cref="#consume consume()"/>
/// resets so we start filling at index 0 again.
// UTF-32 encoded.
#if defined(_MSC_VER) && _MSC_VER == 1900
i32string _data; // Custom type for VS 2015.
typedef __int32 storage_type;
#else
std::u32string _data;
typedef char32_t storage_type;
#endif
/// <summary>
/// 0..n-1 index into <seealso cref="#data data"/> of next character.
/// <p/>
/// The {@code LA(1)} character is {@code data[p]}. If {@code p == n}, we are
/// out of buffered characters.
/// </summary>
size_t _p;
/// <summary>
/// Count up with <seealso cref="#mark mark()"/> and down with
/// <seealso cref="#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]}.
/// </summary>
size_t _numMarkers;
/// This is the {@code LA(-1)} character for the current position.
size_t _lastChar; // UTF-32
/// <summary>
/// When {@code numMarkers > 0}, this is the {@code LA(-1)} character for the
/// first character in <seealso cref="#data data"/>. Otherwise, this is
/// unspecified.
/// </summary>
size_t _lastCharBufferStart; // UTF-32
/// <summary>
/// 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.
/// </summary>
size_t _currentCharIndex;
std::wistream& _input;
/// <summary>
/// Make sure we have 'want' elements from current position <seealso cref="#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}.
/// </summary>
virtual void sync(size_t want);
/// <summary>
/// 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.
/// </summary>
virtual size_t fill(size_t n);
/// Override to provide different source of characters than
/// <seealso cref="#input input"/>.
virtual char32_t nextChar();
virtual void add(char32_t c);
size_t getBufferStartIndex() const;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,257 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "RuleContext.h"
#include "Token.h"
#include "TokenSource.h"
#include "WritableToken.h"
#include "assert.h"
#include "misc/Interval.h"
#include "support/Arrays.h"
#include "UnbufferedTokenStream.h"
using namespace antlr4;
UnbufferedTokenStream::UnbufferedTokenStream(TokenSource* tokenSource)
: UnbufferedTokenStream(tokenSource, 256) {}
UnbufferedTokenStream::UnbufferedTokenStream(TokenSource* tokenSource,
int /*bufferSize*/)
: _tokenSource(tokenSource),
_lastToken(nullptr),
_lastTokenBufferStart(nullptr) {
InitializeInstanceFields();
fill(1); // prime the pump
}
UnbufferedTokenStream::~UnbufferedTokenStream() {}
Token* UnbufferedTokenStream::get(size_t i) const { // get absolute index
size_t bufferStartIndex = getBufferStartIndex();
if (i < bufferStartIndex || i >= bufferStartIndex + _tokens.size()) {
throw IndexOutOfBoundsException(
std::string("get(") + std::to_string(i) +
std::string(") outside buffer: ") + std::to_string(bufferStartIndex) +
std::string("..") + std::to_string(bufferStartIndex + _tokens.size()));
}
return _tokens[i - bufferStartIndex].get();
}
Token* UnbufferedTokenStream::LT(ssize_t i) {
if (i == -1) {
return _lastToken;
}
sync(i);
ssize_t index = static_cast<ssize_t>(_p) + i - 1;
if (index < 0) {
throw IndexOutOfBoundsException(std::string("LT(") + std::to_string(i) +
std::string(") gives negative index"));
}
if (index >= static_cast<ssize_t>(_tokens.size())) {
assert(_tokens.size() > 0 && _tokens.back()->getType() == EOF);
return _tokens.back().get();
}
return _tokens[static_cast<size_t>(index)].get();
}
size_t UnbufferedTokenStream::LA(ssize_t i) { return LT(i)->getType(); }
TokenSource* UnbufferedTokenStream::getTokenSource() const {
return _tokenSource;
}
std::string UnbufferedTokenStream::getText() { return ""; }
std::string UnbufferedTokenStream::getText(RuleContext* ctx) {
return getText(ctx->getSourceInterval());
}
std::string UnbufferedTokenStream::getText(Token* start, Token* stop) {
return getText(misc::Interval(start->getTokenIndex(), stop->getTokenIndex()));
}
void UnbufferedTokenStream::consume() {
if (LA(1) == EOF) {
throw IllegalStateException("cannot consume EOF");
}
// buf always has at least tokens[p==0] in this method due to ctor
_lastToken = _tokens[_p].get(); // track last token for LT(-1)
// if we're at last token and no markers, opportunity to flush buffer
if (_p == _tokens.size() - 1 && _numMarkers == 0) {
_tokens.clear();
_p = 0;
_lastTokenBufferStart = _lastToken;
} else {
++_p;
}
++_currentTokenIndex;
sync(1);
}
/// <summary>
/// Make sure we have 'need' elements from current position <seealso cref="#p
/// p"/>. Last valid
/// {@code p} index is {@code tokens.length-1}. {@code p+need-1} is the tokens
/// index 'need' elements ahead. If we need 1 element, {@code (p+1-1)==p} must
/// be less than {@code tokens.length}.
/// </summary>
void UnbufferedTokenStream::sync(ssize_t want) {
ssize_t need = (static_cast<ssize_t>(_p) + want - 1) -
static_cast<ssize_t>(_tokens.size()) +
1; // how many more elements we need?
if (need > 0) {
fill(static_cast<size_t>(need));
}
}
/// <summary>
/// Add {@code n} elements to the buffer. Returns the number of tokens
/// actually added to the buffer. If the return value is less than {@code n},
/// then EOF was reached before {@code n} tokens could be added.
/// </summary>
size_t UnbufferedTokenStream::fill(size_t n) {
for (size_t i = 0; i < n; i++) {
if (_tokens.size() > 0 && _tokens.back()->getType() == EOF) {
return i;
}
add(_tokenSource->nextToken());
}
return n;
}
void UnbufferedTokenStream::add(std::unique_ptr<Token> t) {
WritableToken* writable = dynamic_cast<WritableToken*>(t.get());
if (writable != nullptr) {
writable->setTokenIndex(int(getBufferStartIndex() + _tokens.size()));
}
_tokens.push_back(std::move(t));
}
/// <summary>
/// Return a marker that we can release later.
/// <p/>
/// 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.
/// </summary>
ssize_t UnbufferedTokenStream::mark() {
if (_numMarkers == 0) {
_lastTokenBufferStart = _lastToken;
}
int mark = -_numMarkers - 1;
_numMarkers++;
return mark;
}
void UnbufferedTokenStream::release(ssize_t marker) {
ssize_t expectedMark = -_numMarkers;
if (marker != expectedMark) {
throw IllegalStateException("release() called with an invalid marker.");
}
_numMarkers--;
if (_numMarkers == 0) { // can we release buffer?
if (_p > 0) {
// Copy tokens[p]..tokens[n-1] to tokens[0]..tokens[(n-1)-p], reset ptrs
// p is last valid token; move nothing if p==n as we have no valid char
_tokens.erase(_tokens.begin(),
_tokens.begin() + static_cast<ssize_t>(_p));
_p = 0;
}
_lastTokenBufferStart = _lastToken;
}
}
size_t UnbufferedTokenStream::index() { return _currentTokenIndex; }
void UnbufferedTokenStream::seek(size_t index) { // seek to absolute index
if (index == _currentTokenIndex) {
return;
}
if (index > _currentTokenIndex) {
sync(ssize_t(index - _currentTokenIndex));
index = std::min(index, getBufferStartIndex() + _tokens.size() - 1);
}
size_t bufferStartIndex = getBufferStartIndex();
if (bufferStartIndex > index) {
throw IllegalArgumentException(
std::string("cannot seek to negative index ") + std::to_string(index));
}
size_t i = index - bufferStartIndex;
if (i >= _tokens.size()) {
throw UnsupportedOperationException(
std::string("seek to index outside buffer: ") + std::to_string(index) +
" not in " + std::to_string(bufferStartIndex) + ".." +
std::to_string(bufferStartIndex + _tokens.size()));
}
_p = i;
_currentTokenIndex = index;
if (_p == 0) {
_lastToken = _lastTokenBufferStart;
} else {
_lastToken = _tokens[_p - 1].get();
}
}
size_t UnbufferedTokenStream::size() {
throw UnsupportedOperationException("Unbuffered stream cannot know its size");
}
std::string UnbufferedTokenStream::getSourceName() const {
return _tokenSource->getSourceName();
}
std::string UnbufferedTokenStream::getText(const misc::Interval& interval) {
size_t bufferStartIndex = getBufferStartIndex();
size_t bufferStopIndex = bufferStartIndex + _tokens.size() - 1;
size_t start = interval.a;
size_t stop = interval.b;
if (start < bufferStartIndex || stop > bufferStopIndex) {
throw UnsupportedOperationException(
std::string("interval ") + interval.toString() +
" not in token buffer window: " + std::to_string(bufferStartIndex) +
".." + std::to_string(bufferStopIndex));
}
size_t a = start - bufferStartIndex;
size_t b = stop - bufferStartIndex;
std::stringstream ss;
for (size_t i = a; i <= b; i++) {
Token* t = _tokens[i].get();
if (i > 0) ss << ", ";
ss << t->getText();
}
return ss.str();
}
size_t UnbufferedTokenStream::getBufferStartIndex() const {
return _currentTokenIndex - _p;
}
void UnbufferedTokenStream::InitializeInstanceFields() {
_p = 0;
_numMarkers = 0;
_currentTokenIndex = 0;
}

View File

@ -1,117 +0,0 @@
/* 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.
*/
#pragma once
#include "TokenStream.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC UnbufferedTokenStream : public TokenStream {
public:
UnbufferedTokenStream(TokenSource* tokenSource);
UnbufferedTokenStream(TokenSource* tokenSource, int bufferSize);
UnbufferedTokenStream(const UnbufferedTokenStream& other) = delete;
virtual ~UnbufferedTokenStream();
UnbufferedTokenStream& operator=(const UnbufferedTokenStream& other) = delete;
virtual Token* get(size_t i) const override;
virtual Token* LT(ssize_t i) override;
virtual size_t LA(ssize_t i) override;
virtual TokenSource* getTokenSource() const override;
virtual std::string getText(const misc::Interval& interval) override;
virtual std::string getText() override;
virtual std::string getText(RuleContext* ctx) override;
virtual std::string getText(Token* start, Token* stop) override;
virtual void consume() override;
/// <summary>
/// Return a marker that we can release later.
/// <p/>
/// 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.
/// </summary>
virtual ssize_t mark() override;
virtual void release(ssize_t marker) override;
virtual size_t index() override;
virtual void seek(size_t index) override;
virtual size_t size() override;
virtual std::string getSourceName() const override;
protected:
/// Make sure we have 'need' elements from current position p. Last valid
/// p index is tokens.length - 1. p + need - 1 is the tokens index 'need'
/// elements ahead. If we need 1 element, (p+1-1)==p must be less than
/// tokens.length.
TokenSource* _tokenSource;
/// <summary>
/// A moving window buffer of the data being scanned. While there's a marker,
/// we keep adding to buffer. Otherwise, <seealso cref="#consume consume()"/>
/// resets so we start filling at index 0 again.
/// </summary>
std::vector<std::unique_ptr<Token>> _tokens;
/// <summary>
/// 0..n-1 index into <seealso cref="#tokens tokens"/> of next token.
/// <p/>
/// The {@code LT(1)} token is {@code tokens[p]}. If {@code p == n}, we are
/// out of buffered tokens.
/// </summary>
size_t _p;
/// <summary>
/// Count up with <seealso cref="#mark mark()"/> and down with
/// <seealso cref="#release release()"/>. When we {@code release()} the last
/// mark,
/// {@code numMarkers} reaches 0 and we reset the buffer. Copy
/// {@code tokens[p]..tokens[n-1]} to {@code tokens[0]..tokens[(n-1)-p]}.
/// </summary>
int _numMarkers;
/// <summary>
/// This is the {@code LT(-1)} token for the current position.
/// </summary>
Token* _lastToken;
/// <summary>
/// When {@code numMarkers > 0}, this is the {@code LT(-1)} token for the
/// first token in <seealso cref="#tokens"/>. Otherwise, this is {@code null}.
/// </summary>
Token* _lastTokenBufferStart;
/// <summary>
/// Absolute token index. It's the index of the token about to be read via
/// {@code LT(1)}. Goes from 0 to the number of tokens in the entire stream,
/// although the stream size is unknown before the end is reached.
/// <p/>
/// This value is used to set the token indexes if the stream provides tokens
/// that implement <seealso cref="WritableToken"/>.
/// </summary>
size_t _currentTokenIndex;
virtual void sync(ssize_t want);
/// <summary>
/// Add {@code n} elements to the buffer. Returns the number of tokens
/// actually added to the buffer. If the return value is less than {@code n},
/// then EOF was reached before {@code n} tokens could be added.
/// </summary>
virtual size_t fill(size_t n);
virtual void add(std::unique_ptr<Token> t);
size_t getBufferStartIndex() const;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

View File

@ -1,108 +0,0 @@
/* 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.
*/
#include "Token.h"
#include "Vocabulary.h"
using namespace antlr4::dfa;
const Vocabulary Vocabulary::EMPTY_VOCABULARY;
Vocabulary::Vocabulary(const std::vector<std::string>& literalNames,
const std::vector<std::string>& symbolicNames)
: Vocabulary(literalNames, symbolicNames, {}) {}
Vocabulary::Vocabulary(const std::vector<std::string>& literalNames,
const std::vector<std::string>& symbolicNames,
const std::vector<std::string>& displayNames)
: _literalNames(literalNames),
_symbolicNames(symbolicNames),
_displayNames(displayNames),
_maxTokenType(
std::max(_displayNames.size(),
std::max(_literalNames.size(), _symbolicNames.size())) -
1) {
// See note here on -1 part: https://github.com/antlr/antlr4/pull/1146
}
Vocabulary::~Vocabulary() {}
Vocabulary Vocabulary::fromTokenNames(
const std::vector<std::string>& tokenNames) {
if (tokenNames.empty()) {
return EMPTY_VOCABULARY;
}
std::vector<std::string> literalNames = tokenNames;
std::vector<std::string> symbolicNames = tokenNames;
std::locale locale;
for (size_t i = 0; i < tokenNames.size(); i++) {
std::string tokenName = tokenNames[i];
if (tokenName == "") {
continue;
}
if (!tokenName.empty()) {
char firstChar = tokenName[0];
if (firstChar == '\'') {
symbolicNames[i] = "";
continue;
} else if (std::isupper(firstChar, locale)) {
literalNames[i] = "";
continue;
}
}
// wasn't a literal or symbolic name
literalNames[i] = "";
symbolicNames[i] = "";
}
return Vocabulary(literalNames, symbolicNames, tokenNames);
}
size_t Vocabulary::getMaxTokenType() const { return _maxTokenType; }
std::string Vocabulary::getLiteralName(size_t tokenType) const {
if (tokenType < _literalNames.size()) {
return _literalNames[tokenType];
}
return "";
}
std::string Vocabulary::getSymbolicName(size_t tokenType) const {
if (tokenType == Token::EOF) {
return "EOF";
}
if (tokenType < _symbolicNames.size()) {
return _symbolicNames[tokenType];
}
return "";
}
std::string Vocabulary::getDisplayName(size_t tokenType) const {
if (tokenType < _displayNames.size()) {
std::string displayName = _displayNames[tokenType];
if (!displayName.empty()) {
return displayName;
}
}
std::string literalName = getLiteralName(tokenType);
if (!literalName.empty()) {
return literalName;
}
std::string symbolicName = getSymbolicName(tokenType);
if (!symbolicName.empty()) {
return symbolicName;
}
return std::to_string(tokenType);
}

View File

@ -1,198 +0,0 @@
/* 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.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
namespace dfa {
/// This class provides a default implementation of the <seealso
/// cref="Vocabulary"/> interface.
class ANTLR4CPP_PUBLIC Vocabulary {
public:
Vocabulary(Vocabulary const&) = default;
virtual ~Vocabulary();
Vocabulary& operator=(Vocabulary const&) = default;
/// Gets an empty <seealso cref="Vocabulary"/> instance.
///
/// <para>
/// No literal or symbol names are assigned to token types, so
/// <seealso cref="#getDisplayName(int)"/> returns the numeric value for all
/// tokens except <seealso cref="Token#EOF"/>.</para>
static const Vocabulary EMPTY_VOCABULARY;
Vocabulary() {}
/// <summary>
/// Constructs a new instance of <seealso cref="Vocabulary"/> from the
/// specified literal and symbolic token names.
/// </summary>
/// <param name="literalNames"> The literal names assigned to tokens, or
/// {@code null} if no literal names are assigned. </param> <param
/// name="symbolicNames"> The symbolic names assigned to tokens, or
/// {@code null} if no symbolic names are assigned.
/// </param>
/// <seealso cref= #getLiteralName(int) </seealso>
/// <seealso cref= #getSymbolicName(int) </seealso>
Vocabulary(const std::vector<std::string>& literalNames,
const std::vector<std::string>& symbolicNames);
/// <summary>
/// Constructs a new instance of <seealso cref="Vocabulary"/> from the
/// specified literal, symbolic, and display token names.
/// </summary>
/// <param name="literalNames"> The literal names assigned to tokens, or
/// {@code null} if no literal names are assigned. </param> <param
/// name="symbolicNames"> The symbolic names assigned to tokens, or
/// {@code null} if no symbolic names are assigned. </param>
/// <param name="displayNames"> The display names assigned to tokens, or
/// {@code null} to use the values in {@code literalNames} and {@code
/// symbolicNames} as the source of display names, as described in <seealso
/// cref="#getDisplayName(int)"/>.
/// </param>
/// <seealso cref= #getLiteralName(int) </seealso>
/// <seealso cref= #getSymbolicName(int) </seealso>
/// <seealso cref= #getDisplayName(int) </seealso>
Vocabulary(const std::vector<std::string>& literalNames,
const std::vector<std::string>& symbolicNames,
const std::vector<std::string>& displayNames);
/// <summary>
/// Returns a <seealso cref="Vocabulary"/> instance from the specified set of
/// token names. This method acts as a compatibility layer for the single
/// {@code tokenNames} array generated by previous releases of ANTLR.
///
/// <para>The resulting vocabulary instance returns {@code null} for
/// <seealso cref="#getLiteralName(int)"/> and <seealso
/// cref="#getSymbolicName(int)"/>, and the value from {@code tokenNames} for
/// the display names.</para>
/// </summary>
/// <param name="tokenNames"> The token names, or {@code null} if no token
/// names are available. </param> <returns> A <seealso cref="Vocabulary"/>
/// instance which uses {@code tokenNames} for the display names of tokens.
/// </returns>
static Vocabulary fromTokenNames(const std::vector<std::string>& tokenNames);
/// <summary>
/// Returns the highest token type value. It can be used to iterate from
/// zero to that number, inclusively, thus querying all stored entries.
/// </summary> <returns> the highest token type value </returns>
virtual size_t getMaxTokenType() const;
/// <summary>
/// Gets the string literal associated with a token type. The string returned
/// by this method, when not {@code null}, can be used unaltered in a parser
/// grammar to represent this token type.
///
/// <para>The following table shows examples of lexer rules and the literal
/// names assigned to the corresponding token types.</para>
///
/// <table>
/// <tr>
/// <th>Rule</th>
/// <th>Literal Name</th>
/// <th>Java String Literal</th>
/// </tr>
/// <tr>
/// <td>{@code THIS : 'this';}</td>
/// <td>{@code 'this'}</td>
/// <td>{@code "'this'"}</td>
/// </tr>
/// <tr>
/// <td>{@code SQUOTE : '\'';}</td>
/// <td>{@code '\''}</td>
/// <td>{@code "'\\''"}</td>
/// </tr>
/// <tr>
/// <td>{@code ID : [A-Z]+;}</td>
/// <td>n/a</td>
/// <td>{@code null}</td>
/// </tr>
/// </table>
/// </summary>
/// <param name="tokenType"> The token type.
/// </param>
/// <returns> The string literal associated with the specified token type, or
/// {@code null} if no string literal is associated with the type. </returns>
virtual std::string getLiteralName(size_t tokenType) const;
/// <summary>
/// Gets the symbolic name associated with a token type. The string returned
/// by this method, when not {@code null}, can be used unaltered in a parser
/// grammar to represent this token type.
///
/// <para>This method supports token types defined by any of the following
/// methods:</para>
///
/// <ul>
/// <li>Tokens created by lexer rules.</li>
/// <li>Tokens defined in a <code>tokens{}</code> block in a lexer or parser
/// grammar.</li>
/// <li>The implicitly defined {@code EOF} token, which has the token type
/// <seealso cref="Token#EOF"/>.</li>
/// </ul>
///
/// <para>The following table shows examples of lexer rules and the literal
/// names assigned to the corresponding token types.</para>
///
/// <table>
/// <tr>
/// <th>Rule</th>
/// <th>Symbolic Name</th>
/// </tr>
/// <tr>
/// <td>{@code THIS : 'this';}</td>
/// <td>{@code THIS}</td>
/// </tr>
/// <tr>
/// <td>{@code SQUOTE : '\'';}</td>
/// <td>{@code SQUOTE}</td>
/// </tr>
/// <tr>
/// <td>{@code ID : [A-Z]+;}</td>
/// <td>{@code ID}</td>
/// </tr>
/// </table>
/// </summary>
/// <param name="tokenType"> The token type.
/// </param>
/// <returns> The symbolic name associated with the specified token type, or
/// {@code null} if no symbolic name is associated with the type. </returns>
virtual std::string getSymbolicName(size_t tokenType) const;
/// <summary>
/// Gets the display name of a token type.
///
/// <para>ANTLR provides a default implementation of this method, but
/// applications are free to override the behavior in any manner which makes
/// sense for the application. The default implementation returns the first
/// result from the following list which produces a non-{@code null}
/// result.</para>
///
/// <ol>
/// <li>The result of <seealso cref="#getLiteralName"/></li>
/// <li>The result of <seealso cref="#getSymbolicName"/></li>
/// <li>The result of <seealso cref="Integer#toString"/></li>
/// </ol>
/// </summary>
/// <param name="tokenType"> The token type.
/// </param>
/// <returns> The display name of the token type, for use in error reporting
/// or other user-visible messages which reference specific token types.
/// </returns>
virtual std::string getDisplayName(size_t tokenType) const;
private:
std::vector<std::string> const _literalNames;
std::vector<std::string> const _symbolicNames;
std::vector<std::string> const _displayNames;
const size_t _maxTokenType = 0;
};
} // namespace dfa
} // namespace antlr4

View File

@ -1,8 +0,0 @@
/* 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.
*/
#include "WritableToken.h"
antlr4::WritableToken::~WritableToken() {}

View File

@ -1,23 +0,0 @@
/* 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.
*/
#pragma once
#include "Token.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC WritableToken : public Token {
public:
virtual ~WritableToken();
virtual void setText(const std::string& text) = 0;
virtual void setType(size_t ttype) = 0;
virtual void setLine(size_t line) = 0;
virtual void setCharPositionInLine(size_t pos) = 0;
virtual void setChannel(size_t channel) = 0;
virtual void setTokenIndex(size_t index) = 0;
};
} // namespace antlr4

View File

@ -1,134 +0,0 @@
/* 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.
*/
#pragma once
#include <assert.h>
#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <algorithm>
#include <atomic>
#include <bitset>
#include <chrono>
#include <condition_variable>
#include <exception>
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
// Defines for the Guid class and other platform dependent stuff.
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable : 4250) // Class inherits by dominance.
#pragma warning(disable : 4512) // assignment operator could not be generated
#if _MSC_VER < 1900
// Before VS 2015 code like "while (true)" will create a (useless) warning in
// level 4.
#pragma warning(disable : 4127) // conditional expression is constant
#endif
#endif
#define GUID_WINDOWS
#ifdef _WIN64
typedef __int64 ssize_t;
#else
typedef __int32 ssize_t;
#endif
#if _MSC_VER >= 1900 && _MSC_VER < 2000
// VS 2015 has a known bug when using std::codecvt_utf8<char32_t>
// so we have to temporarily use __int32 instead.
// https://connect.microsoft.com/VisualStudio/feedback/details/1403302/unresolved-external-when-using-codecvt-utf8
typedef std::basic_string<__int32> i32string;
typedef i32string UTF32String;
#else
typedef std::u32string UTF32String;
#endif
#ifdef ANTLR4CPP_EXPORTS
#define ANTLR4CPP_PUBLIC __declspec(dllexport)
#else
#ifdef ANTLR4CPP_STATIC
#define ANTLR4CPP_PUBLIC
#else
#define ANTLR4CPP_PUBLIC __declspec(dllimport)
#endif
#endif
#elif defined(__APPLE__)
typedef std::u32string UTF32String;
#define GUID_CFUUID
#if __GNUC__ >= 4
#define ANTLR4CPP_PUBLIC __attribute__((visibility("default")))
#else
#define ANTLR4CPP_PUBLIC
#endif
#else
typedef std::u32string UTF32String;
#define GUID_LIBUUID
#if __GNUC__ >= 6
#define ANTLR4CPP_PUBLIC __attribute__((visibility("default")))
#else
#define ANTLR4CPP_PUBLIC
#endif
#endif
#include "support/Declarations.h"
#include "support/guid.h"
#if !defined(HAS_NOEXCEPT)
#if defined(__clang__)
#if __has_feature(cxx_noexcept)
#define HAS_NOEXCEPT
#endif
#else
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
__GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
#define HAS_NOEXCEPT
#endif
#endif
#ifdef HAS_NOEXCEPT
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
#endif
// We have to undefine this symbol as ANTLR will use this name for own members
// and even generated functions. Because EOF is a global macro we cannot use
// e.g. a namespace scope to disambiguate.
#ifdef EOF
#undef EOF
#endif
#define INVALID_INDEX std::numeric_limits<size_t>::max()
template <class T>
using Ref = std::shared_ptr<T>;

View File

@ -1,164 +0,0 @@
/* 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.
*/
#pragma once
// This is the umbrella header for all ANTLR4 C++ runtime headers.
#include "antlr4-common.h"
#include "ANTLRErrorListener.h"
#include "ANTLRErrorStrategy.h"
#include "ANTLRFileStream.h"
#include "ANTLRInputStream.h"
#include "BailErrorStrategy.h"
#include "BaseErrorListener.h"
#include "BufferedTokenStream.h"
#include "CharStream.h"
#include "CommonToken.h"
#include "CommonTokenFactory.h"
#include "CommonTokenStream.h"
#include "ConsoleErrorListener.h"
#include "DefaultErrorStrategy.h"
#include "DiagnosticErrorListener.h"
#include "Exceptions.h"
#include "FailedPredicateException.h"
#include "InputMismatchException.h"
#include "IntStream.h"
#include "InterpreterRuleContext.h"
#include "Lexer.h"
#include "LexerInterpreter.h"
#include "LexerNoViableAltException.h"
#include "ListTokenSource.h"
#include "NoViableAltException.h"
#include "Parser.h"
#include "ParserInterpreter.h"
#include "ParserRuleContext.h"
#include "ProxyErrorListener.h"
#include "RecognitionException.h"
#include "Recognizer.h"
#include "RuleContext.h"
#include "RuleContextWithAltNum.h"
#include "RuntimeMetaData.h"
#include "Token.h"
#include "TokenFactory.h"
#include "TokenSource.h"
#include "TokenStream.h"
#include "TokenStreamRewriter.h"
#include "UnbufferedCharStream.h"
#include "UnbufferedTokenStream.h"
#include "Vocabulary.h"
#include "WritableToken.h"
#include "atn/ATN.h"
#include "atn/ATNConfig.h"
#include "atn/ATNConfigSet.h"
#include "atn/ATNDeserializationOptions.h"
#include "atn/ATNDeserializer.h"
#include "atn/ATNSerializer.h"
#include "atn/ATNSimulator.h"
#include "atn/ATNState.h"
#include "atn/ATNType.h"
#include "atn/AbstractPredicateTransition.h"
#include "atn/ActionTransition.h"
#include "atn/AmbiguityInfo.h"
#include "atn/ArrayPredictionContext.h"
#include "atn/AtomTransition.h"
#include "atn/BasicBlockStartState.h"
#include "atn/BasicState.h"
#include "atn/BlockEndState.h"
#include "atn/BlockStartState.h"
#include "atn/ContextSensitivityInfo.h"
#include "atn/DecisionEventInfo.h"
#include "atn/DecisionInfo.h"
#include "atn/DecisionState.h"
#include "atn/EmptyPredictionContext.h"
#include "atn/EpsilonTransition.h"
#include "atn/ErrorInfo.h"
#include "atn/LL1Analyzer.h"
#include "atn/LexerATNConfig.h"
#include "atn/LexerATNSimulator.h"
#include "atn/LexerAction.h"
#include "atn/LexerActionExecutor.h"
#include "atn/LexerActionType.h"
#include "atn/LexerChannelAction.h"
#include "atn/LexerCustomAction.h"
#include "atn/LexerIndexedCustomAction.h"
#include "atn/LexerModeAction.h"
#include "atn/LexerMoreAction.h"
#include "atn/LexerPopModeAction.h"
#include "atn/LexerPushModeAction.h"
#include "atn/LexerSkipAction.h"
#include "atn/LexerTypeAction.h"
#include "atn/LookaheadEventInfo.h"
#include "atn/LoopEndState.h"
#include "atn/NotSetTransition.h"
#include "atn/OrderedATNConfigSet.h"
#include "atn/ParseInfo.h"
#include "atn/ParserATNSimulator.h"
#include "atn/PlusBlockStartState.h"
#include "atn/PlusLoopbackState.h"
#include "atn/PrecedencePredicateTransition.h"
#include "atn/PredicateEvalInfo.h"
#include "atn/PredicateTransition.h"
#include "atn/PredictionContext.h"
#include "atn/PredictionMode.h"
#include "atn/ProfilingATNSimulator.h"
#include "atn/RangeTransition.h"
#include "atn/RuleStartState.h"
#include "atn/RuleStopState.h"
#include "atn/RuleTransition.h"
#include "atn/SemanticContext.h"
#include "atn/SetTransition.h"
#include "atn/SingletonPredictionContext.h"
#include "atn/StarBlockStartState.h"
#include "atn/StarLoopEntryState.h"
#include "atn/StarLoopbackState.h"
#include "atn/TokensStartState.h"
#include "atn/Transition.h"
#include "atn/WildcardTransition.h"
#include "dfa/DFA.h"
#include "dfa/DFASerializer.h"
#include "dfa/DFAState.h"
#include "dfa/LexerDFASerializer.h"
#include "misc/InterpreterDataReader.h"
#include "misc/Interval.h"
#include "misc/IntervalSet.h"
#include "misc/MurmurHash.h"
#include "misc/Predicate.h"
#include "support/Any.h"
#include "support/Arrays.h"
#include "support/BitSet.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "support/guid.h"
#include "tree/AbstractParseTreeVisitor.h"
#include "tree/ErrorNode.h"
#include "tree/ErrorNodeImpl.h"
#include "tree/ParseTree.h"
#include "tree/ParseTreeListener.h"
#include "tree/ParseTreeProperty.h"
#include "tree/ParseTreeVisitor.h"
#include "tree/ParseTreeWalker.h"
#include "tree/TerminalNode.h"
#include "tree/TerminalNodeImpl.h"
#include "tree/Trees.h"
#include "tree/pattern/Chunk.h"
#include "tree/pattern/ParseTreeMatch.h"
#include "tree/pattern/ParseTreePattern.h"
#include "tree/pattern/ParseTreePatternMatcher.h"
#include "tree/pattern/RuleTagToken.h"
#include "tree/pattern/TagChunk.h"
#include "tree/pattern/TextChunk.h"
#include "tree/pattern/TokenTagToken.h"
#include "tree/xpath/XPath.h"
#include "tree/xpath/XPathElement.h"
#include "tree/xpath/XPathLexer.h"
#include "tree/xpath/XPathLexerErrorListener.h"
#include "tree/xpath/XPathRuleAnywhereElement.h"
#include "tree/xpath/XPathRuleElement.h"
#include "tree/xpath/XPathTokenAnywhereElement.h"
#include "tree/xpath/XPathTokenElement.h"
#include "tree/xpath/XPathWildcardAnywhereElement.h"
#include "tree/xpath/XPathWildcardElement.h"

View File

@ -1,212 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "Recognizer.h"
#include "RuleContext.h"
#include "Token.h"
#include "atn/ATNType.h"
#include "atn/DecisionState.h"
#include "atn/LL1Analyzer.h"
#include "atn/RuleTransition.h"
#include "misc/IntervalSet.h"
#include "support/CPPUtils.h"
#include "atn/ATN.h"
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;
ATN::ATN() : ATN(ATNType::LEXER, 0) {}
ATN::ATN(ATN&& other) {
// All source vectors are implicitly cleared by the moves.
states = std::move(other.states);
decisionToState = std::move(other.decisionToState);
ruleToStartState = std::move(other.ruleToStartState);
ruleToStopState = std::move(other.ruleToStopState);
grammarType = std::move(other.grammarType);
maxTokenType = std::move(other.maxTokenType);
ruleToTokenType = std::move(other.ruleToTokenType);
lexerActions = std::move(other.lexerActions);
modeToStartState = std::move(other.modeToStartState);
}
ATN::ATN(ATNType grammarType_, size_t maxTokenType_)
: grammarType(grammarType_), maxTokenType(maxTokenType_) {}
ATN::~ATN() {
for (ATNState* state : states) {
delete state;
}
}
/**
* Required to be defined (even though not used) as we have an explicit move
* assignment operator.
*/
ATN& ATN::operator=(ATN& other) NOEXCEPT {
states = other.states;
decisionToState = other.decisionToState;
ruleToStartState = other.ruleToStartState;
ruleToStopState = other.ruleToStopState;
grammarType = other.grammarType;
maxTokenType = other.maxTokenType;
ruleToTokenType = other.ruleToTokenType;
lexerActions = other.lexerActions;
modeToStartState = other.modeToStartState;
return *this;
}
/**
* Explicit move assignment operator to make this the preferred assignment. With
* implicit copy/move assignment operators it seems the copy operator is
* preferred causing trouble when releasing the allocated ATNState instances.
*/
ATN& ATN::operator=(ATN&& other) NOEXCEPT {
// All source vectors are implicitly cleared by the moves.
states = std::move(other.states);
decisionToState = std::move(other.decisionToState);
ruleToStartState = std::move(other.ruleToStartState);
ruleToStopState = std::move(other.ruleToStopState);
grammarType = std::move(other.grammarType);
maxTokenType = std::move(other.maxTokenType);
ruleToTokenType = std::move(other.ruleToTokenType);
lexerActions = std::move(other.lexerActions);
modeToStartState = std::move(other.modeToStartState);
return *this;
}
misc::IntervalSet ATN::nextTokens(ATNState* s, RuleContext* ctx) const {
LL1Analyzer analyzer(*this);
return analyzer.LOOK(s, ctx);
}
misc::IntervalSet const& ATN::nextTokens(ATNState* s) const {
if (!s->_nextTokenUpdated) {
std::unique_lock<std::mutex> lock{_mutex};
if (!s->_nextTokenUpdated) {
s->_nextTokenWithinRule = nextTokens(s, nullptr);
s->_nextTokenUpdated = true;
}
}
return s->_nextTokenWithinRule;
}
void ATN::addState(ATNState* state) {
if (state != nullptr) {
// state->atn = this;
state->stateNumber = static_cast<int>(states.size());
}
states.push_back(state);
}
void ATN::removeState(ATNState* state) {
delete states.at(
state->stateNumber); // just free mem, don't shift states in list
states.at(state->stateNumber) = nullptr;
}
int ATN::defineDecisionState(DecisionState* s) {
decisionToState.push_back(s);
s->decision = static_cast<int>(decisionToState.size() - 1);
return s->decision;
}
DecisionState* ATN::getDecisionState(size_t decision) const {
if (!decisionToState.empty()) {
return decisionToState[decision];
}
return nullptr;
}
size_t ATN::getNumberOfDecisions() const { return decisionToState.size(); }
misc::IntervalSet ATN::getExpectedTokens(size_t stateNumber,
RuleContext* context) const {
if (stateNumber == ATNState::INVALID_STATE_NUMBER ||
stateNumber >= states.size()) {
throw IllegalArgumentException("Invalid state number.");
}
RuleContext* ctx = context;
ATNState* s = states.at(stateNumber);
misc::IntervalSet following = nextTokens(s);
if (!following.contains(Token::EPSILON)) {
return following;
}
misc::IntervalSet expected;
expected.addAll(following);
expected.remove(Token::EPSILON);
while (ctx && ctx->invokingState != ATNState::INVALID_STATE_NUMBER &&
following.contains(Token::EPSILON)) {
ATNState* invokingState = states.at(ctx->invokingState);
RuleTransition* rt =
static_cast<RuleTransition*>(invokingState->transitions[0]);
following = nextTokens(rt->followState);
expected.addAll(following);
expected.remove(Token::EPSILON);
if (ctx->parent == nullptr) {
break;
}
ctx = static_cast<RuleContext*>(ctx->parent);
}
if (following.contains(Token::EPSILON)) {
expected.add(Token::EOF);
}
return expected;
}
std::string ATN::toString() const {
std::stringstream ss;
std::string type;
switch (grammarType) {
case ATNType::LEXER:
type = "LEXER ";
break;
case ATNType::PARSER:
type = "PARSER ";
break;
default:
break;
}
ss << "(" << type << "ATN " << std::hex << this << std::dec
<< ") maxTokenType: " << maxTokenType << std::endl;
ss << "states (" << states.size() << ") {" << std::endl;
size_t index = 0;
for (auto state : states) {
if (state == nullptr) {
ss << " " << index++ << ": nul" << std::endl;
} else {
std::string text = state->toString();
ss << " " << index++ << ": " << indent(text, " ", false) << std::endl;
}
}
index = 0;
for (auto state : decisionToState) {
if (state == nullptr) {
ss << " " << index++ << ": nul" << std::endl;
} else {
std::string text = state->toString();
ss << " " << index++ << ": " << indent(text, " ", false) << std::endl;
}
}
ss << "}";
return ss.str();
}

View File

@ -1,115 +0,0 @@
/* 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.
*/
#pragma once
#include "RuleContext.h"
namespace antlr4 {
namespace atn {
class ANTLR4CPP_PUBLIC ATN {
public:
static const size_t INVALID_ALT_NUMBER = 0;
/// Used for runtime deserialization of ATNs from strings.
ATN();
ATN(ATN&& other);
ATN(ATNType grammarType, size_t maxTokenType);
virtual ~ATN();
std::vector<ATNState*> states;
/// Each subrule/rule is a decision point and we must track them so we
/// can go back later and build DFA predictors for them. This includes
/// all the rules, subrules, optional blocks, ()+, ()* etc...
std::vector<DecisionState*> decisionToState;
/// Maps from rule index to starting state number.
std::vector<RuleStartState*> ruleToStartState;
/// Maps from rule index to stop state number.
std::vector<RuleStopState*> ruleToStopState;
/// The type of the ATN.
ATNType grammarType;
/// The maximum value for any symbol recognized by a transition in the ATN.
size_t maxTokenType;
/// <summary>
/// For lexer ATNs, this maps the rule index to the resulting token type.
/// For parser ATNs, this maps the rule index to the generated bypass token
/// type if the
/// <seealso
/// cref="ATNDeserializationOptions#isGenerateRuleBypassTransitions"/>
/// deserialization option was specified; otherwise, this is {@code null}.
/// </summary>
std::vector<size_t> ruleToTokenType;
/// For lexer ATNs, this is an array of {@link LexerAction} objects which may
/// be referenced by action transitions in the ATN.
std::vector<Ref<LexerAction>> lexerActions;
std::vector<TokensStartState*> modeToStartState;
ATN& operator=(ATN& other) NOEXCEPT;
ATN& operator=(ATN&& other) NOEXCEPT;
/// <summary>
/// Compute the set of valid tokens that can occur starting in state {@code
/// s}.
/// If {@code ctx} is null, the set of tokens will not include what can
/// follow the rule surrounding {@code s}. In other words, the set will be
/// restricted to tokens reachable staying within {@code s}'s rule.
/// </summary>
virtual misc::IntervalSet nextTokens(ATNState* s, RuleContext* ctx) const;
/// <summary>
/// Compute the set of valid tokens that can occur starting in {@code s} and
/// staying in same rule. <seealso cref="Token#EPSILON"/> is in set if we
/// reach end of rule.
/// </summary>
virtual misc::IntervalSet const& nextTokens(ATNState* s) const;
virtual void addState(ATNState* state);
virtual void removeState(ATNState* state);
virtual int defineDecisionState(DecisionState* s);
virtual DecisionState* getDecisionState(size_t decision) const;
virtual size_t getNumberOfDecisions() const;
/// <summary>
/// Computes the set of input symbols which could follow ATN state number
/// {@code stateNumber} in the specified full {@code context}. This method
/// considers the complete parser context, but does not evaluate semantic
/// predicates (i.e. all predicates encountered during the calculation are
/// assumed true). If a path in the ATN exists from the starting state to the
/// <seealso cref="RuleStopState"/> of the outermost context without matching
/// any symbols, <seealso cref="Token#EOF"/> is added to the returned set.
/// <p/>
/// If {@code context} is {@code null}, it is treated as
/// <seealso cref="ParserRuleContext#EMPTY"/>.
/// </summary>
/// <param name="stateNumber"> the ATN state number </param>
/// <param name="context"> the full parse context </param>
/// <returns> The set of potentially valid input symbols which could follow
/// the specified state in the specified context. </returns> <exception
/// cref="IllegalArgumentException"> if the ATN does not contain a state with
/// number {@code stateNumber} </exception>
virtual misc::IntervalSet getExpectedTokens(size_t stateNumber,
RuleContext* context) const;
std::string toString() const;
private:
mutable std::mutex _mutex;
};
} // namespace atn
} // namespace antlr4

View File

@ -1,118 +0,0 @@
/* 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.
*/
#include "SemanticContext.h"
#include "atn/PredictionContext.h"
#include "misc/MurmurHash.h"
#include "atn/ATNConfig.h"
using namespace antlr4::atn;
const size_t ATNConfig::SUPPRESS_PRECEDENCE_FILTER = 0x40000000;
ATNConfig::ATNConfig(ATNState* state_, size_t alt_,
Ref<PredictionContext> const& context_)
: ATNConfig(state_, alt_, context_, SemanticContext::NONE) {}
ATNConfig::ATNConfig(ATNState* state_, size_t alt_,
Ref<PredictionContext> const& context_,
Ref<SemanticContext> const& semanticContext_)
: state(state_),
alt(alt_),
context(context_),
semanticContext(semanticContext_) {
reachesIntoOuterContext = 0;
}
ATNConfig::ATNConfig(Ref<ATNConfig> const& c)
: ATNConfig(c, c->state, c->context, c->semanticContext) {}
ATNConfig::ATNConfig(Ref<ATNConfig> const& c, ATNState* state_)
: ATNConfig(c, state_, c->context, c->semanticContext) {}
ATNConfig::ATNConfig(Ref<ATNConfig> const& c, ATNState* state,
Ref<SemanticContext> const& semanticContext)
: ATNConfig(c, state, c->context, semanticContext) {}
ATNConfig::ATNConfig(Ref<ATNConfig> const& c,
Ref<SemanticContext> const& semanticContext)
: ATNConfig(c, c->state, c->context, semanticContext) {}
ATNConfig::ATNConfig(Ref<ATNConfig> const& c, ATNState* state,
Ref<PredictionContext> const& context)
: ATNConfig(c, state, context, c->semanticContext) {}
ATNConfig::ATNConfig(Ref<ATNConfig> const& c, ATNState* state,
Ref<PredictionContext> const& context,
Ref<SemanticContext> const& semanticContext)
: state(state),
alt(c->alt),
context(context),
reachesIntoOuterContext(c->reachesIntoOuterContext),
semanticContext(semanticContext) {}
ATNConfig::~ATNConfig() {}
size_t ATNConfig::hashCode() const {
size_t hashCode = misc::MurmurHash::initialize(7);
hashCode = misc::MurmurHash::update(hashCode, state->stateNumber);
hashCode = misc::MurmurHash::update(hashCode, alt);
hashCode = misc::MurmurHash::update(hashCode, context);
hashCode = misc::MurmurHash::update(hashCode, semanticContext);
hashCode = misc::MurmurHash::finish(hashCode, 4);
return hashCode;
}
size_t ATNConfig::getOuterContextDepth() const {
return reachesIntoOuterContext & ~SUPPRESS_PRECEDENCE_FILTER;
}
bool ATNConfig::isPrecedenceFilterSuppressed() const {
return (reachesIntoOuterContext & SUPPRESS_PRECEDENCE_FILTER) != 0;
}
void ATNConfig::setPrecedenceFilterSuppressed(bool value) {
if (value) {
reachesIntoOuterContext |= SUPPRESS_PRECEDENCE_FILTER;
} else {
reachesIntoOuterContext &= ~SUPPRESS_PRECEDENCE_FILTER;
}
}
bool ATNConfig::operator==(const ATNConfig& other) const {
return state->stateNumber == other.state->stateNumber && alt == other.alt &&
((context == other.context) || (*context == *other.context)) &&
*semanticContext == *other.semanticContext &&
isPrecedenceFilterSuppressed() == other.isPrecedenceFilterSuppressed();
}
bool ATNConfig::operator!=(const ATNConfig& other) const {
return !operator==(other);
}
std::string ATNConfig::toString() { return toString(true); }
std::string ATNConfig::toString(bool showAlt) {
std::stringstream ss;
ss << "(";
ss << state->toString();
if (showAlt) {
ss << "," << alt;
}
if (context) {
ss << ",[" << context->toString() << "]";
}
if (semanticContext != nullptr && semanticContext != SemanticContext::NONE) {
ss << "," << semanticContext.get();
}
if (getOuterContextDepth() > 0) {
ss << ",up=" << getOuterContextDepth();
}
ss << ')';
return ss.str();
}

View File

@ -1,148 +0,0 @@
/* 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.
*/
#pragma once
#include "./antlr4-common.h"
namespace antlr4 {
namespace atn {
/// <summary>
/// A tuple: (ATN state, predicted alt, syntactic, semantic context).
/// The syntactic context is a graph-structured stack node whose
/// path(s) to the root is the rule invocation(s)
/// chain used to arrive at the state. The semantic context is
/// the tree of semantic predicates encountered before reaching
/// an ATN state.
/// </summary>
class ANTLR4CPP_PUBLIC ATNConfig {
public:
struct Hasher {
size_t operator()(ATNConfig const& k) const { return k.hashCode(); }
};
struct Comparer {
bool operator()(ATNConfig const& lhs, ATNConfig const& rhs) const {
return (&lhs == &rhs) || (lhs == rhs);
}
};
using Set = std::unordered_set<Ref<ATNConfig>, Hasher, Comparer>;
/// The ATN state associated with this configuration.
ATNState* state;
/// What alt (or lexer rule) is predicted by this configuration.
const size_t alt;
/// The stack of invoking states leading to the rule/states associated
/// with this config. We track only those contexts pushed during
/// execution of the ATN simulator.
///
/// Can be shared between multiple ANTConfig instances.
Ref<PredictionContext> context;
/**
* We cannot execute predicates dependent upon local context unless
* we know for sure we are in the correct context. Because there is
* no way to do this efficiently, we simply cannot evaluate
* dependent predicates unless we are in the rule that initially
* invokes the ATN simulator.
*
* <p>
* closure() tracks the depth of how far we dip into the outer context:
* depth > 0. Note that it may not be totally accurate depth since I
* don't ever decrement. TO_DO: make it a boolean then</p>
*
* <p>
* For memory efficiency, the {@link #isPrecedenceFilterSuppressed} method
* is also backed by this field. Since the field is publicly accessible, the
* highest bit which would not cause the value to become negative is used to
* store this field. This choice minimizes the risk that code which only
* compares this value to 0 would be affected by the new purpose of the
* flag. It also ensures the performance of the existing {@link ATNConfig}
* constructors as well as certain operations like
* {@link ATNConfigSet#add(ATNConfig, DoubleKeyMap)} method are
* <em>completely</em> unaffected by the change.</p>
*/
size_t reachesIntoOuterContext;
/// Can be shared between multiple ATNConfig instances.
Ref<SemanticContext> semanticContext;
ATNConfig(ATNState* state, size_t alt, Ref<PredictionContext> const& context);
ATNConfig(ATNState* state, size_t alt, Ref<PredictionContext> const& context,
Ref<SemanticContext> const& semanticContext);
ATNConfig(Ref<ATNConfig> const& c); // dup
ATNConfig(Ref<ATNConfig> const& c, ATNState* state);
ATNConfig(Ref<ATNConfig> const& c, ATNState* state,
Ref<SemanticContext> const& semanticContext);
ATNConfig(Ref<ATNConfig> const& c,
Ref<SemanticContext> const& semanticContext);
ATNConfig(Ref<ATNConfig> const& c, ATNState* state,
Ref<PredictionContext> const& context);
ATNConfig(Ref<ATNConfig> const& c, ATNState* state,
Ref<PredictionContext> const& context,
Ref<SemanticContext> const& semanticContext);
ATNConfig(ATNConfig const&) = default;
virtual ~ATNConfig();
ATNConfig& operator=(ATNConfig const&) = default;
virtual size_t hashCode() const;
/**
* This method gets the value of the {@link #reachesIntoOuterContext} field
* as it existed prior to the introduction of the
* {@link #isPrecedenceFilterSuppressed} method.
*/
size_t getOuterContextDepth() const;
bool isPrecedenceFilterSuppressed() const;
void setPrecedenceFilterSuppressed(bool value);
/// An ATN configuration is equal to another if both have
/// the same state, they predict the same alternative, and
/// syntactic/semantic contexts are the same.
bool operator==(const ATNConfig& other) const;
bool operator!=(const ATNConfig& other) const;
virtual std::string toString();
std::string toString(bool showAlt);
private:
/**
* This field stores the bit mask for implementing the
* {@link #isPrecedenceFilterSuppressed} property as a bit within the
* existing {@link #reachesIntoOuterContext} field.
*/
static const size_t SUPPRESS_PRECEDENCE_FILTER;
};
} // namespace atn
} // namespace antlr4
// Hash function for ATNConfig.
namespace std {
using antlr4::atn::ATNConfig;
template <>
struct hash<ATNConfig> {
size_t operator()(const ATNConfig& x) const { return x.hashCode(); }
};
template <>
struct hash<std::vector<Ref<ATNConfig>>> {
size_t operator()(const std::vector<Ref<ATNConfig>>& vector) const {
std::size_t seed = 0;
for (auto& config : vector) {
seed ^= config->hashCode() + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
} // namespace std

View File

@ -1,224 +0,0 @@
/* 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.
*/
#include "Exceptions.h"
#include "atn/ATNConfig.h"
#include "atn/ATNSimulator.h"
#include "atn/PredictionContext.h"
#include "atn/SemanticContext.h"
#include "support/Arrays.h"
#include "atn/ATNConfigSet.h"
using namespace antlr4::atn;
using namespace antlrcpp;
ATNConfigSet::ATNConfigSet(bool fullCtx) : fullCtx(fullCtx) {
InitializeInstanceFields();
}
ATNConfigSet::ATNConfigSet(const Ref<ATNConfigSet>& old)
: ATNConfigSet(old->fullCtx) {
addAll(old);
uniqueAlt = old->uniqueAlt;
conflictingAlts = old->conflictingAlts;
hasSemanticContext = old->hasSemanticContext;
dipsIntoOuterContext = old->dipsIntoOuterContext;
}
ATNConfigSet::~ATNConfigSet() {}
bool ATNConfigSet::add(const Ref<ATNConfig>& config) {
return add(config, nullptr);
}
bool ATNConfigSet::add(const Ref<ATNConfig>& config,
PredictionContextMergeCache* mergeCache) {
if (_readonly) {
throw IllegalStateException("This set is readonly");
}
if (config->semanticContext != SemanticContext::NONE) {
hasSemanticContext = true;
}
if (config->getOuterContextDepth() > 0) {
dipsIntoOuterContext = true;
}
size_t hash = getHash(config.get());
ATNConfig* existing = _configLookup[hash];
if (existing == nullptr) {
_configLookup[hash] = config.get();
_cachedHashCode = 0;
configs.push_back(config); // track order here
return true;
}
// a previous (s,i,pi,_), merge with it and save result
bool rootIsWildcard = !fullCtx;
Ref<PredictionContext> 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
// cache at both places.
existing->reachesIntoOuterContext = std::max(
existing->reachesIntoOuterContext, config->reachesIntoOuterContext);
// make sure to preserve the precedence filter suppression during the merge
if (config->isPrecedenceFilterSuppressed()) {
existing->setPrecedenceFilterSuppressed(true);
}
existing->context = merged; // replace context; no need to alt mapping
return true;
}
bool ATNConfigSet::addAll(const Ref<ATNConfigSet>& other) {
for (auto& c : other->configs) {
add(c);
}
return false;
}
std::vector<ATNState*> ATNConfigSet::getStates() {
std::vector<ATNState*> states;
for (auto c : configs) {
states.push_back(c->state);
}
return states;
}
/**
* Gets the complete set of represented alternatives for the configuration
* set.
*
* @return the set of represented alternatives in this configuration set
*
* @since 4.3
*/
BitSet ATNConfigSet::getAlts() {
BitSet alts;
for (ATNConfig config : configs) {
alts.set(config.alt);
}
return alts;
}
std::vector<Ref<SemanticContext>> ATNConfigSet::getPredicates() {
std::vector<Ref<SemanticContext>> preds;
for (auto c : configs) {
if (c->semanticContext != SemanticContext::NONE) {
preds.push_back(c->semanticContext);
}
}
return preds;
}
Ref<ATNConfig> ATNConfigSet::get(size_t i) const { return configs[i]; }
void ATNConfigSet::optimizeConfigs(ATNSimulator* interpreter) {
if (_readonly) {
throw IllegalStateException("This set is readonly");
}
if (_configLookup.empty()) return;
for (auto& config : configs) {
config->context = interpreter->getCachedContext(config->context);
}
}
bool ATNConfigSet::operator==(const ATNConfigSet& other) {
if (&other == this) {
return true;
}
if (configs.size() != other.configs.size()) return false;
if (fullCtx != other.fullCtx || uniqueAlt != other.uniqueAlt ||
conflictingAlts != other.conflictingAlts ||
hasSemanticContext != other.hasSemanticContext ||
dipsIntoOuterContext !=
other.dipsIntoOuterContext) // includes stack context
return false;
return Arrays::equals(configs, other.configs);
}
size_t ATNConfigSet::hashCode() {
if (!isReadonly() || _cachedHashCode == 0) {
_cachedHashCode = 1;
for (auto& i : configs) {
_cachedHashCode = 31 * _cachedHashCode +
i->hashCode(); // Same as Java's list hashCode impl.
}
}
return _cachedHashCode;
}
size_t ATNConfigSet::size() { return configs.size(); }
bool ATNConfigSet::isEmpty() { return configs.empty(); }
void ATNConfigSet::clear() {
if (_readonly) {
throw IllegalStateException("This set is readonly");
}
configs.clear();
_cachedHashCode = 0;
_configLookup.clear();
}
bool ATNConfigSet::isReadonly() { return _readonly; }
void ATNConfigSet::setReadonly(bool readonly) {
_readonly = readonly;
_configLookup.clear();
}
std::string ATNConfigSet::toString() {
std::stringstream ss;
ss << "[";
for (size_t i = 0; i < configs.size(); i++) {
ss << configs[i]->toString();
}
ss << "]";
if (hasSemanticContext) {
ss << ",hasSemanticContext = " << hasSemanticContext;
}
if (uniqueAlt != ATN::INVALID_ALT_NUMBER) {
ss << ",uniqueAlt = " << uniqueAlt;
}
if (conflictingAlts.size() > 0) {
ss << ",conflictingAlts = ";
ss << conflictingAlts.toString();
}
if (dipsIntoOuterContext) {
ss << ", dipsIntoOuterContext";
}
return ss.str();
}
size_t ATNConfigSet::getHash(ATNConfig* c) {
size_t hashCode = 7;
hashCode = 31 * hashCode + c->state->stateNumber;
hashCode = 31 * hashCode + c->alt;
hashCode = 31 * hashCode + c->semanticContext->hashCode();
return hashCode;
}
void ATNConfigSet::InitializeInstanceFields() {
uniqueAlt = 0;
hasSemanticContext = false;
dipsIntoOuterContext = false;
_readonly = false;
_cachedHashCode = 0;
}

View File

@ -1,114 +0,0 @@
/* 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.
*/
#pragma once
#include "atn/PredictionContext.h"
#include "support/BitSet.h"
namespace antlr4 {
namespace atn {
/// Specialized set that can track info about the set, with support for
/// combining similar configurations using a graph-structured stack.
class ANTLR4CPP_PUBLIC ATNConfigSet {
public:
/// Track the elements as they are added to the set; supports get(i)
std::vector<Ref<ATNConfig>> configs;
// TO_DO: these fields make me pretty uncomfortable but nice to pack up info
// together, saves recomputation TO_DO: can we track conflicts as they are
// added to save scanning configs later?
size_t uniqueAlt;
/** Currently this is only used when we detect SLL conflict; this does
* not necessarily represent the ambiguous alternatives. In fact,
* I should also point out that this seems to include predicated alternatives
* that have predicates that evaluate to false. Computed in
* computeTargetState().
*/
antlrcpp::BitSet conflictingAlts;
// 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.
bool hasSemanticContext;
bool dipsIntoOuterContext;
/// Indicates that this configuration set is part of a full context
/// LL prediction. It will be used to determine how to merge $. With SLL
/// it's a wildcard whereas it is not for LL context merge.
const bool fullCtx;
ATNConfigSet(bool fullCtx = true);
ATNConfigSet(const Ref<ATNConfigSet>& old);
virtual ~ATNConfigSet();
virtual bool add(const Ref<ATNConfig>& config);
/// <summary>
/// Adding a new config means merging contexts with existing configs for
/// {@code (s, i, pi, _)}, where {@code s} is the
/// <seealso cref="ATNConfig#state"/>, {@code i} is the <seealso
/// cref="ATNConfig#alt"/>, and
/// {@code pi} is the <seealso cref="ATNConfig#semanticContext"/>. We use
/// {@code (s,i,pi)} as key.
/// <p/>
/// This method updates <seealso cref="#dipsIntoOuterContext"/> and
/// <seealso cref="#hasSemanticContext"/> when necessary.
/// </summary>
virtual bool add(const Ref<ATNConfig>& config,
PredictionContextMergeCache* mergeCache);
virtual std::vector<ATNState*> getStates();
/**
* Gets the complete set of represented alternatives for the configuration
* set.
*
* @return the set of represented alternatives in this configuration set
*
* @since 4.3
*/
antlrcpp::BitSet getAlts();
virtual std::vector<Ref<SemanticContext>> getPredicates();
virtual Ref<ATNConfig> get(size_t i) const;
virtual void optimizeConfigs(ATNSimulator* interpreter);
bool addAll(const Ref<ATNConfigSet>& other);
bool operator==(const ATNConfigSet& other);
virtual size_t hashCode();
virtual size_t size();
virtual bool isEmpty();
virtual void clear();
virtual bool isReadonly();
virtual void setReadonly(bool readonly);
virtual std::string toString();
protected:
/// Indicates that the set of configurations is read-only. Do not
/// allow any code to manipulate the set; DFA states will point at
/// the sets and they must not change. This does not protect the other
/// fields; in particular, conflictingAlts is set after
/// we've made this readonly.
bool _readonly;
virtual size_t getHash(ATNConfig* c); // Hash differs depending on set type.
private:
size_t _cachedHashCode;
/// All configs but hashed by (s, i, _, pi) not including context. Wiped out
/// when we go readonly as this set becomes a DFA state.
std::unordered_map<size_t, ATNConfig*> _configLookup;
void InitializeInstanceFields();
};
} // namespace atn
} // namespace antlr4

View File

@ -1,61 +0,0 @@
/* 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.
*/
#include "atn/ATNDeserializationOptions.h"
using namespace antlr4::atn;
ATNDeserializationOptions ATNDeserializationOptions::defaultOptions;
ATNDeserializationOptions::ATNDeserializationOptions() {
InitializeInstanceFields();
}
ATNDeserializationOptions::ATNDeserializationOptions(
ATNDeserializationOptions* options)
: ATNDeserializationOptions() {
this->verifyATN = options->verifyATN;
this->generateRuleBypassTransitions = options->generateRuleBypassTransitions;
}
ATNDeserializationOptions::~ATNDeserializationOptions() {}
const ATNDeserializationOptions&
ATNDeserializationOptions::getDefaultOptions() {
return defaultOptions;
}
bool ATNDeserializationOptions::isReadOnly() { return readOnly; }
void ATNDeserializationOptions::makeReadOnly() { readOnly = true; }
bool ATNDeserializationOptions::isVerifyATN() { return verifyATN; }
void ATNDeserializationOptions::setVerifyATN(bool verify) {
throwIfReadOnly();
verifyATN = verify;
}
bool ATNDeserializationOptions::isGenerateRuleBypassTransitions() {
return generateRuleBypassTransitions;
}
void ATNDeserializationOptions::setGenerateRuleBypassTransitions(
bool generate) {
throwIfReadOnly();
generateRuleBypassTransitions = generate;
}
void ATNDeserializationOptions::throwIfReadOnly() {
if (isReadOnly()) {
throw "The object is read only.";
}
}
void ATNDeserializationOptions::InitializeInstanceFields() {
readOnly = false;
verifyATN = true;
generateRuleBypassTransitions = false;
}

View File

@ -1,51 +0,0 @@
/* 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.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
namespace atn {
class ANTLR4CPP_PUBLIC ATNDeserializationOptions {
private:
static ATNDeserializationOptions defaultOptions;
bool readOnly;
bool verifyATN;
bool generateRuleBypassTransitions;
public:
ATNDeserializationOptions();
ATNDeserializationOptions(ATNDeserializationOptions* options);
ATNDeserializationOptions(ATNDeserializationOptions const&) = default;
virtual ~ATNDeserializationOptions();
ATNDeserializationOptions& operator=(ATNDeserializationOptions const&) =
default;
static const ATNDeserializationOptions& getDefaultOptions();
bool isReadOnly();
void makeReadOnly();
bool isVerifyATN();
void setVerifyATN(bool verify);
bool isGenerateRuleBypassTransitions();
void setGenerateRuleBypassTransitions(bool generate);
protected:
virtual void throwIfReadOnly();
private:
void InitializeInstanceFields();
};
} // namespace atn
} // namespace antlr4

View File

@ -1,813 +0,0 @@
/* 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.
*/
#include "atn/ATNDeserializationOptions.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "atn/ATNType.h"
#include "atn/BasicBlockStartState.h"
#include "atn/BasicState.h"
#include "atn/BlockEndState.h"
#include "atn/DecisionState.h"
#include "atn/EpsilonTransition.h"
#include "atn/LoopEndState.h"
#include "atn/PlusBlockStartState.h"
#include "atn/PlusLoopbackState.h"
#include "atn/RuleStartState.h"
#include "atn/RuleStopState.h"
#include "atn/RuleTransition.h"
#include "atn/StarLoopEntryState.h"
#include "atn/StarLoopbackState.h"
#include "atn/TokensStartState.h"
#include "Token.h"
#include "atn/ActionTransition.h"
#include "atn/AtomTransition.h"
#include "atn/NotSetTransition.h"
#include "atn/PrecedencePredicateTransition.h"
#include "atn/PredicateTransition.h"
#include "atn/RangeTransition.h"
#include "atn/SetTransition.h"
#include "atn/StarBlockStartState.h"
#include "atn/WildcardTransition.h"
#include "Exceptions.h"
#include "misc/IntervalSet.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "atn/LexerChannelAction.h"
#include "atn/LexerCustomAction.h"
#include "atn/LexerModeAction.h"
#include "atn/LexerMoreAction.h"
#include "atn/LexerPopModeAction.h"
#include "atn/LexerPushModeAction.h"
#include "atn/LexerSkipAction.h"
#include "atn/LexerTypeAction.h"
#include "atn/ATNDeserializer.h"
#include <string>
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;
const size_t ATNDeserializer::SERIALIZED_VERSION = 3;
namespace {
uint32_t deserializeInt32(const std::vector<uint16_t>& data, size_t offset) {
return (uint32_t)data[offset] | ((uint32_t)data[offset + 1] << 16);
}
ssize_t readUnicodeInt(const std::vector<uint16_t>& data, int& p) {
return static_cast<ssize_t>(data[p++]);
}
ssize_t readUnicodeInt32(const std::vector<uint16_t>& data, int& p) {
auto result = deserializeInt32(data, p);
p += 2;
return static_cast<ssize_t>(result);
}
// We templatize this on the function type so the optimizer can inline
// the 16- or 32-bit readUnicodeInt/readUnicodeInt32 as needed.
template <typename F>
void deserializeSets(const std::vector<uint16_t>& data, int& p,
std::vector<misc::IntervalSet>& sets, F readUnicode) {
int nsets = data[p++];
for (int i = 0; i < nsets; i++) {
int nintervals = data[p++];
misc::IntervalSet set;
bool containsEof = data[p++] != 0;
if (containsEof) {
set.add(-1);
}
for (int j = 0; j < nintervals; j++) {
auto a = readUnicode(data, p);
auto b = readUnicode(data, p);
set.add(a, b);
}
sets.push_back(set);
}
}
} // namespace
ATNDeserializer::ATNDeserializer()
: ATNDeserializer(ATNDeserializationOptions::getDefaultOptions()) {}
ATNDeserializer::ATNDeserializer(const ATNDeserializationOptions& dso)
: deserializationOptions(dso) {}
ATNDeserializer::~ATNDeserializer() {}
/**
* This value should never change. Updates following this version are
* reflected as change in the unique ID SERIALIZED_UUID.
*/
Guid ATNDeserializer::ADDED_PRECEDENCE_TRANSITIONS() {
return Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61");
}
Guid ATNDeserializer::ADDED_LEXER_ACTIONS() {
return Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E");
}
Guid ATNDeserializer::ADDED_UNICODE_SMP() {
return Guid("59627784-3BE5-417A-B9EB-8131A7286089");
}
Guid ATNDeserializer::SERIALIZED_UUID() { return ADDED_UNICODE_SMP(); }
Guid ATNDeserializer::BASE_SERIALIZED_UUID() {
return Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3");
}
std::vector<Guid>& ATNDeserializer::SUPPORTED_UUIDS() {
static std::vector<Guid> singleton = {
BASE_SERIALIZED_UUID(), ADDED_PRECEDENCE_TRANSITIONS(),
ADDED_LEXER_ACTIONS(), ADDED_UNICODE_SMP()};
return singleton;
}
bool ATNDeserializer::isFeatureSupported(const Guid& feature,
const Guid& actualUuid) {
auto featureIterator =
std::find(SUPPORTED_UUIDS().begin(), SUPPORTED_UUIDS().end(), feature);
if (featureIterator == SUPPORTED_UUIDS().end()) {
return false;
}
auto actualIterator =
std::find(SUPPORTED_UUIDS().begin(), SUPPORTED_UUIDS().end(), actualUuid);
if (actualIterator == SUPPORTED_UUIDS().end()) {
return false;
}
return std::distance(featureIterator, actualIterator) >= 0;
}
ATN ATNDeserializer::deserialize(const std::vector<uint16_t>& input) {
// Don't adjust the first value since that's the version number.
std::vector<uint16_t> data(input.size());
data[0] = input[0];
for (size_t i = 1; i < input.size(); ++i) {
data[i] = input[i] - 2;
}
int p = 0;
int version = data[p++];
if (version != SERIALIZED_VERSION) {
std::string reason = "Could not deserialize ATN with version" +
std::to_string(version) + "(expected " +
std::to_string(SERIALIZED_VERSION) + ").";
throw UnsupportedOperationException(reason);
}
Guid uuid = toUUID(data.data(), p);
p += 8;
auto uuidIterator =
std::find(SUPPORTED_UUIDS().begin(), SUPPORTED_UUIDS().end(), uuid);
if (uuidIterator == SUPPORTED_UUIDS().end()) {
std::string reason = "Could not deserialize ATN with UUID " +
uuid.toString() + " (expected " +
SERIALIZED_UUID().toString() + " or a legacy UUID).";
throw UnsupportedOperationException(reason);
}
bool supportsPrecedencePredicates =
isFeatureSupported(ADDED_PRECEDENCE_TRANSITIONS(), uuid);
bool supportsLexerActions = isFeatureSupported(ADDED_LEXER_ACTIONS(), uuid);
ATNType grammarType = (ATNType)data[p++];
size_t maxTokenType = data[p++];
ATN atn(grammarType, maxTokenType);
//
// STATES
//
std::vector<std::pair<LoopEndState*, size_t>> loopBackStateNumbers;
std::vector<std::pair<BlockStartState*, size_t>> endStateNumbers;
size_t nstates = data[p++];
for (size_t i = 0; i < nstates; i++) {
size_t stype = data[p++];
// ignore bad type of states
if (stype == ATNState::ATN_INVALID_TYPE) {
atn.addState(nullptr);
continue;
}
size_t ruleIndex = data[p++];
if (ruleIndex == 0xFFFF) {
ruleIndex = INVALID_INDEX;
}
ATNState* s = stateFactory(stype, ruleIndex);
if (stype == ATNState::LOOP_END) { // special case
int loopBackStateNumber = data[p++];
loopBackStateNumbers.push_back({(LoopEndState*)s, loopBackStateNumber});
} else if (is<BlockStartState*>(s)) {
int endStateNumber = data[p++];
endStateNumbers.push_back({(BlockStartState*)s, endStateNumber});
}
atn.addState(s);
}
// delay the assignment of loop back and end states until we know all the
// state instances have been initialized
for (auto& pair : loopBackStateNumbers) {
pair.first->loopBackState = atn.states[pair.second];
}
for (auto& pair : endStateNumbers) {
pair.first->endState = (BlockEndState*)atn.states[pair.second];
}
size_t numNonGreedyStates = data[p++];
for (size_t i = 0; i < numNonGreedyStates; i++) {
size_t stateNumber = data[p++];
// The serialized ATN must be specifying the right states, so that the
// cast below is correct.
((DecisionState*)atn.states[stateNumber])->nonGreedy = true;
}
if (supportsPrecedencePredicates) {
size_t numPrecedenceStates = data[p++];
for (size_t i = 0; i < numPrecedenceStates; i++) {
size_t stateNumber = data[p++];
((RuleStartState*)atn.states[stateNumber])->isLeftRecursiveRule = true;
}
}
//
// RULES
//
size_t nrules = data[p++];
for (size_t i = 0; i < nrules; i++) {
size_t s = data[p++];
// Also here, the serialized atn must ensure to point to the correct class
// type.
RuleStartState* startState = (RuleStartState*)atn.states[s];
atn.ruleToStartState.push_back(startState);
if (atn.grammarType == ATNType::LEXER) {
size_t tokenType = data[p++];
if (tokenType == 0xFFFF) {
tokenType = Token::EOF;
}
atn.ruleToTokenType.push_back(tokenType);
if (!isFeatureSupported(ADDED_LEXER_ACTIONS(), uuid)) {
// this piece of unused metadata was serialized prior to the
// addition of LexerAction
// int actionIndexIgnored = data[p++];
p++;
}
}
}
atn.ruleToStopState.resize(nrules);
for (ATNState* state : atn.states) {
if (!is<RuleStopState*>(state)) {
continue;
}
RuleStopState* stopState = static_cast<RuleStopState*>(state);
atn.ruleToStopState[state->ruleIndex] = stopState;
atn.ruleToStartState[state->ruleIndex]->stopState = stopState;
}
//
// MODES
//
size_t nmodes = data[p++];
for (size_t i = 0; i < nmodes; i++) {
size_t s = data[p++];
atn.modeToStartState.push_back(
static_cast<TokensStartState*>(atn.states[s]));
}
//
// SETS
//
std::vector<misc::IntervalSet> sets;
// First, deserialize sets with 16-bit arguments <= U+FFFF.
deserializeSets(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(ADDED_UNICODE_SMP(), uuid)) {
deserializeSets(data, p, sets, readUnicodeInt32);
}
//
// EDGES
//
int nedges = data[p++];
for (int i = 0; i < nedges; i++) {
size_t src = data[p];
size_t trg = data[p + 1];
size_t ttype = data[p + 2];
size_t arg1 = data[p + 3];
size_t arg2 = data[p + 4];
size_t arg3 = data[p + 5];
Transition* trans =
edgeFactory(atn, ttype, src, trg, arg1, arg2, arg3, sets);
ATNState* srcState = atn.states[src];
srcState->addTransition(trans);
p += 6;
}
// edges for rule stop states can be derived, so they aren't serialized
for (ATNState* state : atn.states) {
for (size_t i = 0; i < state->transitions.size(); i++) {
Transition* t = state->transitions[i];
if (!is<RuleTransition*>(t)) {
continue;
}
RuleTransition* ruleTransition = static_cast<RuleTransition*>(t);
size_t outermostPrecedenceReturn = INVALID_INDEX;
if (atn.ruleToStartState[ruleTransition->target->ruleIndex]
->isLeftRecursiveRule) {
if (ruleTransition->precedence == 0) {
outermostPrecedenceReturn = ruleTransition->target->ruleIndex;
}
}
EpsilonTransition* returnTransition = new EpsilonTransition(
ruleTransition->followState,
outermostPrecedenceReturn); /* mem check: freed in ANTState d-tor */
atn.ruleToStopState[ruleTransition->target->ruleIndex]->addTransition(
returnTransition);
}
}
for (ATNState* state : atn.states) {
if (is<BlockStartState*>(state)) {
BlockStartState* startState = static_cast<BlockStartState*>(state);
// we need to know the end state to set its start state
if (startState->endState == nullptr) {
throw IllegalStateException();
}
// block end states can only be associated to a single block start state
if (startState->endState->startState != nullptr) {
throw IllegalStateException();
}
startState->endState->startState = static_cast<BlockStartState*>(state);
}
if (is<PlusLoopbackState*>(state)) {
PlusLoopbackState* loopbackState = static_cast<PlusLoopbackState*>(state);
for (size_t i = 0; i < loopbackState->transitions.size(); i++) {
ATNState* target = loopbackState->transitions[i]->target;
if (is<PlusBlockStartState*>(target)) {
(static_cast<PlusBlockStartState*>(target))->loopBackState =
loopbackState;
}
}
} else if (is<StarLoopbackState*>(state)) {
StarLoopbackState* loopbackState = static_cast<StarLoopbackState*>(state);
for (size_t i = 0; i < loopbackState->transitions.size(); i++) {
ATNState* target = loopbackState->transitions[i]->target;
if (is<StarLoopEntryState*>(target)) {
(static_cast<StarLoopEntryState*>(target))->loopBackState =
loopbackState;
}
}
}
}
//
// DECISIONS
//
size_t ndecisions = data[p++];
for (size_t i = 1; i <= ndecisions; i++) {
size_t s = data[p++];
DecisionState* decState = dynamic_cast<DecisionState*>(atn.states[s]);
if (decState == nullptr) throw IllegalStateException();
atn.decisionToState.push_back(decState);
decState->decision = (int)i - 1;
}
//
// LEXER ACTIONS
//
if (atn.grammarType == ATNType::LEXER) {
if (supportsLexerActions) {
atn.lexerActions.resize(data[p++]);
for (size_t i = 0; i < atn.lexerActions.size(); i++) {
LexerActionType actionType = (LexerActionType)data[p++];
int data1 = data[p++];
if (data1 == 0xFFFF) {
data1 = -1;
}
int data2 = data[p++];
if (data2 == 0xFFFF) {
data2 = -1;
}
atn.lexerActions[i] = lexerActionFactory(actionType, data1, data2);
}
} else {
// for compatibility with older serialized ATNs, convert the old
// serialized action index for action transitions to the new
// form, which is the index of a LexerCustomAction
for (ATNState* state : atn.states) {
for (size_t i = 0; i < state->transitions.size(); i++) {
Transition* transition = state->transitions[i];
if (!is<ActionTransition*>(transition)) {
continue;
}
size_t ruleIndex =
static_cast<ActionTransition*>(transition)->ruleIndex;
size_t actionIndex =
static_cast<ActionTransition*>(transition)->actionIndex;
Ref<LexerCustomAction> lexerAction =
std::make_shared<LexerCustomAction>(ruleIndex, actionIndex);
state->transitions[i] = new ActionTransition(
transition->target, ruleIndex, atn.lexerActions.size(),
false); /* mem-check freed in ATNState d-tor */
delete transition; // ml: no longer needed since we just replaced it.
atn.lexerActions.push_back(lexerAction);
}
}
}
}
markPrecedenceDecisions(atn);
if (deserializationOptions.isVerifyATN()) {
verifyATN(atn);
}
if (deserializationOptions.isGenerateRuleBypassTransitions() &&
atn.grammarType == ATNType::PARSER) {
atn.ruleToTokenType.resize(atn.ruleToStartState.size());
for (size_t i = 0; i < atn.ruleToStartState.size(); i++) {
atn.ruleToTokenType[i] = int(atn.maxTokenType + i + 1);
}
for (std::vector<RuleStartState*>::size_type i = 0;
i < atn.ruleToStartState.size(); i++) {
BasicBlockStartState* bypassStart =
new BasicBlockStartState(); /* mem check: freed in ATN d-tor */
bypassStart->ruleIndex = (int)i;
atn.addState(bypassStart);
BlockEndState* bypassStop =
new BlockEndState(); /* mem check: freed in ATN d-tor */
bypassStop->ruleIndex = (int)i;
atn.addState(bypassStop);
bypassStart->endState = bypassStop;
atn.defineDecisionState(bypassStart);
bypassStop->startState = bypassStart;
ATNState* endState;
Transition* excludeTransition = nullptr;
if (atn.ruleToStartState[i]->isLeftRecursiveRule) {
// wrap from the beginning of the rule to the StarLoopEntryState
endState = nullptr;
for (ATNState* state : atn.states) {
if (state->ruleIndex != i) {
continue;
}
if (!is<StarLoopEntryState*>(state)) {
continue;
}
ATNState* maybeLoopEndState =
state->transitions[state->transitions.size() - 1]->target;
if (!is<LoopEndState*>(maybeLoopEndState)) {
continue;
}
if (maybeLoopEndState->epsilonOnlyTransitions &&
is<RuleStopState*>(maybeLoopEndState->transitions[0]->target)) {
endState = state;
break;
}
}
if (endState == nullptr) {
throw UnsupportedOperationException(
"Couldn't identify final state of the precedence rule prefix "
"section.");
}
excludeTransition = (static_cast<StarLoopEntryState*>(endState))
->loopBackState->transitions[0];
} else {
endState = atn.ruleToStopState[i];
}
// all non-excluded transitions that currently target end state need to
// target blockEnd instead
for (ATNState* state : atn.states) {
for (Transition* transition : state->transitions) {
if (transition == excludeTransition) {
continue;
}
if (transition->target == endState) {
transition->target = bypassStop;
}
}
}
// all transitions leaving the rule start state need to leave blockStart
// instead
while (atn.ruleToStartState[i]->transitions.size() > 0) {
Transition* transition = atn.ruleToStartState[i]->removeTransition(
atn.ruleToStartState[i]->transitions.size() - 1);
bypassStart->addTransition(transition);
}
// link the new states
atn.ruleToStartState[i]->addTransition(new EpsilonTransition(
bypassStart)); /* mem check: freed in ATNState d-tor */
bypassStop->addTransition(new EpsilonTransition(
endState)); /* mem check: freed in ATNState d-tor */
ATNState* matchState =
new BasicState(); /* mem check: freed in ATN d-tor */
atn.addState(matchState);
matchState->addTransition(new AtomTransition(
bypassStop,
atn.ruleToTokenType[i])); /* mem check: freed in ATNState d-tor */
bypassStart->addTransition(new EpsilonTransition(
matchState)); /* mem check: freed in ATNState d-tor */
}
if (deserializationOptions.isVerifyATN()) {
// reverify after modification
verifyATN(atn);
}
}
return atn;
}
/**
* Analyze the {@link StarLoopEntryState} states in the specified ATN to set
* the {@link StarLoopEntryState#isPrecedenceDecision} field to the
* correct value.
*
* @param atn The ATN.
*/
void ATNDeserializer::markPrecedenceDecisions(const ATN& atn) {
for (ATNState* state : atn.states) {
if (!is<StarLoopEntryState*>(state)) {
continue;
}
/* We analyze the ATN to determine if this ATN decision state is the
* decision for the closure block that determines whether a
* precedence rule should continue or complete.
*/
if (atn.ruleToStartState[state->ruleIndex]->isLeftRecursiveRule) {
ATNState* maybeLoopEndState =
state->transitions[state->transitions.size() - 1]->target;
if (is<LoopEndState*>(maybeLoopEndState)) {
if (maybeLoopEndState->epsilonOnlyTransitions &&
is<RuleStopState*>(maybeLoopEndState->transitions[0]->target)) {
static_cast<StarLoopEntryState*>(state)->isPrecedenceDecision = true;
}
}
}
}
}
void ATNDeserializer::verifyATN(const ATN& atn) {
// verify assumptions
for (ATNState* state : atn.states) {
if (state == nullptr) {
continue;
}
checkCondition(state->epsilonOnlyTransitions ||
state->transitions.size() <= 1);
if (is<PlusBlockStartState*>(state)) {
checkCondition(
(static_cast<PlusBlockStartState*>(state))->loopBackState != nullptr);
}
if (is<StarLoopEntryState*>(state)) {
StarLoopEntryState* starLoopEntryState =
static_cast<StarLoopEntryState*>(state);
checkCondition(starLoopEntryState->loopBackState != nullptr);
checkCondition(starLoopEntryState->transitions.size() == 2);
if (is<StarBlockStartState*>(
starLoopEntryState->transitions[0]->target)) {
checkCondition(static_cast<LoopEndState*>(
starLoopEntryState->transitions[1]->target) !=
nullptr);
checkCondition(!starLoopEntryState->nonGreedy);
} else if (is<LoopEndState*>(
starLoopEntryState->transitions[0]->target)) {
checkCondition(is<StarBlockStartState*>(
starLoopEntryState->transitions[1]->target));
checkCondition(starLoopEntryState->nonGreedy);
} else {
throw IllegalStateException();
}
}
if (is<StarLoopbackState*>(state)) {
checkCondition(state->transitions.size() == 1);
checkCondition(is<StarLoopEntryState*>(state->transitions[0]->target));
}
if (is<LoopEndState*>(state)) {
checkCondition((static_cast<LoopEndState*>(state))->loopBackState !=
nullptr);
}
if (is<RuleStartState*>(state)) {
checkCondition((static_cast<RuleStartState*>(state))->stopState !=
nullptr);
}
if (is<BlockStartState*>(state)) {
checkCondition((static_cast<BlockStartState*>(state))->endState !=
nullptr);
}
if (is<BlockEndState*>(state)) {
checkCondition((static_cast<BlockEndState*>(state))->startState !=
nullptr);
}
if (is<DecisionState*>(state)) {
DecisionState* decisionState = static_cast<DecisionState*>(state);
checkCondition(decisionState->transitions.size() <= 1 ||
decisionState->decision >= 0);
} else {
checkCondition(state->transitions.size() <= 1 ||
is<RuleStopState*>(state));
}
}
}
void ATNDeserializer::checkCondition(bool condition) {
checkCondition(condition, "");
}
void ATNDeserializer::checkCondition(bool condition,
const std::string& message) {
if (!condition) {
throw IllegalStateException(message);
}
}
Guid ATNDeserializer::toUUID(const unsigned short* data, size_t offset) {
return Guid((uint16_t*)data + offset, true);
}
/* mem check: all created instances are freed in the d-tor of the ATNState they
* are added to. */
Transition* ATNDeserializer::edgeFactory(
const ATN& atn, size_t type, size_t /*src*/, size_t trg, size_t arg1,
size_t arg2, size_t arg3, const std::vector<misc::IntervalSet>& sets) {
ATNState* target = atn.states[trg];
switch (type) {
case Transition::EPSILON:
return new EpsilonTransition(target);
case Transition::RANGE:
if (arg3 != 0) {
return new RangeTransition(target, Token::EOF, arg2);
} else {
return new RangeTransition(target, arg1, arg2);
}
case Transition::RULE:
return new RuleTransition(static_cast<RuleStartState*>(atn.states[arg1]),
arg2, (int)arg3, target);
case Transition::PREDICATE:
return new PredicateTransition(target, arg1, arg2, arg3 != 0);
case Transition::PRECEDENCE:
return new PrecedencePredicateTransition(target, (int)arg1);
case Transition::ATOM:
if (arg3 != 0) {
return new AtomTransition(target, Token::EOF);
} else {
return new AtomTransition(target, arg1);
}
case Transition::ACTION:
return new ActionTransition(target, arg1, arg2, arg3 != 0);
case Transition::SET:
return new SetTransition(target, sets[arg1]);
case Transition::NOT_SET:
return new NotSetTransition(target, sets[arg1]);
case Transition::WILDCARD:
return new WildcardTransition(target);
}
throw IllegalArgumentException("The specified transition type is not valid.");
}
/* mem check: all created instances are freed in the d-tor of the ATN. */
ATNState* ATNDeserializer::stateFactory(size_t type, size_t ruleIndex) {
ATNState* s;
switch (type) {
case ATNState::ATN_INVALID_TYPE:
return nullptr;
case ATNState::BASIC:
s = new BasicState();
break;
case ATNState::RULE_START:
s = new RuleStartState();
break;
case ATNState::BLOCK_START:
s = new BasicBlockStartState();
break;
case ATNState::PLUS_BLOCK_START:
s = new PlusBlockStartState();
break;
case ATNState::STAR_BLOCK_START:
s = new StarBlockStartState();
break;
case ATNState::TOKEN_START:
s = new TokensStartState();
break;
case ATNState::RULE_STOP:
s = new RuleStopState();
break;
case ATNState::BLOCK_END:
s = new BlockEndState();
break;
case ATNState::STAR_LOOP_BACK:
s = new StarLoopbackState();
break;
case ATNState::STAR_LOOP_ENTRY:
s = new StarLoopEntryState();
break;
case ATNState::PLUS_LOOP_BACK:
s = new PlusLoopbackState();
break;
case ATNState::LOOP_END:
s = new LoopEndState();
break;
default:
std::string message =
"The specified state type " + std::to_string(type) + " is not valid.";
throw IllegalArgumentException(message);
}
s->ruleIndex = ruleIndex;
return s;
}
Ref<LexerAction> ATNDeserializer::lexerActionFactory(LexerActionType type,
int data1, int data2) {
switch (type) {
case LexerActionType::CHANNEL:
return std::make_shared<LexerChannelAction>(data1);
case LexerActionType::CUSTOM:
return std::make_shared<LexerCustomAction>(data1, data2);
case LexerActionType::MODE:
return std::make_shared<LexerModeAction>(data1);
case LexerActionType::MORE:
return LexerMoreAction::getInstance();
case LexerActionType::POP_MODE:
return LexerPopModeAction::getInstance();
case LexerActionType::PUSH_MODE:
return std::make_shared<LexerPushModeAction>(data1);
case LexerActionType::SKIP:
return LexerSkipAction::getInstance();
case LexerActionType::TYPE:
return std::make_shared<LexerTypeAction>(data1);
default:
throw IllegalArgumentException("The specified lexer action type " +
std::to_string(static_cast<size_t>(type)) +
" is not valid.");
}
}

View File

@ -1,88 +0,0 @@
/* 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.
*/
#pragma once
#include "atn/ATNDeserializationOptions.h"
#include "atn/LexerAction.h"
namespace antlr4 {
namespace atn {
class ANTLR4CPP_PUBLIC ATNDeserializer {
public:
static const size_t SERIALIZED_VERSION;
/// This is the current serialized UUID.
// ml: defined as function to avoid the “static initialization order fiasco”.
static Guid SERIALIZED_UUID();
ATNDeserializer();
ATNDeserializer(const ATNDeserializationOptions& dso);
virtual ~ATNDeserializer();
static Guid toUUID(const unsigned short* data, size_t offset);
virtual ATN deserialize(const std::vector<uint16_t>& input);
virtual void verifyATN(const ATN& atn);
static void checkCondition(bool condition);
static void checkCondition(bool condition, const std::string& message);
static Transition* edgeFactory(const ATN& atn, size_t type, size_t src,
size_t trg, size_t arg1, size_t arg2,
size_t arg3,
const std::vector<misc::IntervalSet>& sets);
static ATNState* stateFactory(size_t type, size_t ruleIndex);
protected:
/// Determines if a particular serialized representation of an ATN supports
/// a particular feature, identified by the <seealso cref="UUID"/> used for
/// serializing the ATN at the time the feature was first introduced.
///
/// <param name="feature"> The <seealso cref="UUID"/> marking the first time
/// the feature was supported in the serialized ATN. </param> <param
/// name="actualUuid"> The <seealso cref="UUID"/> of the actual serialized ATN
/// which is currently being deserialized. </param> <returns> {@code true} if
/// the {@code actualUuid} value represents a serialized ATN at or after the
/// feature identified by {@code feature} was introduced; otherwise, {@code
/// false}. </returns>
virtual bool isFeatureSupported(const Guid& feature, const Guid& actualUuid);
void markPrecedenceDecisions(const ATN& atn);
Ref<LexerAction> lexerActionFactory(LexerActionType type, int data1,
int data2);
private:
/// This is the earliest supported serialized UUID.
static Guid BASE_SERIALIZED_UUID();
/// This UUID indicates an extension of <seealso cref="BASE_SERIALIZED_UUID"/>
/// for the addition of precedence predicates.
static Guid ADDED_PRECEDENCE_TRANSITIONS();
/**
* This UUID indicates an extension of ADDED_PRECEDENCE_TRANSITIONS
* for the addition of lexer actions encoded as a sequence of
* LexerAction instances.
*/
static Guid ADDED_LEXER_ACTIONS();
/**
* This UUID indicates the serialized ATN contains two sets of
* IntervalSets, where the second set's values are encoded as
* 32-bit integers to support the full Unicode SMP range up to U+10FFFF.
*/
static Guid ADDED_UNICODE_SMP();
/// This list contains all of the currently supported UUIDs, ordered by when
/// the feature first appeared in this branch.
static std::vector<Guid>& SUPPORTED_UUIDS();
ATNDeserializationOptions deserializationOptions;
};
} // namespace atn
} // namespace antlr4

View File

@ -1,622 +0,0 @@
/* 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.
*/
#include "atn/ATNState.h"
#include "atn/ATNType.h"
#include "atn/BlockEndState.h"
#include "misc/IntervalSet.h"
#include "Token.h"
#include "atn/ATN.h"
#include "atn/BlockStartState.h"
#include "atn/DecisionState.h"
#include "atn/LoopEndState.h"
#include "atn/RuleStartState.h"
#include "atn/SetTransition.h"
#include "atn/Transition.h"
#include "misc/Interval.h"
#include "atn/ATNDeserializer.h"
#include "atn/ActionTransition.h"
#include "atn/AtomTransition.h"
#include "atn/PrecedencePredicateTransition.h"
#include "atn/PredicateTransition.h"
#include "atn/RangeTransition.h"
#include "atn/RuleTransition.h"
#include "Exceptions.h"
#include "atn/TokensStartState.h"
#include "support/CPPUtils.h"
#include "atn/LexerChannelAction.h"
#include "atn/LexerCustomAction.h"
#include "atn/LexerModeAction.h"
#include "atn/LexerPushModeAction.h"
#include "atn/LexerTypeAction.h"
#include "Exceptions.h"
#include "atn/ATNSerializer.h"
using namespace antlrcpp;
using namespace antlr4::atn;
ATNSerializer::ATNSerializer(ATN* atn) { this->atn = atn; }
ATNSerializer::ATNSerializer(ATN* atn,
const std::vector<std::string>& tokenNames) {
this->atn = atn;
_tokenNames = tokenNames;
}
ATNSerializer::~ATNSerializer() {}
std::vector<size_t> ATNSerializer::serialize() {
std::vector<size_t> data;
data.push_back(ATNDeserializer::SERIALIZED_VERSION);
serializeUUID(data, ATNDeserializer::SERIALIZED_UUID());
// convert grammar type to ATN const to avoid dependence on ANTLRParser
data.push_back(static_cast<size_t>(atn->grammarType));
data.push_back(atn->maxTokenType);
size_t nedges = 0;
std::unordered_map<misc::IntervalSet, int> setIndices;
std::vector<misc::IntervalSet> sets;
// dump states, count edges and collect sets while doing so
std::vector<size_t> nonGreedyStates;
std::vector<size_t> precedenceStates;
data.push_back(atn->states.size());
for (ATNState* s : atn->states) {
if (s == nullptr) { // might be optimized away
data.push_back(ATNState::ATN_INVALID_TYPE);
continue;
}
size_t stateType = s->getStateType();
if (is<DecisionState*>(s) && (static_cast<DecisionState*>(s))->nonGreedy) {
nonGreedyStates.push_back(s->stateNumber);
}
if (is<RuleStartState*>(s) &&
(static_cast<RuleStartState*>(s))->isLeftRecursiveRule) {
precedenceStates.push_back(s->stateNumber);
}
data.push_back(stateType);
if (s->ruleIndex == INVALID_INDEX) {
data.push_back(0xFFFF);
} else {
data.push_back(s->ruleIndex);
}
if (s->getStateType() == ATNState::LOOP_END) {
data.push_back(
(static_cast<LoopEndState*>(s))->loopBackState->stateNumber);
} else if (is<BlockStartState*>(s)) {
data.push_back((static_cast<BlockStartState*>(s))->endState->stateNumber);
}
if (s->getStateType() != ATNState::RULE_STOP) {
// the deserializer can trivially derive these edges, so there's no need
// to serialize them
nedges += s->transitions.size();
}
for (size_t i = 0; i < s->transitions.size(); i++) {
Transition* t = s->transitions[i];
Transition::SerializationType edgeType = t->getSerializationType();
if (edgeType == Transition::SET || edgeType == Transition::NOT_SET) {
SetTransition* st = static_cast<SetTransition*>(t);
if (setIndices.find(st->set) == setIndices.end()) {
sets.push_back(st->set);
setIndices.insert({st->set, (int)sets.size() - 1});
}
}
}
}
// non-greedy states
data.push_back(nonGreedyStates.size());
for (size_t i = 0; i < nonGreedyStates.size(); i++) {
data.push_back(nonGreedyStates.at(i));
}
// precedence states
data.push_back(precedenceStates.size());
for (size_t i = 0; i < precedenceStates.size(); i++) {
data.push_back(precedenceStates.at(i));
}
size_t nrules = atn->ruleToStartState.size();
data.push_back(nrules);
for (size_t r = 0; r < nrules; r++) {
ATNState* ruleStartState = atn->ruleToStartState[r];
data.push_back(ruleStartState->stateNumber);
if (atn->grammarType == ATNType::LEXER) {
if (atn->ruleToTokenType[r] == Token::EOF) {
data.push_back(0xFFFF);
} else {
data.push_back(atn->ruleToTokenType[r]);
}
}
}
size_t nmodes = atn->modeToStartState.size();
data.push_back(nmodes);
if (nmodes > 0) {
for (const auto& modeStartState : atn->modeToStartState) {
data.push_back(modeStartState->stateNumber);
}
}
size_t nsets = sets.size();
data.push_back(nsets);
for (auto set : sets) {
bool containsEof = set.contains(Token::EOF);
if (containsEof && set.getIntervals().at(0).b == -1) {
data.push_back(set.getIntervals().size() - 1);
} else {
data.push_back(set.getIntervals().size());
}
data.push_back(containsEof ? 1 : 0);
for (auto& interval : set.getIntervals()) {
if (interval.a == -1) {
if (interval.b == -1) {
continue;
} else {
data.push_back(0);
}
} else {
data.push_back(interval.a);
}
data.push_back(interval.b);
}
}
data.push_back(nedges);
for (ATNState* s : atn->states) {
if (s == nullptr) {
// might be optimized away
continue;
}
if (s->getStateType() == ATNState::RULE_STOP) {
continue;
}
for (size_t i = 0; i < s->transitions.size(); i++) {
Transition* t = s->transitions[i];
if (atn->states[t->target->stateNumber] == nullptr) {
throw IllegalStateException(
"Cannot serialize a transition to a removed state.");
}
size_t src = s->stateNumber;
size_t trg = t->target->stateNumber;
Transition::SerializationType edgeType = t->getSerializationType();
size_t arg1 = 0;
size_t arg2 = 0;
size_t arg3 = 0;
switch (edgeType) {
case Transition::RULE:
trg = (static_cast<RuleTransition*>(t))->followState->stateNumber;
arg1 = (static_cast<RuleTransition*>(t))->target->stateNumber;
arg2 = (static_cast<RuleTransition*>(t))->ruleIndex;
arg3 = (static_cast<RuleTransition*>(t))->precedence;
break;
case Transition::PRECEDENCE: {
PrecedencePredicateTransition* ppt =
static_cast<PrecedencePredicateTransition*>(t);
arg1 = ppt->precedence;
} break;
case Transition::PREDICATE: {
PredicateTransition* pt = static_cast<PredicateTransition*>(t);
arg1 = pt->ruleIndex;
arg2 = pt->predIndex;
arg3 = pt->isCtxDependent ? 1 : 0;
} break;
case Transition::RANGE:
arg1 = (static_cast<RangeTransition*>(t))->from;
arg2 = (static_cast<RangeTransition*>(t))->to;
if (arg1 == Token::EOF) {
arg1 = 0;
arg3 = 1;
}
break;
case Transition::ATOM:
arg1 = (static_cast<AtomTransition*>(t))->_label;
if (arg1 == Token::EOF) {
arg1 = 0;
arg3 = 1;
}
break;
case Transition::ACTION: {
ActionTransition* at = static_cast<ActionTransition*>(t);
arg1 = at->ruleIndex;
arg2 = at->actionIndex;
if (arg2 == INVALID_INDEX) {
arg2 = 0xFFFF;
}
arg3 = at->isCtxDependent ? 1 : 0;
} break;
case Transition::SET:
arg1 = setIndices[(static_cast<SetTransition*>(t))->set];
break;
case Transition::NOT_SET:
arg1 = setIndices[(static_cast<SetTransition*>(t))->set];
break;
default:
break;
}
data.push_back(src);
data.push_back(trg);
data.push_back(edgeType);
data.push_back(arg1);
data.push_back(arg2);
data.push_back(arg3);
}
}
size_t ndecisions = atn->decisionToState.size();
data.push_back(ndecisions);
for (DecisionState* decStartState : atn->decisionToState) {
data.push_back(decStartState->stateNumber);
}
// LEXER ACTIONS
if (atn->grammarType == ATNType::LEXER) {
data.push_back(atn->lexerActions.size());
for (Ref<LexerAction>& action : atn->lexerActions) {
data.push_back(static_cast<size_t>(action->getActionType()));
switch (action->getActionType()) {
case LexerActionType::CHANNEL: {
int channel = std::dynamic_pointer_cast<LexerChannelAction>(action)
->getChannel();
data.push_back(channel != -1 ? channel : 0xFFFF);
data.push_back(0);
break;
}
case LexerActionType::CUSTOM: {
size_t ruleIndex =
std::dynamic_pointer_cast<LexerCustomAction>(action)
->getRuleIndex();
size_t actionIndex =
std::dynamic_pointer_cast<LexerCustomAction>(action)
->getActionIndex();
data.push_back(ruleIndex != INVALID_INDEX ? ruleIndex : 0xFFFF);
data.push_back(actionIndex != INVALID_INDEX ? actionIndex : 0xFFFF);
break;
}
case LexerActionType::MODE: {
int mode =
std::dynamic_pointer_cast<LexerModeAction>(action)->getMode();
data.push_back(mode != -1 ? mode : 0xFFFF);
data.push_back(0);
break;
}
case LexerActionType::MORE:
data.push_back(0);
data.push_back(0);
break;
case LexerActionType::POP_MODE:
data.push_back(0);
data.push_back(0);
break;
case LexerActionType::PUSH_MODE: {
int mode =
std::dynamic_pointer_cast<LexerPushModeAction>(action)->getMode();
data.push_back(mode != -1 ? mode : 0xFFFF);
data.push_back(0);
break;
}
case LexerActionType::SKIP:
data.push_back(0);
data.push_back(0);
break;
case LexerActionType::TYPE: {
int type =
std::dynamic_pointer_cast<LexerTypeAction>(action)->getType();
data.push_back(type != -1 ? type : 0xFFFF);
data.push_back(0);
break;
}
default:
throw IllegalArgumentException(
"The specified lexer action type " +
std::to_string(static_cast<size_t>(action->getActionType())) +
" is not valid.");
}
}
}
// don't adjust the first value since that's the version number
for (size_t i = 1; i < data.size(); i++) {
if (data.at(i) > 0xFFFF) {
throw UnsupportedOperationException(
"Serialized ATN data element out of range.");
}
size_t value = (data.at(i) + 2) & 0xFFFF;
data.at(i) = value;
}
return data;
}
//------------------------------------------------------------------------------------------------------------
std::string ATNSerializer::decode(const std::wstring& inpdata) {
if (inpdata.size() < 10)
throw IllegalArgumentException("Not enough data to decode");
std::vector<uint16_t> data(inpdata.size());
data[0] = (uint16_t)inpdata[0];
// Don't adjust the first value since that's the version number.
for (size_t i = 1; i < inpdata.size(); ++i) {
data[i] = (uint16_t)inpdata[i] - 2;
}
std::string buf;
size_t p = 0;
size_t version = data[p++];
if (version != ATNDeserializer::SERIALIZED_VERSION) {
std::string reason = "Could not deserialize ATN with version " +
std::to_string(version) + "(expected " +
std::to_string(ATNDeserializer::SERIALIZED_VERSION) +
").";
throw UnsupportedOperationException("ATN Serializer" + reason);
}
Guid uuid = ATNDeserializer::toUUID(data.data(), p);
p += 8;
if (uuid != ATNDeserializer::SERIALIZED_UUID()) {
std::string reason = "Could not deserialize ATN with UUID " +
uuid.toString() + " (expected " +
ATNDeserializer::SERIALIZED_UUID().toString() + ").";
throw UnsupportedOperationException("ATN Serializer" + reason);
}
p++; // skip grammarType
size_t maxType = data[p++];
buf.append("max type ").append(std::to_string(maxType)).append("\n");
size_t nstates = data[p++];
for (size_t i = 0; i < nstates; i++) {
size_t stype = data[p++];
if (stype == ATNState::ATN_INVALID_TYPE) { // ignore bad type of states
continue;
}
size_t ruleIndex = data[p++];
if (ruleIndex == 0xFFFF) {
ruleIndex = INVALID_INDEX;
}
std::string arg = "";
if (stype == ATNState::LOOP_END) {
int loopBackStateNumber = data[p++];
arg = std::string(" ") + std::to_string(loopBackStateNumber);
} else if (stype == ATNState::PLUS_BLOCK_START ||
stype == ATNState::STAR_BLOCK_START ||
stype == ATNState::BLOCK_START) {
int endStateNumber = data[p++];
arg = std::string(" ") + std::to_string(endStateNumber);
}
buf.append(std::to_string(i))
.append(":")
.append(ATNState::serializationNames[stype])
.append(" ")
.append(std::to_string(ruleIndex))
.append(arg)
.append("\n");
}
size_t numNonGreedyStates = data[p++];
p += numNonGreedyStates; // Instead of that useless loop below.
/*
for (int i = 0; i < numNonGreedyStates; i++) {
int stateNumber = data[p++];
}
*/
size_t numPrecedenceStates = data[p++];
p += numPrecedenceStates;
/*
for (int i = 0; i < numPrecedenceStates; i++) {
int stateNumber = data[p++];
}
*/
size_t nrules = data[p++];
for (size_t i = 0; i < nrules; i++) {
size_t s = data[p++];
if (atn->grammarType == ATNType::LEXER) {
size_t arg1 = data[p++];
buf.append("rule ")
.append(std::to_string(i))
.append(":")
.append(std::to_string(s))
.append(" ")
.append(std::to_string(arg1))
.append("\n");
} else {
buf.append("rule ")
.append(std::to_string(i))
.append(":")
.append(std::to_string(s))
.append("\n");
}
}
size_t nmodes = data[p++];
for (size_t i = 0; i < nmodes; i++) {
size_t s = data[p++];
buf.append("mode ")
.append(std::to_string(i))
.append(":")
.append(std::to_string(s))
.append("\n");
}
size_t nsets = data[p++];
for (size_t i = 0; i < nsets; i++) {
size_t nintervals = data[p++];
buf.append(std::to_string(i)).append(":");
bool containsEof = data[p++] != 0;
if (containsEof) {
buf.append(getTokenName(Token::EOF));
}
for (size_t j = 0; j < nintervals; j++) {
if (containsEof || j > 0) {
buf.append(", ");
}
buf.append(getTokenName(data[p]))
.append("..")
.append(getTokenName(data[p + 1]));
p += 2;
}
buf.append("\n");
}
size_t nedges = data[p++];
for (size_t i = 0; i < nedges; i++) {
size_t src = data[p];
size_t trg = data[p + 1];
size_t ttype = data[p + 2];
size_t arg1 = data[p + 3];
size_t arg2 = data[p + 4];
size_t arg3 = data[p + 5];
buf.append(std::to_string(src))
.append("->")
.append(std::to_string(trg))
.append(" ")
.append(Transition::serializationNames[ttype])
.append(" ")
.append(std::to_string(arg1))
.append(",")
.append(std::to_string(arg2))
.append(",")
.append(std::to_string(arg3))
.append("\n");
p += 6;
}
size_t ndecisions = data[p++];
for (size_t i = 0; i < ndecisions; i++) {
size_t s = data[p++];
buf += std::to_string(i) + ":" + std::to_string(s) + "\n";
}
if (atn->grammarType == ATNType::LEXER) {
// int lexerActionCount = data[p++];
// p += lexerActionCount * 3; // Instead of useless loop below.
/*
for (int i = 0; i < lexerActionCount; i++) {
LexerActionType actionType = (LexerActionType)data[p++];
int data1 = data[p++];
int data2 = data[p++];
}
*/
}
return buf;
}
std::string ATNSerializer::getTokenName(size_t t) {
if (t == Token::EOF) {
return "EOF";
}
if (atn->grammarType == ATNType::LEXER && t <= 0x10FFFF) {
switch (t) {
case '\n':
return "'\\n'";
case '\r':
return "'\\r'";
case '\t':
return "'\\t'";
case '\b':
return "'\\b'";
case '\f':
return "'\\f'";
case '\\':
return "'\\\\'";
case '\'':
return "'\\''";
default:
std::string s_hex = antlrcpp::toHexString((int)t);
if (s_hex >= "0" && s_hex <= "7F" && !iscntrl((int)t)) {
return "'" + std::to_string(t) + "'";
}
// turn on the bit above max "\u10FFFF" value so that we pad with zeros
// then only take last 6 digits
std::string hex =
antlrcpp::toHexString((int)t | 0x1000000).substr(1, 6);
std::string unicodeStr = std::string("'\\u") + hex + std::string("'");
return unicodeStr;
}
}
if (_tokenNames.size() > 0 && t < _tokenNames.size()) {
return _tokenNames[t];
}
return std::to_string(t);
}
std::wstring ATNSerializer::getSerializedAsString(ATN* atn) {
std::vector<size_t> data = getSerialized(atn);
std::wstring result;
for (size_t entry : data) result.push_back((wchar_t)entry);
return result;
}
std::vector<size_t> ATNSerializer::getSerialized(ATN* atn) {
return ATNSerializer(atn).serialize();
}
std::string ATNSerializer::getDecoded(ATN* atn,
std::vector<std::string>& tokenNames) {
std::wstring serialized = getSerializedAsString(atn);
return ATNSerializer(atn, tokenNames).decode(serialized);
}
void ATNSerializer::serializeUUID(std::vector<size_t>& data, Guid uuid) {
unsigned int twoBytes = 0;
bool firstByte = true;
for (std::vector<unsigned char>::const_reverse_iterator rit = uuid.rbegin();
rit != uuid.rend(); ++rit) {
if (firstByte) {
twoBytes = *rit;
firstByte = false;
} else {
twoBytes |= (*rit << 8);
data.push_back(twoBytes);
firstByte = true;
}
}
if (!firstByte)
throw IllegalArgumentException(
"The UUID provided is not valid (odd number of bytes).");
}

Some files were not shown because too many files have changed in this diff Show More