Joos1W Compiler Framework
All Classes Functions Typedefs Pages
ParseTree.cc
1 #include "parsetree/ParseTree.h"
2 
3 #include <algorithm>
4 #include <iostream>
5 #include <string>
6 
7 #include "utils/DotPrinter.h"
8 
9 namespace parsetree {
10 
11 bool Literal::isValid() const {
12  if(type != Type::Integer) return true;
13  errno = 0;
14  char* endptr{};
15  const long long int x = std::strtol(value.c_str(), &endptr, 10);
16  const long long int INT_MAX = 2147483647ULL;
17  if(errno == ERANGE || *endptr != '\0') return false;
18  if(x > INT_MAX && !isNegative_) return false;
19  if(x > INT_MAX + 1 && isNegative_) return false;
20  return true;
21 }
22 
23 // Leaf node printers //////////////////////////////////////////////////////////
24 
25 std::string Operator::to_string() const {
26  using T = Operator::Type;
27  switch(type) {
28  case T::Assign:
29  return "=";
30  case T::GreaterThan:
31  return ">";
32  case T::LessThan:
33  return "<";
34  case T::Not:
35  return "!";
36  case T::Equal:
37  return "==";
38  case T::LessThanOrEqual:
39  return "<=";
40  case T::GreaterThanOrEqual:
41  return ">=";
42  case T::NotEqual:
43  return "!=";
44  case T::And:
45  return "&&";
46  case T::Or:
47  return "||";
48  case T::BitwiseAnd:
49  return "&";
50  case T::BitwiseOr:
51  return "|";
52  case T::BitwiseXor:
53  return "^";
54  case T::BitwiseNot:
55  return "~";
56  case T::Add:
57  return "+";
58  case T::Subtract:
59  return "-";
60  case T::Multiply:
61  return "*";
62  case T::Divide:
63  return "/";
64  case T::Modulo:
65  return "%";
66  case T::Plus:
67  return "+";
68  case T::Minus:
69  return "-";
70  case T::InstanceOf:
71  return "instanceof";
72  }
73  return "";
74 }
75 
76 std::ostream& Identifier::print(std::ostream& os) const {
77  os << "(Id " << name << ")";
78  return os;
79 }
80 
81 std::ostream& Literal::print(std::ostream& os) const {
82  std::string formattedValue{value};
83  std::replace(formattedValue.begin(), formattedValue.end(), '\"', ' ');
84  os << "(Literal " << Type_to_string(type, "??") << " " << formattedValue << ")";
85  return os;
86 }
87 
88 std::ostream& Modifier::print(std::ostream& os) const {
89  os << "(Modifier " << Type_to_string(modty, "??") << ")";
90  return os;
91 }
92 
93 std::ostream& BasicType::print(std::ostream& os) const {
94  os << "(BasicType " << Type_to_string(type, "??") << ")";
95  return os;
96 }
97 
98 void Identifier::printDotNode(DotPrinter& dp) const {
99  dp.printTableDoubleRow("Id", name);
100 }
101 
102 void Literal::printDotNode(DotPrinter& dp) const {
103  dp.printTableDoubleRow("Literal", value);
104 }
105 
106 void Modifier::printDotNode(DotPrinter& dp) const {
107  dp.printTableDoubleRow("Modifier", Type_to_string(modty, "??"));
108 }
109 
110 void BasicType::printDotNode(DotPrinter& dp) const {
111  dp.printTableDoubleRow("BasicType", Type_to_string(type, "??"));
112 }
113 
114 void Operator::printDotNode(DotPrinter& dp) const {
115  dp.printTableDoubleRow("Op", to_string());
116 }
117 
118 // Node printers ///////////////////////////////////////////////////////////////
119 
120 std::ostream& Node::print(std::ostream& os) const {
121  os << "(";
122  os << Type_to_string(type, "Unknown");
123  for(size_t i = 0; i < num_args; ++i) {
124  os << " ";
125  if(args[i] == nullptr) {
126  os << "ε";
127  } else {
128  args[i]->print(os);
129  }
130  }
131  os << ")";
132  return os;
133 }
134 
135 void Node::printDotNode(DotPrinter& dp) const {
136  dp.printTableSingleRow(Type_to_string(this->type, "Unknown"));
137  dp.printTableSingleRow(this->loc.toString());
138 }
139 
140 int Node::printDotRecursive(DotPrinter& dp, const Node& node) const {
141  const int id = dp.id();
142  // Print the label first
143  if(node.is_marked()) {
144  // clang-format off
145  dp.startTLabel(id, {
146  "color", "red",
147  }, "5");
148  // clang-format on
149  } else if(node.get_node_type() == Node::Type::Poison) {
150  // clang-format off
151  dp.startTLabel(id, {
152  "style", "filled",
153  "fillcolor", "red",
154  "fontcolor", "white"
155  }, "5");
156  // clang-format on
157  } else if(node.num_children() == 0) {
158  // clang-format off
159  dp.startTLabel(id, {
160  "style", "filled",
161  "fillcolor", "lightblue"
162  }, "5");
163  // clang-format on
164  } else {
165  dp.startTLabel(id, {}, "5");
166  }
167  node.printDotNode(dp);
168  dp.endTLabel();
169 
170  for(size_t i = 0; i < node.num_children(); i++) {
171  const Node* child = node.child(i);
172  int child_id = 0;
173  if(child != nullptr) {
174  child_id = printDotRecursive(dp, *child);
175  } else {
176  child_id = dp.id();
177  // clang-format off
178  dp.printLabel(child_id, "ε", {
179  "shape", "rect",
180  "style", "filled",
181  "fillcolor", "lightgrey",
182  "width", "0.25",
183  "height", "0.25",
184  "fontsize", "20"
185  });
186  // clang-format on
187  }
188  dp.printConnection(id, child_id);
189  }
190  return id;
191 }
192 
193 std::ostream& Node::printDot(std::ostream& os) const {
194  DotPrinter dp{os, "35"};
195  dp.startGraph();
196  printDotRecursive(dp, *this);
197  dp.endGraph();
198  return os;
199 }
200 
201 std::ostream& operator<<(std::ostream& os, Node const& n) { return n.print(os); }
202 
203 } // namespace parsetree