1 //===-- DILParser.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_DILPARSER_H 10 #define LLDB_VALUEOBJECT_DILPARSER_H 11 12 #include "lldb/Target/ExecutionContextScope.h" 13 #include "lldb/Utility/DiagnosticsRendering.h" 14 #include "lldb/Utility/Status.h" 15 #include "lldb/ValueObject/DILAST.h" 16 #include "lldb/ValueObject/DILLexer.h" 17 #include "llvm/Support/Error.h" 18 #include <memory> 19 #include <optional> 20 #include <string> 21 #include <system_error> 22 #include <tuple> 23 #include <vector> 24 25 namespace lldb_private::dil { 26 27 enum class ErrorCode : unsigned char { 28 kOk = 0, 29 kInvalidExpressionSyntax, 30 kUndeclaredIdentifier, 31 kUnknown, 32 }; 33 34 // The following is modeled on class OptionParseError. 35 class DILDiagnosticError 36 : public llvm::ErrorInfo<DILDiagnosticError, DiagnosticError> { 37 DiagnosticDetail m_detail; 38 39 public: 40 using llvm::ErrorInfo<DILDiagnosticError, DiagnosticError>::ErrorInfo; DILDiagnosticError(DiagnosticDetail detail)41 DILDiagnosticError(DiagnosticDetail detail) 42 : ErrorInfo(make_error_code(std::errc::invalid_argument)), 43 m_detail(std::move(detail)) {} 44 45 DILDiagnosticError(llvm::StringRef expr, const std::string &message, 46 uint32_t loc, uint16_t err_len = 1); 47 Clone()48 std::unique_ptr<CloneableError> Clone() const override { 49 return std::make_unique<DILDiagnosticError>(m_detail); 50 } 51 GetDetails()52 llvm::ArrayRef<DiagnosticDetail> GetDetails() const override { 53 return m_detail; 54 } 55 message()56 std::string message() const override { return m_detail.rendered; } 57 }; 58 59 /// Pure recursive descent parser for C++ like expressions. 60 /// EBNF grammar for the parser is described in lldb/docs/dil-expr-lang.ebnf 61 class DILParser { 62 public: 63 static llvm::Expected<ASTNodeUP> Parse(llvm::StringRef dil_input_expr, 64 DILLexer lexer, 65 std::shared_ptr<StackFrame> frame_sp, 66 lldb::DynamicValueType use_dynamic, 67 bool use_synthetic, bool fragile_ivar, 68 bool check_ptr_vs_member); 69 70 ~DILParser() = default; 71 UseSynthetic()72 bool UseSynthetic() { return m_use_synthetic; } 73 UseFragileIvar()74 bool UseFragileIvar() { return m_fragile_ivar; } 75 CheckPtrVsMember()76 bool CheckPtrVsMember() { return m_check_ptr_vs_member; } 77 UseDynamic()78 lldb::DynamicValueType UseDynamic() { return m_use_dynamic; } 79 80 private: 81 explicit DILParser(llvm::StringRef dil_input_expr, DILLexer lexer, 82 std::shared_ptr<StackFrame> frame_sp, 83 lldb::DynamicValueType use_dynamic, bool use_synthetic, 84 bool fragile_ivar, bool check_ptr_vs_member, 85 llvm::Error &error); 86 87 ASTNodeUP Run(); 88 89 ASTNodeUP ParseExpression(); 90 ASTNodeUP ParseUnaryExpression(); 91 ASTNodeUP ParsePostfixExpression(); 92 ASTNodeUP ParsePrimaryExpression(); 93 94 std::string ParseNestedNameSpecifier(); 95 96 std::string ParseIdExpression(); 97 std::string ParseUnqualifiedId(); 98 std::optional<int64_t> ParseIntegerConstant(); 99 100 void BailOut(const std::string &error, uint32_t loc, uint16_t err_len); 101 102 void Expect(Token::Kind kind); 103 TentativeParsingRollback(uint32_t saved_idx)104 void TentativeParsingRollback(uint32_t saved_idx) { 105 if (m_error) 106 llvm::consumeError(std::move(m_error)); 107 m_dil_lexer.ResetTokenIdx(saved_idx); 108 } 109 CurToken()110 Token CurToken() { return m_dil_lexer.GetCurrentToken(); } 111 112 // Parser doesn't own the evaluation context. The produced AST may depend on 113 // it (for example, for source locations), so it's expected that expression 114 // context will outlive the parser. 115 std::shared_ptr<StackFrame> m_ctx_scope; 116 117 llvm::StringRef m_input_expr; 118 119 DILLexer m_dil_lexer; 120 121 // Holds an error if it occures during parsing. 122 llvm::Error &m_error; 123 124 lldb::DynamicValueType m_use_dynamic; 125 bool m_use_synthetic; 126 bool m_fragile_ivar; 127 bool m_check_ptr_vs_member; 128 }; // class DILParser 129 130 } // namespace lldb_private::dil 131 132 #endif // LLDB_VALUEOBJECT_DILPARSER_H 133