/* 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 "atn/LexerAction.h" namespace antlr4 { namespace atn { /// Represents an executor for a sequence of lexer actions which traversed during /// the matching operation of a lexer rule (token). /// /// The executor tracks position information for position-dependent lexer actions /// efficiently, ensuring that actions appearing only at the end of the rule do /// not cause bloating of the created for the lexer. class ANTLR4CPP_PUBLIC LexerActionExecutor final : public std::enable_shared_from_this { public: /// /// Constructs an executor for a sequence of actions. /// The lexer actions to execute. explicit LexerActionExecutor(std::vector> lexerActions); /// /// Creates a which executes the actions for /// the input {@code lexerActionExecutor} followed by a specified /// {@code lexerAction}. /// /// The executor for actions already traversed by /// the lexer while matching a token within a particular /// . If this is {@code null}, the method behaves as /// though it were an empty executor. /// The lexer action to execute after the actions /// specified in {@code lexerActionExecutor}. /// /// A for executing the combine actions /// of {@code lexerActionExecutor} and {@code lexerAction}. static Ref append(const Ref &lexerActionExecutor, Ref lexerAction); /// /// Creates a which encodes the current offset /// for position-dependent lexer actions. /// /// Normally, when the executor encounters lexer actions where /// returns {@code true}, it calls /// on the input to set the input /// position to the end of the current token. This behavior provides /// for efficient DFA representation of lexer actions which appear at the end /// of a lexer rule, even when the lexer rule matches a variable number of /// characters. /// /// Prior to traversing a match transition in the ATN, the current offset /// from the token start index is assigned to all position-dependent lexer /// actions which have not already been assigned a fixed offset. By storing /// the offsets relative to the token start index, the DFA representation of /// lexer actions which appear in the middle of tokens remains efficient due /// to sharing among tokens of the same length, regardless of their absolute /// position in the input stream. /// /// If the current executor already has offsets assigned to all /// position-dependent lexer actions, the method returns {@code this}. /// /// The current offset to assign to all position-dependent /// lexer actions which do not already have offsets assigned. /// /// A which stores input stream offsets /// for all position-dependent lexer actions. Ref fixOffsetBeforeMatch(int offset) const; /// /// Gets the lexer actions to be executed by this executor. /// The lexer actions to be executed by this executor. const std::vector>& getLexerActions() const; /// /// Execute the actions encapsulated by this executor within the context of a /// particular . /// /// This method calls to set the position of the /// {@code input} prior to calling /// on a position-dependent action. Before the /// method returns, the input position will be restored to the same position /// it was in when the method was invoked. /// /// The lexer instance. /// The input stream which is the source for the current token. /// When this method is called, the current for /// {@code input} should be the start of the following token, i.e. 1 /// character past the end of the current token. /// The token start index. This value may be passed to /// to set the {@code input} position to the beginning /// of the token. void execute(Lexer *lexer, CharStream *input, size_t startIndex) const; size_t hashCode() const; bool equals(const LexerActionExecutor &other) const; private: const std::vector> _lexerActions; mutable std::atomic _hashCode; }; inline bool operator==(const LexerActionExecutor &lhs, const LexerActionExecutor &rhs) { return lhs.equals(rhs); } inline bool operator!=(const LexerActionExecutor &lhs, const LexerActionExecutor &rhs) { return !operator==(lhs, rhs); } } // namespace atn } // namespace antlr4 namespace std { template <> struct hash<::antlr4::atn::LexerActionExecutor> { size_t operator()(const ::antlr4::atn::LexerActionExecutor &lexerActionExecutor) const { return lexerActionExecutor.hashCode(); } }; } // namespace std