Lexer.hpp
A general-purpose, fast lexer.
This file is part of Empirical, https://github.com/devosoft/Empirical Copyright (C) 2016-2024 Michigan State University MIT Software license; see doc/LICENSE.md
Build a lexer that can convert input strings or streams into a series of provided tokens.
Use AddToken(name, regex) to provide the relevant tokens. ‘name’ is the unique name for this token. ‘regex’ is the regular expression that describes this token. It will return a unique ID associated with this token that will be used in output Token objects later. You may provide additional arguments to indicate of the lexeme should be saved in a token, whether the token should be saved at all (unsaved token types are simply left out of the output), and a more detailed description.
IgnoreToken(name, regex) uses the same arguments, but is used for tokens that should be skipped over during lexical analysis
Names and IDs can be recovered later using GetTokenID(name) and GetTokenName(id).
Either strings or streams can be converted into their associated Tokens. Tokenize(in) returns the entire series of tokens as a TokenStream. TokenizeNext(in, &line) return the next token only, and updates the line number Process(in) returns the next token (even if it’s normally ignored); does not track line
Finally, GetLexeme() returns the lexeme from the most recent token found.
Note
Status: BETA
Defines
-
INCLUDE_EMP_COMPILER_LEXER_HPP_GUARD
Typedefs
-
using Lexer = Lexer_Base<255>
-
template<int MAX_ID>
class Lexer_Base - #include <Lexer.hpp>
A lexer with a set of token types (and associated regular expressions) MAX_ID determines the maximum number of allowed lexical rules.
Public Functions
-
inline size_t GetNumTokens() const
How many types of tokens can be identified in this Lexer?
-
void Reset()
Reset the entire lexer to its start state.
-
int AddToken(String name, String regex, bool save_lexeme = true, bool save_token = true, String desc = "")
Add a new token, specified by a name and the regex used to identify it. Note that token ids count down with highest IDs having priority.
-
int IgnoreToken(String name, String regex, String desc = "")
Add a token to ignore, specified by a name and the regex used to identify it.
-
int GetTokenID(String name) const
Get the ID associated with a token type (you provide the token name)
-
const TokenType &GetTokenType(int id) const
Get the full information about a token (you provide the id)
-
bool GetSaveToken(int id) const
Identify if a token should be saved.
-
void Generate() const
Create the NFA that will identify the current set of tokens in a sequence.
-
Token TokenizeNext(std::string_view in_str, size_t &cur_line, size_t &start_pos, bool keep_all = false) const
Perform a single step in the Tokenize process, updating line number and start position as we go.
-
Token TokenizeNext(std::istream &in_stream, size_t &cur_line, bool keep_all = false) const
Perform a single step in the Tokenize process, updating line number as we go.
-
inline Token TokenizeNext(std::istream &in_stream) const
Perform a single step in the Tokenize process.
-
TokenStream Tokenize(std::string_view str, String name = "in_view", bool keep_all = false) const
Turn an input string into a vector of tokens.
-
TokenStream Tokenize(std::istream &is, String name = "in_stream", bool keep_all = false) const
Turn an input stream of text into a vector of tokens.
-
TokenStream Tokenize(const vector<String> &str_v, String name = "in_string vector", bool keep_all = false) const
Turn a vector of strings into a vector of tokens.
-
void Print(std::ostream &os = std::cout) const
Print the full information about this lexer (for debugging)
-
void DebugString(String test_string) const
Try out the lexer on a string and demonstrate how it’s tokenized.
-
void DebugToken(int token_id) const
Private Functions
-
Token Process(std::string_view in_str, size_t &start_pos) const
Get the next token found in an input string. Do so by examining one character at a time. Keep going as long as there is a chance of a valid lexeme (since we need to choose the longest one available), saving best option so far. Once no more other valid lexemes are possible, stop and return the best we’ve found so far.
Private Members
-
mutable bool generate_lexer = false
Do we need to regenerate the lexer?
Private Static Functions
-
static inline const TokenType &ERROR_TOKEN()
Private Static Attributes
-
static constexpr int ERROR_ID = -1
Code for unknown token ID.
-
inline size_t GetNumTokens() const