|
| 1 | +//===-- DILLexer.h ----------------------------------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | + |
| 9 | +#ifndef LLDB_VALUEOBJECT_DILLEXER_H |
| 10 | +#define LLDB_VALUEOBJECT_DILLEXER_H |
| 11 | + |
| 12 | +#include "llvm/ADT/StringRef.h" |
| 13 | +#include "llvm/Support/Error.h" |
| 14 | +#include <cstdint> |
| 15 | +#include <limits.h> |
| 16 | +#include <memory> |
| 17 | +#include <string> |
| 18 | +#include <vector> |
| 19 | + |
| 20 | +namespace lldb_private::dil { |
| 21 | + |
| 22 | +/// Class defining the tokens generated by the DIL lexer and used by the |
| 23 | +/// DIL parser. |
| 24 | +class Token { |
| 25 | +public: |
| 26 | + enum Kind { |
| 27 | + coloncolon, |
| 28 | + eof, |
| 29 | + identifier, |
| 30 | + l_paren, |
| 31 | + r_paren, |
| 32 | + }; |
| 33 | + |
| 34 | + Token(Kind kind, std::string spelling, uint32_t start) |
| 35 | + : m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {} |
| 36 | + |
| 37 | + Kind GetKind() const { return m_kind; } |
| 38 | + |
| 39 | + std::string GetSpelling() const { return m_spelling; } |
| 40 | + |
| 41 | + bool Is(Kind kind) const { return m_kind == kind; } |
| 42 | + |
| 43 | + bool IsNot(Kind kind) const { return m_kind != kind; } |
| 44 | + |
| 45 | + bool IsOneOf(Kind kind1, Kind kind2) const { return Is(kind1) || Is(kind2); } |
| 46 | + |
| 47 | + template <typename... Ts> bool IsOneOf(Kind kind, Ts... Ks) const { |
| 48 | + return Is(kind) || IsOneOf(Ks...); |
| 49 | + } |
| 50 | + |
| 51 | + uint32_t GetLocation() const { return m_start_pos; } |
| 52 | + |
| 53 | + static llvm::StringRef GetTokenName(Kind kind); |
| 54 | + |
| 55 | +private: |
| 56 | + Kind m_kind; |
| 57 | + std::string m_spelling; |
| 58 | + uint32_t m_start_pos; // within entire expression string |
| 59 | +}; |
| 60 | + |
| 61 | +/// Class for doing the simple lexing required by DIL. |
| 62 | +class DILLexer { |
| 63 | +public: |
| 64 | + /// Lexes all the tokens in expr and calls the private constructor |
| 65 | + /// with the lexed tokens. |
| 66 | + static llvm::Expected<DILLexer> Create(llvm::StringRef expr); |
| 67 | + |
| 68 | + /// Return the current token to be handled by the DIL parser. |
| 69 | + const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; } |
| 70 | + |
| 71 | + /// Advance the current token position by N. |
| 72 | + void Advance(uint32_t N = 1) { |
| 73 | + if (m_tokens_idx + N >= m_lexed_tokens.size()) |
| 74 | + // N is too large; advance to the end of the lexed tokens. |
| 75 | + m_tokens_idx = m_lexed_tokens.size() - 1; |
| 76 | + else |
| 77 | + m_tokens_idx += N; |
| 78 | + } |
| 79 | + |
| 80 | + /// Return the lexed token N positions ahead of the 'current' token |
| 81 | + /// being handled by the DIL parser. |
| 82 | + const Token &LookAhead(uint32_t N) { |
| 83 | + if (m_tokens_idx + N < m_lexed_tokens.size()) |
| 84 | + return m_lexed_tokens[m_tokens_idx + N]; |
| 85 | + |
| 86 | + // Last token should be an 'eof' token. |
| 87 | + return m_lexed_tokens.back(); |
| 88 | + } |
| 89 | + |
| 90 | + /// Return the index for the 'current' token being handled by the DIL parser. |
| 91 | + uint32_t GetCurrentTokenIdx() { return m_tokens_idx; } |
| 92 | + |
| 93 | + /// Set the index for the 'current' token (to be handled by the parser) |
| 94 | + /// to a particular position. Used for either committing 'look ahead' parsing |
| 95 | + /// or rolling back tentative parsing. |
| 96 | + void ResetTokenIdx(uint32_t new_value) { |
| 97 | + assert(new_value < m_lexed_tokens.size()); |
| 98 | + m_tokens_idx = new_value; |
| 99 | + } |
| 100 | + |
| 101 | + uint32_t NumLexedTokens() { return m_lexed_tokens.size(); } |
| 102 | + |
| 103 | +private: |
| 104 | + DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens) |
| 105 | + : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)), |
| 106 | + m_tokens_idx(0), m_eof_token(Token(Token::eof, "", 0)) {} |
| 107 | + |
| 108 | + static llvm::Expected<Token> Lex(llvm::StringRef expr, |
| 109 | + llvm::StringRef &remainder); |
| 110 | + |
| 111 | + // The input string we are lexing & parsing. |
| 112 | + llvm::StringRef m_expr; |
| 113 | + |
| 114 | + // Holds all of the tokens lexed so far. |
| 115 | + std::vector<Token> m_lexed_tokens; |
| 116 | + |
| 117 | + // Index into m_lexed_tokens; indicates which token the DIL parser is |
| 118 | + // currently trying to parse/handle. |
| 119 | + uint32_t m_tokens_idx; |
| 120 | + |
| 121 | + // "eof" token; to be returned by lexer when 'look ahead' fails. |
| 122 | + Token m_eof_token; |
| 123 | +}; |
| 124 | + |
| 125 | +} // namespace lldb_private::dil |
| 126 | + |
| 127 | +#endif // LLDB_VALUEOBJECT_DILLEXER_H |
0 commit comments