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 "llvm/Support/FormatVariadic.h" 15 #include <cstdint> 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 amp, 28 arrow, 29 coloncolon, 30 eof, 31 identifier, 32 l_paren, 33 l_square, 34 minus, 35 numeric_constant, 36 period, 37 r_paren, 38 r_square, 39 star, 40 }; 41 Token(Kind kind,std::string spelling,uint32_t start)42 Token(Kind kind, std::string spelling, uint32_t start) 43 : m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {} 44 GetKind()45 Kind GetKind() const { return m_kind; } 46 GetSpelling()47 std::string GetSpelling() const { return m_spelling; } 48 Is(Kind kind)49 bool Is(Kind kind) const { return m_kind == kind; } 50 IsNot(Kind kind)51 bool IsNot(Kind kind) const { return m_kind != kind; } 52 IsOneOf(llvm::ArrayRef<Kind> kinds)53 bool IsOneOf(llvm::ArrayRef<Kind> kinds) const { 54 return llvm::is_contained(kinds, m_kind); 55 } 56 GetLocation()57 uint32_t GetLocation() const { return m_start_pos; } 58 59 static llvm::StringRef GetTokenName(Kind kind); 60 61 private: 62 Kind m_kind; 63 std::string m_spelling; 64 uint32_t m_start_pos; // within entire expression string 65 }; 66 67 /// Class for doing the simple lexing required by DIL. 68 class DILLexer { 69 public: 70 /// Lexes all the tokens in expr and calls the private constructor 71 /// with the lexed tokens. 72 static llvm::Expected<DILLexer> Create(llvm::StringRef expr); 73 74 /// Return the current token to be handled by the DIL parser. GetCurrentToken()75 const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; } 76 77 /// Advance the current token position by N. 78 void Advance(uint32_t N = 1) { 79 if (m_tokens_idx + N >= m_lexed_tokens.size()) 80 // N is too large; advance to the end of the lexed tokens. 81 m_tokens_idx = m_lexed_tokens.size() - 1; 82 else 83 m_tokens_idx += N; 84 } 85 86 /// Return the lexed token N positions ahead of the 'current' token 87 /// being handled by the DIL parser. LookAhead(uint32_t N)88 const Token &LookAhead(uint32_t N) { 89 if (m_tokens_idx + N < m_lexed_tokens.size()) 90 return m_lexed_tokens[m_tokens_idx + N]; 91 92 // Last token should be an 'eof' token. 93 return m_lexed_tokens.back(); 94 } 95 96 /// Return the index for the 'current' token being handled by the DIL parser. GetCurrentTokenIdx()97 uint32_t GetCurrentTokenIdx() { return m_tokens_idx; } 98 99 /// Set the index for the 'current' token (to be handled by the parser) 100 /// to a particular position. Used for either committing 'look ahead' parsing 101 /// or rolling back tentative parsing. ResetTokenIdx(uint32_t new_value)102 void ResetTokenIdx(uint32_t new_value) { 103 assert(new_value < m_lexed_tokens.size()); 104 m_tokens_idx = new_value; 105 } 106 NumLexedTokens()107 uint32_t NumLexedTokens() { return m_lexed_tokens.size(); } 108 109 private: DILLexer(llvm::StringRef dil_expr,std::vector<Token> lexed_tokens)110 DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens) 111 : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)), 112 m_tokens_idx(0) {} 113 114 static llvm::Expected<Token> Lex(llvm::StringRef expr, 115 llvm::StringRef &remainder); 116 117 // The input string we are lexing & parsing. 118 llvm::StringRef m_expr; 119 120 // Holds all of the tokens lexed so far. 121 std::vector<Token> m_lexed_tokens; 122 123 // Index into m_lexed_tokens; indicates which token the DIL parser is 124 // currently trying to parse/handle. 125 uint32_t m_tokens_idx; 126 }; 127 128 } // namespace lldb_private::dil 129 130 namespace llvm { 131 132 template <> struct format_provider<lldb_private::dil::Token::Kind> { 133 static void format(const lldb_private::dil::Token::Kind &k, raw_ostream &OS, 134 llvm::StringRef Options) { 135 OS << "'" << lldb_private::dil::Token::GetTokenName(k) << "'"; 136 } 137 }; 138 139 template <> struct format_provider<lldb_private::dil::Token> { 140 static void format(const lldb_private::dil::Token &t, raw_ostream &OS, 141 llvm::StringRef Options) { 142 lldb_private::dil::Token::Kind kind = t.GetKind(); 143 OS << "<'" << t.GetSpelling() << "' (" 144 << lldb_private::dil::Token::GetTokenName(kind) << ")>"; 145 } 146 }; 147 148 } // namespace llvm 149 150 #endif // LLDB_VALUEOBJECT_DILLEXER_H 151