xref: /freebsd/contrib/llvm-project/lldb/include/lldb/ValueObject/DILLexer.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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