Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/DILLexer.cpp
213766 views
//===-- DILLexer.cpp ------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6// This implements the recursive descent parser for the Data Inspection7// Language (DIL), and its helper functions, which will eventually underlie the8// 'frame variable' command. The language that this parser recognizes is9// described in lldb/docs/dil-expr-lang.ebnf10//11//===----------------------------------------------------------------------===//1213#include "lldb/ValueObject/DILLexer.h"14#include "lldb/Utility/Status.h"15#include "lldb/ValueObject/DILParser.h"16#include "llvm/ADT/StringSwitch.h"1718namespace lldb_private::dil {1920llvm::StringRef Token::GetTokenName(Kind kind) {21switch (kind) {22case Kind::amp:23return "amp";24case Kind::arrow:25return "arrow";26case Kind::coloncolon:27return "coloncolon";28case Kind::eof:29return "eof";30case Kind::identifier:31return "identifier";32case Kind::l_paren:33return "l_paren";34case Kind::l_square:35return "l_square";36case Kind::minus:37return "minus";38case Kind::numeric_constant:39return "numeric_constant";40case Kind::period:41return "period";42case Kind::r_paren:43return "r_paren";44case Kind::r_square:45return "r_square";46case Token::star:47return "star";48}49llvm_unreachable("Unknown token name");50}5152static bool IsLetter(char c) {53return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');54}5556static bool IsDigit(char c) { return '0' <= c && c <= '9'; }5758// A word starts with a letter, underscore, or dollar sign, followed by59// letters ('a'..'z','A'..'Z'), digits ('0'..'9'), and/or underscores.60static std::optional<llvm::StringRef> IsWord(llvm::StringRef expr,61llvm::StringRef &remainder) {62// Find the longest prefix consisting of letters, digits, underscors and63// '$'. If it doesn't start with a digit, then it's a word.64llvm::StringRef candidate = remainder.take_while(65[](char c) { return IsDigit(c) || IsLetter(c) || c == '_' || c == '$'; });66if (candidate.empty() || IsDigit(candidate[0]))67return std::nullopt;68remainder = remainder.drop_front(candidate.size());69return candidate;70}7172static bool IsNumberBodyChar(char ch) { return IsDigit(ch) || IsLetter(ch); }7374static std::optional<llvm::StringRef> IsNumber(llvm::StringRef expr,75llvm::StringRef &remainder) {76if (IsDigit(remainder[0])) {77llvm::StringRef number = remainder.take_while(IsNumberBodyChar);78remainder = remainder.drop_front(number.size());79return number;80}81return std::nullopt;82}8384llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr) {85std::vector<Token> tokens;86llvm::StringRef remainder = expr;87do {88if (llvm::Expected<Token> t = Lex(expr, remainder)) {89tokens.push_back(std::move(*t));90} else {91return t.takeError();92}93} while (tokens.back().GetKind() != Token::eof);94return DILLexer(expr, std::move(tokens));95}9697llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,98llvm::StringRef &remainder) {99// Skip over whitespace (spaces).100remainder = remainder.ltrim();101llvm::StringRef::iterator cur_pos = remainder.begin();102103// Check to see if we've reached the end of our input string.104if (remainder.empty())105return Token(Token::eof, "", (uint32_t)expr.size());106107uint32_t position = cur_pos - expr.begin();108std::optional<llvm::StringRef> maybe_number = IsNumber(expr, remainder);109if (maybe_number)110return Token(Token::numeric_constant, maybe_number->str(), position);111std::optional<llvm::StringRef> maybe_word = IsWord(expr, remainder);112if (maybe_word)113return Token(Token::identifier, maybe_word->str(), position);114115constexpr std::pair<Token::Kind, const char *> operators[] = {116{Token::amp, "&"}, {Token::arrow, "->"}, {Token::coloncolon, "::"},117{Token::l_paren, "("}, {Token::l_square, "["}, {Token::minus, "-"},118{Token::period, "."}, {Token::r_paren, ")"}, {Token::r_square, "]"},119{Token::star, "*"},120};121for (auto [kind, str] : operators) {122if (remainder.consume_front(str))123return Token(kind, str, position);124}125126// Unrecognized character(s) in string; unable to lex it.127return llvm::make_error<DILDiagnosticError>(expr, "unrecognized token",128position);129}130131} // namespace lldb_private::dil132133134