diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf index 67328939ba420..70eda3bf40650 100644 --- a/lldb/docs/dil-expr-lang.ebnf +++ b/lldb/docs/dil-expr-lang.ebnf @@ -16,6 +16,7 @@ postfix_expression = primary_expression | postfix_expression "->" id_expression ; primary_expression = numeric_literal + | boolean_literal | id_expression | "(" expression ")" ; @@ -35,6 +36,8 @@ integer_literal = ? Integer constant: hexademical, decimal, octal, binary ? ; numeric_literal = ? Integer constant: hexademical, decimal, octal, binary ? | ? Floating constant ? ; +boolean_literal = "true" | "false" ; + register = "$" ? Register name ? ; nested_name_specifier = type_name "::" diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h index 1d10755c46e39..0f05d753f1b56 100644 --- a/lldb/include/lldb/ValueObject/DILAST.h +++ b/lldb/include/lldb/ValueObject/DILAST.h @@ -20,6 +20,7 @@ namespace lldb_private::dil { enum class NodeKind { eArraySubscriptNode, eBitExtractionNode, + eBooleanLiteralNode, eErrorNode, eFloatLiteralNode, eIdentifierNode, @@ -226,6 +227,23 @@ class FloatLiteralNode : public ASTNode { llvm::APFloat m_value; }; +class BooleanLiteralNode : public ASTNode { +public: + BooleanLiteralNode(uint32_t location, bool value) + : ASTNode(location, NodeKind::eBooleanLiteralNode), m_value(value) {} + + llvm::Expected Accept(Visitor *v) const override; + + bool GetValue() const & { return m_value; } + + static bool classof(const ASTNode *node) { + return node->GetKind() == NodeKind::eBooleanLiteralNode; + } + +private: + bool m_value; +}; + /// This class contains one Visit method for each specialized type of /// DIL AST node. The Visit methods are used to dispatch a DIL AST node to /// the correct function in the DIL expression evaluator for evaluating that @@ -247,6 +265,8 @@ class Visitor { Visit(const IntegerLiteralNode *node) = 0; virtual llvm::Expected Visit(const FloatLiteralNode *node) = 0; + virtual llvm::Expected + Visit(const BooleanLiteralNode *node) = 0; }; } // namespace lldb_private::dil diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h index 5a48c2c989f4d..eab3218ff828f 100644 --- a/lldb/include/lldb/ValueObject/DILEval.h +++ b/lldb/include/lldb/ValueObject/DILEval.h @@ -58,6 +58,8 @@ class Interpreter : Visitor { Visit(const IntegerLiteralNode *node) override; llvm::Expected Visit(const FloatLiteralNode *node) override; + llvm::Expected + Visit(const BooleanLiteralNode *node) override; llvm::Expected PickIntegerType(lldb::TypeSystemSP type_system, diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h index 4345e6ce7f26b..28b94a79c5902 100644 --- a/lldb/include/lldb/ValueObject/DILLexer.h +++ b/lldb/include/lldb/ValueObject/DILLexer.h @@ -31,6 +31,8 @@ class Token { float_constant, identifier, integer_constant, + kw_false, + kw_true, l_paren, l_square, minus, diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h index 90df109337dcf..d17ed66d9b3ee 100644 --- a/lldb/include/lldb/ValueObject/DILParser.h +++ b/lldb/include/lldb/ValueObject/DILParser.h @@ -99,11 +99,14 @@ class DILParser { ASTNodeUP ParseNumericLiteral(); ASTNodeUP ParseIntegerLiteral(); ASTNodeUP ParseFloatingPointLiteral(); + ASTNodeUP ParseBooleanLiteral(); void BailOut(const std::string &error, uint32_t loc, uint16_t err_len); void Expect(Token::Kind kind); + void ExpectOneOf(std::vector kinds_vec); + void TentativeParsingRollback(uint32_t saved_idx) { if (m_error) llvm::consumeError(std::move(m_error)); diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp index 70564663a62cd..7ed34db6e20df 100644 --- a/lldb/source/ValueObject/DILAST.cpp +++ b/lldb/source/ValueObject/DILAST.cpp @@ -46,4 +46,9 @@ llvm::Expected FloatLiteralNode::Accept(Visitor *v) const { return v->Visit(this); } +llvm::Expected +BooleanLiteralNode::Accept(Visitor *v) const { + return v->Visit(this); +} + } // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index c6cf41ee9e9ee..a9dbfad298d05 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -602,4 +602,10 @@ Interpreter::Visit(const FloatLiteralNode *node) { "result"); } +llvm::Expected +Interpreter::Visit(const BooleanLiteralNode *node) { + bool value = node->GetValue(); + return ValueObject::CreateValueObjectFromBool(m_target, value, "result"); +} + } // namespace lldb_private::dil diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp index 0b2288a9d9230..e0202a2fe24cc 100644 --- a/lldb/source/ValueObject/DILLexer.cpp +++ b/lldb/source/ValueObject/DILLexer.cpp @@ -34,6 +34,10 @@ llvm::StringRef Token::GetTokenName(Kind kind) { return "identifier"; case Kind::integer_constant: return "integer_constant"; + case Kind::kw_false: + return "false"; + case Kind::kw_true: + return "true"; case Kind::l_paren: return "l_paren"; case Kind::l_square: @@ -42,7 +46,6 @@ llvm::StringRef Token::GetTokenName(Kind kind) { return "minus"; case Kind::period: return "period"; - return "l_square"; case Kind::plus: return "plus"; case Kind::r_paren: @@ -137,8 +140,14 @@ llvm::Expected DILLexer::Lex(llvm::StringRef expr, return Token(kind, maybe_number->str(), position); } std::optional maybe_word = IsWord(expr, remainder); - if (maybe_word) - return Token(Token::identifier, maybe_word->str(), position); + if (maybe_word) { + llvm::StringRef word = *maybe_word; + Token::Kind kind = llvm::StringSwitch(word) + .Case("false", Token::kw_false) + .Case("true", Token::kw_true) + .Default(Token::identifier); + return Token(kind, word.str(), position); + } constexpr std::pair operators[] = { {Token::amp, "&"}, {Token::arrow, "->"}, {Token::coloncolon, "::"}, diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp index 8c4f7fdb25bea..566bcaf81094a 100644 --- a/lldb/source/ValueObject/DILParser.cpp +++ b/lldb/source/ValueObject/DILParser.cpp @@ -180,12 +180,15 @@ ASTNodeUP DILParser::ParsePostfixExpression() { // // primary_expression: // numeric_literal +// boolean_literal // id_expression // "(" expression ")" // ASTNodeUP DILParser::ParsePrimaryExpression() { if (CurToken().IsOneOf({Token::integer_constant, Token::float_constant})) return ParseNumericLiteral(); + if (CurToken().IsOneOf({Token::kw_true, Token::kw_false})) + return ParseBooleanLiteral(); if (CurToken().IsOneOf( {Token::coloncolon, Token::identifier, Token::l_paren})) { // Save the source location for the diagnostics message. @@ -336,6 +339,20 @@ std::string DILParser::ParseUnqualifiedId() { return identifier; } +// Parse an boolean_literal. +// +// boolean_literal: +// "true" +// "false" +// +ASTNodeUP DILParser::ParseBooleanLiteral() { + ExpectOneOf(std::vector{Token::kw_true, Token::kw_false}); + uint32_t loc = CurToken().GetLocation(); + bool literal_value = CurToken().Is(Token::kw_true); + m_dil_lexer.Advance(); + return std::make_unique(loc, literal_value); +} + void DILParser::BailOut(const std::string &error, uint32_t loc, uint16_t err_len) { if (m_error) @@ -444,4 +461,12 @@ void DILParser::Expect(Token::Kind kind) { } } +void DILParser::ExpectOneOf(std::vector kinds_vec) { + if (!CurToken().IsOneOf(kinds_vec)) { + BailOut(llvm::formatv("expected any of ({0}), got: {1}", + llvm::iterator_range(kinds_vec), CurToken()), + CurToken().GetLocation(), CurToken().GetSpelling().length()); + } +} + } // namespace lldb_private::dil diff --git a/lldb/test/API/commands/frame/var-dil/expr/Literals/TestFrameVarDILLiterals.py b/lldb/test/API/commands/frame/var-dil/expr/Literals/TestFrameVarDILLiterals.py index 431ec2829bc75..ca3357cd683a0 100644 --- a/lldb/test/API/commands/frame/var-dil/expr/Literals/TestFrameVarDILLiterals.py +++ b/lldb/test/API/commands/frame/var-dil/expr/Literals/TestFrameVarDILLiterals.py @@ -19,6 +19,10 @@ def test_literals(self): self.runCmd("settings set target.experimental.use-DIL true") + # Check boolean literals parsing + self.expect_var_path("true", value="true", type="bool") + self.expect_var_path("false", value="false", type="bool") + # Check number literals parsing self.expect_var_path("1.0", value="1", type="double") self.expect_var_path("1.0f", value="1", type="float")