1 /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
2 * Use of this file is governed by the BSD 3-clause license that
3 * can be found in the LICENSE.txt file in the project root.
6 #include "misc/MurmurHash.h"
7 #include "atn/LexerIndexedCustomAction.h"
8 #include "support/CPPUtils.h"
9 #include "support/Arrays.h"
11 #include "atn/LexerActionExecutor.h"
13 using namespace antlr4;
14 using namespace antlr4::atn;
15 using namespace antlr4::misc;
16 using namespace antlrcpp;
18 LexerActionExecutor::LexerActionExecutor(const std::vector<Ref<LexerAction>> &lexerActions)
19 : _lexerActions(lexerActions), _hashCode(generateHashCode()) {
22 LexerActionExecutor::~LexerActionExecutor() {
25 Ref<LexerActionExecutor> LexerActionExecutor::append(Ref<LexerActionExecutor> const& lexerActionExecutor,
26 Ref<LexerAction> const& lexerAction) {
27 if (lexerActionExecutor == nullptr) {
28 return std::make_shared<LexerActionExecutor>(std::vector<Ref<LexerAction>> { lexerAction });
31 std::vector<Ref<LexerAction>> lexerActions = lexerActionExecutor->_lexerActions; // Make a copy.
32 lexerActions.push_back(lexerAction);
33 return std::make_shared<LexerActionExecutor>(lexerActions);
36 Ref<LexerActionExecutor> LexerActionExecutor::fixOffsetBeforeMatch(int offset) {
37 std::vector<Ref<LexerAction>> updatedLexerActions;
38 for (size_t i = 0; i < _lexerActions.size(); i++) {
39 if (_lexerActions[i]->isPositionDependent() && !is<LexerIndexedCustomAction>(_lexerActions[i])) {
40 if (updatedLexerActions.empty()) {
41 updatedLexerActions = _lexerActions; // Make a copy.
44 updatedLexerActions[i] = std::make_shared<LexerIndexedCustomAction>(offset, _lexerActions[i]);
48 if (updatedLexerActions.empty()) {
49 return shared_from_this();
52 return std::make_shared<LexerActionExecutor>(updatedLexerActions);
55 std::vector<Ref<LexerAction>> LexerActionExecutor::getLexerActions() const {
59 void LexerActionExecutor::execute(Lexer *lexer, CharStream *input, size_t startIndex) {
60 bool requiresSeek = false;
61 size_t stopIndex = input->index();
63 auto onExit = finally([requiresSeek, input, stopIndex]() {
65 input->seek(stopIndex);
68 for (auto lexerAction : _lexerActions) {
69 if (is<LexerIndexedCustomAction>(lexerAction)) {
70 int offset = (std::static_pointer_cast<LexerIndexedCustomAction>(lexerAction))->getOffset();
71 input->seek(startIndex + offset);
72 lexerAction = std::static_pointer_cast<LexerIndexedCustomAction>(lexerAction)->getAction();
73 requiresSeek = (startIndex + offset) != stopIndex;
74 } else if (lexerAction->isPositionDependent()) {
75 input->seek(stopIndex);
79 lexerAction->execute(lexer);
83 size_t LexerActionExecutor::hashCode() const {
87 bool LexerActionExecutor::operator == (const LexerActionExecutor &obj) const {
92 return _hashCode == obj._hashCode && Arrays::equals(_lexerActions, obj._lexerActions);
95 bool LexerActionExecutor::operator != (const LexerActionExecutor &obj) const {
96 return !operator==(obj);
99 size_t LexerActionExecutor::generateHashCode() const {
100 size_t hash = MurmurHash::initialize();
101 for (auto lexerAction : _lexerActions) {
102 hash = MurmurHash::update(hash, lexerAction);
104 hash = MurmurHash::finish(hash, _lexerActions.size());