1 //===-- PostfixExpressionTest.cpp -------------------------------*- 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 #include "lldb/Symbol/PostfixExpression.h"
10 #include "llvm/Support/FormatVariadic.h"
11 #include "llvm/Support/raw_ostream.h"
12 #include "gtest/gtest.h"
13 
14 using namespace lldb_private;
15 using namespace lldb_private::postfix;
16 
17 static std::string ToString(BinaryOpNode::OpType type) {
18   switch (type) {
19   case BinaryOpNode::Align:
20     return "@";
21   case BinaryOpNode::Minus:
22     return "-";
23   case BinaryOpNode::Plus:
24     return "+";
25   }
26   llvm_unreachable("Fully covered switch!");
27 }
28 
29 static std::string ToString(UnaryOpNode::OpType type) {
30   switch (type) {
31   case UnaryOpNode::Deref:
32     return "^";
33   }
34   llvm_unreachable("Fully covered switch!");
35 }
36 
37 struct ASTPrinter : public Visitor<std::string> {
38 protected:
39   std::string Visit(BinaryOpNode &binary, Node *&) override {
40     return llvm::formatv("{0}({1}, {2})", ToString(binary.GetOpType()),
41                          Dispatch(binary.Left()), Dispatch(binary.Right()));
42   }
43 
44   std::string Visit(IntegerNode &integer, Node *&) override {
45     return llvm::formatv("int({0})", integer.GetValue());
46   }
47 
48   std::string Visit(RegisterNode &reg, Node *&) override {
49     return llvm::formatv("reg({0})", reg.GetRegNum());
50   }
51 
52   std::string Visit(SymbolNode &symbol, Node *&) override {
53     return symbol.GetName();
54   }
55 
56   std::string Visit(UnaryOpNode &unary, Node *&) override {
57     return llvm::formatv("{0}({1})", ToString(unary.GetOpType()),
58                          Dispatch(unary.Operand()));
59   }
60 
61 public:
62   static std::string Print(Node *node) {
63     if (node)
64       return ASTPrinter().Dispatch(node);
65     return "nullptr";
66   }
67 };
68 
69 static std::string ParseAndStringify(llvm::StringRef expr) {
70   llvm::BumpPtrAllocator alloc;
71   return ASTPrinter::Print(Parse(expr, alloc));
72 }
73 
74 TEST(PostfixExpression, Parse) {
75   EXPECT_EQ("int(47)", ParseAndStringify("47"));
76   EXPECT_EQ("$foo", ParseAndStringify("$foo"));
77   EXPECT_EQ("+(int(1), int(2))", ParseAndStringify("1 2 +"));
78   EXPECT_EQ("-(int(1), int(2))", ParseAndStringify("1 2 -"));
79   EXPECT_EQ("@(int(1), int(2))", ParseAndStringify("1 2 @"));
80   EXPECT_EQ("+(int(1), +(int(2), int(3)))", ParseAndStringify("1 2 3 + +"));
81   EXPECT_EQ("+(+(int(1), int(2)), int(3))", ParseAndStringify("1 2 + 3 +"));
82   EXPECT_EQ("^(int(1))", ParseAndStringify("1 ^"));
83   EXPECT_EQ("^(^(int(1)))", ParseAndStringify("1 ^ ^"));
84   EXPECT_EQ("^(+(int(1), ^(int(2))))", ParseAndStringify("1 2 ^ + ^"));
85   EXPECT_EQ("-($foo, int(47))", ParseAndStringify("$foo 47 -"));
86 
87   EXPECT_EQ("nullptr", ParseAndStringify("+"));
88   EXPECT_EQ("nullptr", ParseAndStringify("^"));
89   EXPECT_EQ("nullptr", ParseAndStringify("1 +"));
90   EXPECT_EQ("nullptr", ParseAndStringify("1 2 ^"));
91   EXPECT_EQ("nullptr", ParseAndStringify("1 2 3 +"));
92   EXPECT_EQ("nullptr", ParseAndStringify("^ 1"));
93   EXPECT_EQ("nullptr", ParseAndStringify("+ 1 2"));
94   EXPECT_EQ("nullptr", ParseAndStringify("1 + 2"));
95   EXPECT_EQ("nullptr", ParseAndStringify("1 2"));
96   EXPECT_EQ("nullptr", ParseAndStringify(""));
97 }
98