1 //===-- PostfixExpression.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 //  This file implements support for postfix expressions found in several symbol
10 //  file formats, and their conversion to DWARF.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "lldb/Symbol/PostfixExpression.h"
15 #include "llvm/ADT/StringExtras.h"
16 
17 using namespace lldb_private;
18 using namespace lldb_private::postfix;
19 
20 static llvm::Optional<BinaryOpNode::OpType>
21 GetBinaryOpType(llvm::StringRef token) {
22   if (token.size() != 1)
23     return llvm::None;
24   switch (token[0]) {
25   case '@':
26     return BinaryOpNode::Align;
27   case '-':
28     return BinaryOpNode::Minus;
29   case '+':
30     return BinaryOpNode::Plus;
31   }
32   return llvm::None;
33 }
34 
35 static llvm::Optional<UnaryOpNode::OpType>
36 GetUnaryOpType(llvm::StringRef token) {
37   if (token == "^")
38     return UnaryOpNode::Deref;
39   return llvm::None;
40 }
41 
42 Node *postfix::Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc) {
43   llvm::SmallVector<Node *, 4> stack;
44 
45   llvm::StringRef token;
46   while (std::tie(token, expr) = getToken(expr), !token.empty()) {
47     if (auto op_type = GetBinaryOpType(token)) {
48       // token is binary operator
49       if (stack.size() < 2)
50         return nullptr;
51 
52       Node *right = stack.pop_back_val();
53       Node *left = stack.pop_back_val();
54       stack.push_back(MakeNode<BinaryOpNode>(alloc, *op_type, *left, *right));
55       continue;
56     }
57 
58     if (auto op_type = GetUnaryOpType(token)) {
59       // token is unary operator
60       if (stack.empty())
61         return nullptr;
62 
63       Node *operand = stack.pop_back_val();
64       stack.push_back(MakeNode<UnaryOpNode>(alloc, *op_type, *operand));
65       continue;
66     }
67 
68     uint32_t value;
69     if (to_integer(token, value, 10)) {
70       // token is integer literal
71       stack.push_back(MakeNode<IntegerNode>(alloc, value));
72       continue;
73     }
74 
75     stack.push_back(MakeNode<SymbolNode>(alloc, token));
76   }
77 
78   if (stack.size() != 1)
79     return nullptr;
80 
81   return stack.back();
82 }
83