18#include "llvm/ADT/StringSwitch.h"
49 return "exclaimequal";
51 return "float_constant";
55 return "greaterequal";
57 return "greatergreater";
59 return "greatergreaterequal";
63 return "integer_constant";
79 return "lesslessequal";
89 return "percentequal";
121 llvm_unreachable(
"Unknown token name");
125 return (
'a' <= c && c <=
'z') || (
'A' <= c && c <=
'Z');
128static bool IsDigit(
char c) {
return '0' <= c && c <=
'9'; }
132static std::optional<llvm::StringRef>
IsWord(llvm::StringRef expr,
133 llvm::StringRef &remainder) {
136 llvm::StringRef candidate = remainder.take_while(
137 [](
char c) {
return IsDigit(c) ||
IsLetter(c) || c ==
'_' || c ==
'$'; });
138 if (candidate.empty() ||
IsDigit(candidate[0]))
140 remainder = remainder.drop_front(candidate.size());
148static std::optional<llvm::StringRef>
IsNumber(llvm::StringRef &remainder,
150 llvm::StringRef tail = remainder;
152 size_t dots = body.count(
'.');
153 if (dots > 1 || dots == body.size())
155 if (
IsDigit(body.front()) || (body[0] ==
'.' &&
IsDigit(body[1]))) {
157 tail = tail.drop_front(body.size());
158 bool isHex = body.contains_insensitive(
'x');
159 bool hasExp = !isHex && body.contains_insensitive(
'e');
160 bool hasHexExp = isHex && body.contains_insensitive(
'p');
161 if (hasExp || hasHexExp) {
163 if (body.ends_with_insensitive(
"e") || body.ends_with_insensitive(
"p"))
164 if (tail.consume_front(
"+") || tail.consume_front(
"-"))
167 size_t number_length = remainder.size() - tail.size();
168 llvm::StringRef number = remainder.take_front(number_length);
169 remainder = remainder.drop_front(number_length);
179 if (!token.
IsOneOf({Token::identifier, Token::period, Token::eof})) {
180 return llvm::make_error<DILDiagnosticError>(
181 expr, llvm::formatv(
"{0} is not allowed in DIL simple mode", token),
186 if (!token.
IsOneOf({Token::identifier, Token::integer_constant,
187 Token::period, Token::arrow, Token::star, Token::amp,
188 Token::l_square, Token::r_square, Token::eof})) {
189 return llvm::make_error<DILDiagnosticError>(
190 expr, llvm::formatv(
"{0} is not allowed in DIL legacy mode", token),
197 return llvm::Error::success();
202 std::vector<Token> tokens;
203 llvm::StringRef remainder = expr;
205 if (llvm::Expected<Token> t =
Lex(expr, remainder)) {
209 "[DILLexer::Create] DIL mode restriction:\n{0}",
210 llvm::toStringWithoutConsuming(
error));
213 tokens.push_back(std::move(token));
215 auto error = t.takeError();
217 "[DILLexer::Create] DIL lexer failed:\n{0}",
218 llvm::toStringWithoutConsuming(
error));
221 }
while (tokens.back().GetKind() !=
Token::eof);
222 return DILLexer(expr, std::move(tokens));
226 llvm::StringRef &remainder) {
228 remainder = remainder.ltrim();
229 llvm::StringRef::iterator cur_pos = remainder.begin();
232 if (remainder.empty())
235 uint32_t position = cur_pos - expr.begin();
236 bool isFloat =
false;
237 std::optional<llvm::StringRef> maybe_number =
IsNumber(remainder, isFloat);
240 return Token(kind, maybe_number->str(), position);
242 std::optional<llvm::StringRef> maybe_word =
IsWord(expr, remainder);
244 llvm::StringRef word = *maybe_word;
245 Token::Kind kind = llvm::StringSwitch<Token::Kind>(word)
249 return Token(kind, word.str(), position);
255 constexpr std::pair<Token::Kind, const char *> operators[] = {
299 for (
auto [kind, str] : operators) {
300 if (remainder.consume_front(str))
301 return Token(kind, str, position);
305 return llvm::make_error<DILDiagnosticError>(expr,
"unrecognized token",
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static llvm::Expected< DILLexer > Create(llvm::StringRef expr, lldb::DILMode mode=lldb::eDILModeFull)
Lexes all the tokens in expr and calls the private constructor with the lexed tokens.
DILLexer(llvm::StringRef dil_expr, std::vector< Token > lexed_tokens)
static llvm::Expected< Token > Lex(llvm::StringRef expr, llvm::StringRef &remainder)
Class defining the tokens generated by the DIL lexer and used by the DIL parser.
static llvm::StringRef GetTokenName(Kind kind)
uint32_t GetLocation() const
bool IsOneOf(llvm::ArrayRef< Kind > kinds) const
static std::optional< llvm::StringRef > IsWord(llvm::StringRef expr, llvm::StringRef &remainder)
static bool IsNumberBodyChar(char ch)
static llvm::Error IsNotAllowedByMode(llvm::StringRef expr, Token token, lldb::DILMode mode)
static bool IsLetter(char c)
static std::optional< llvm::StringRef > IsNumber(llvm::StringRef &remainder, bool &isFloat)
static bool IsDigit(char c)
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
DILMode
Data Inspection Language (DIL) evaluation modes.
@ eDILModeFull
Allowed: everything supported by DIL.
@ eDILModeLegacy
Allowed: identifiers, integers, operators: '.', '->', '*', '&', '[]'.
@ eDILModeSimple
Allowed: identifiers, operators: '.'.