[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:
parent
7221681b7b
commit
29d08f1cd8
342
third_party/antlr4/BUILD.gn
vendored
342
third_party/antlr4/BUILD.gn
vendored
@ -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",
|
||||
]
|
||||
}
|
52
third_party/antlr4/LICENSE.txt
vendored
52
third_party/antlr4/LICENSE.txt
vendored
@ -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.
|
59
third_party/antlr4/runtime/Cpp/README.md
vendored
59
third_party/antlr4/runtime/Cpp/README.md
vendored
@ -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.
|
||||
|
1
third_party/antlr4/runtime/Cpp/VERSION
vendored
1
third_party/antlr4/runtime/Cpp/VERSION
vendored
@ -1 +0,0 @@
|
||||
4.7.1
|
@ -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() {}
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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; }
|
@ -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
|
@ -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; }
|
@ -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
|
@ -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*/) {}
|
@ -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
|
@ -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*/) {}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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));
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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 → expr → atom
|
||||
* </pre>
|
||||
*
|
||||
* and it will be trying to match the {@code ')'} at this point in the
|
||||
* derivation:
|
||||
*
|
||||
* <pre>
|
||||
* => 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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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; }
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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;
|
@ -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
|
@ -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; }
|
@ -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
|
274
third_party/antlr4/runtime/Cpp/runtime/src/Lexer.cpp
vendored
274
third_party/antlr4/runtime/Cpp/runtime/src/Lexer.cpp
vendored
@ -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;
|
||||
}
|
198
third_party/antlr4/runtime/Cpp/runtime/src/Lexer.h
vendored
198
third_party/antlr4/runtime/Cpp/runtime/src/Lexer.h
vendored
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
489
third_party/antlr4/runtime/Cpp/runtime/src/Parser.h
vendored
489
third_party/antlr4/runtime/Cpp/runtime/src/Parser.h
vendored
@ -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<String> 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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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()) + '}';
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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; }
|
@ -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
|
@ -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; }
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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
|
@ -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() {}
|
@ -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
|
@ -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>;
|
@ -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"
|
@ -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();
|
||||
}
|
115
third_party/antlr4/runtime/Cpp/runtime/src/atn/ATN.h
vendored
115
third_party/antlr4/runtime/Cpp/runtime/src/atn/ATN.h
vendored
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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.");
|
||||
}
|
||||
}
|
@ -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
|
@ -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
Loading…
Reference in New Issue
Block a user