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