Joos1W Compiler Framework
All Classes Functions Typedefs Pages
ParseTree.h
1 #pragma once
2 
3 #include <array>
4 #include <iostream>
5 #include <memory_resource>
6 #include <string>
7 #include <type_traits>
8 
9 #include "diagnostics/Location.h"
10 #include "utils/BumpAllocator.h"
11 #include "utils/DotPrinter.h"
12 #include "utils/EnumMacros.h"
13 
14 class Joos1WLexer;
15 class Joos1WParser;
16 
17 namespace parsetree {
18 
19 using utils::DotPrinter;
20 
21 struct Node;
22 class Literal;
23 class Identifier;
24 class Operator;
25 class Modifier;
26 class BasicType;
27 
28 /// @brief The basic type-tagged node in the parse tree.
29 struct Node {
30  friend class ::Joos1WLexer;
31  friend class ::Joos1WParser;
32 
33 #define NODE_TYPE_LIST(F)
34  /* Leaf nodes */
35  F(Literal)
36  F(QualifiedIdentifier)
37  F(Identifier)
38  F(Operator)
39  F(BasicType)
40  F(Modifier)
41  F(ArrayType)
42  F(Type)
43  F(Poison)
44  /* Compilation Unit */
45  F(CompilationUnit)
46  F(PackageDeclaration)
47  F(ImportDeclarationList)
48  F(SingleTypeImportDeclaration)
49  F(TypeImportOnDemandDeclaration)
50  /* Modifiers */
51  F(ModifierList)
52  /* Classes */
53  F(ClassDeclaration)
54  F(FieldDeclaration)
55  F(ClassBodyDeclarationList)
56  F(ConstructorDeclaration)
57  F(SuperOpt)
58  /* Interfaces */
59  F(InterfaceDeclaration)
60  F(InterfaceMemberDeclarationList)
61  F(InterfaceTypeList)
62  /* Methods */
63  F(AbstractMethodDeclaration)
64  F(MethodHeader)
65  F(MethodDeclaration)
66  F(FormalParameterList)
67  F(FormalParameter)
68  /* Statements */
69  F(Statement)
70  F(Block)
71  F(BlockStatementList)
72  F(IfThenStatement)
73  F(WhileStatement)
74  F(ForStatement)
75  F(ReturnStatement)
76  F(StatementExpression)
77  /* Variable declarations and such */
78  F(VariableDeclarator)
79  F(LocalVariableDeclaration)
80  /* Expressions */
81  F(Expression)
82  F(ArgumentList)
83  F(FieldAccess)
84  F(ArrayAccess)
85  F(CastExpression)
86  F(MethodInvocation)
87  F(ArrayCreationExpression)
88  F(ClassInstanceCreationExpression)
89  F(Dims)
90 public:
91  /// @brief The enum for each node type
92  DECLARE_ENUM(Type, NODE_TYPE_LIST)
93 private:
94  DECLARE_STRING_TABLE(Type, type_strings, NODE_TYPE_LIST)
95 #undef NODE_TYPE_LIST
96 
97 protected:
98  /// @brief Protected constructor for leaf nodes
99  /// @param type The type of the leaf node
100  Node(SourceRange loc, Type type)
101  : loc{loc}, type{type}, args{nullptr}, num_args{0}, parent_{nullptr} {}
102 
103  /// @brief Protected constructor for non-leaf nodes
104  /// @tparam ...Args The child node types (should be Node*)
105  /// @param type The type of the node
106  /// @param ...args The child nodes
107  template <typename... Args>
108  Node(SourceRange loc, BumpAllocator& alloc, Type type, Args&&... args)
109  : loc{loc},
110  type{type},
111  args{static_cast<Node**>(alloc.allocate_bytes(
112  sizeof...(Args) * sizeof(Node*), alignof(Node*)))},
113  num_args{sizeof...(Args)} {
114  static_assert(sizeof...(Args) > 0, "Must have at least one child");
115  static_assert(std::conjunction_v<std::is_convertible<Args, Node*>...>,
116  "All arguments must be convertible to Node*");
117  std::array<Node*, sizeof...(Args)> tmp{std::forward<Args>(args)...};
118  for(size_t i = 0; i < sizeof...(Args); i++) {
119  this->args[i] = tmp[i];
120  if(this->args[i] != nullptr) this->args[i]->parent_ = this;
121  }
122  }
123 
124 public:
125  /// @brief Gets the number of children
126  size_t num_children() const { return num_args; }
127  /// @brief Gets the child at index i
128  Node* child(size_t i) const { return args[i]; }
129  /// @brief Gets the type of the node
130  Type get_node_type() const { return type; }
131  /// @brief Operator to turn Type into a string
132  std::string type_string() const { return Type_to_string(type, "Unknown Type"); }
133  /// @brief Operator to turn Type into a string
134  static std::string type_string(Type type) {
135  return Type_to_string(type, "Unknown Type");
136  }
137  /// @brief Check if the tree has been poisoned
138  bool is_poisoned() const {
139  if(type == Type::Poison)
140  return true;
141  else {
142  for(size_t i = 0; i < num_args; i++) {
143  if(args[i] == nullptr) continue;
144  if(args[i]->is_poisoned()) return true;
145  }
146  return false;
147  }
148  }
149  /// @brief Get the location of the node
150  SourceRange location() const { return loc; }
151  /// @brief Get the parent of the node
152  Node const* parent() const { return parent_; }
153  Node* parent() { return parent_; }
154  void mark() { marked = true; }
155  bool is_marked() const { return marked; }
156 
157 public:
158  /// @brief Virtual function to print the node
159  virtual std::ostream& print(std::ostream& os) const;
160  /// @brief Print the node as a dot file
161  std::ostream& printDot(std::ostream& os) const;
162 
163 protected:
164  /// @brief Custom function to print the DOT node
165  virtual void printDotNode(DotPrinter& dp) const;
166 
167 private:
168  /// @brief Recursively print the DOT graph
169  int printDotRecursive(DotPrinter& dp, const Node& node) const;
170 
171 private:
172  SourceRange loc;
173  Type type;
174  Node** args;
175  size_t num_args;
176  Node* parent_;
177  bool marked = false;
178 };
179 
180 // Output stream operator for a parse tree node
181 std::ostream& operator<<(std::ostream& os, Node const& n);
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 
185 /// @brief A lex node in the parse tree representing a literal value.
186 class Literal : public Node {
187  friend class ::Joos1WLexer;
188  friend class ::Joos1WParser;
189 
190 #define LITERAL_TYPE_LIST(F)
191  F(Integer)
192  F(Character)
193  F(String)
194  F(Boolean)
195  F(Null)
196 public:
197  /// @brief The enum for each literal type
198  DECLARE_ENUM(Type, LITERAL_TYPE_LIST)
199 private:
200  DECLARE_STRING_TABLE(Type, literal_strings, LITERAL_TYPE_LIST)
201 #undef LITERAL_TYPE_LIST
202 
203 private:
204  Literal(SourceRange loc, BumpAllocator const& alloc, Type type,
205  char const* value)
206  : Node{loc, Node::Type::Literal},
207  type{type},
208  isNegative_{false},
209  value{value, alloc} {}
210 
211 public:
212  // Override printing for this leaf node
213  std::ostream& print(std::ostream& os) const override;
214  // Set the value of the literal to negative
215  void setNegative() { isNegative_ = true; }
216  bool isNegative() const { return isNegative_; }
217  // Check if the literal is valid
218  bool isValid() const;
219  // Get the type of the literal
220  Type get_type() const { return type; }
221  // Get the string representation of the literal
222  std::string_view get_value() const { return value; }
223 
224 protected:
225  void printDotNode(DotPrinter& dp) const override;
226 
227 private:
228  Type type;
229  bool isNegative_;
230  std::pmr::string value;
231 };
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 
235 /// @brief A lex node in the parse tree representing an identifier.
236 class Identifier : public Node {
237  friend class ::Joos1WLexer;
238  friend class ::Joos1WParser;
239 
240 private:
241  Identifier(SourceRange loc, BumpAllocator const& alloc, char const* name)
242  : Node{loc, Node::Type::Identifier}, name{name, alloc} {}
243 
244 public:
245  // Get the name of the identifier
246  std::string_view get_name() const { return name; }
247  // Override printing for this leaf node
248  std::ostream& print(std::ostream& os) const override;
249 
250 protected:
251  void printDotNode(DotPrinter& dp) const override;
252 
253 private:
254  std::pmr::string name;
255 };
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 
259 /// @brief A lex node in the parse tree representing an operator.
260 class Operator : public Node {
261  friend class ::Joos1WLexer;
262  friend class ::Joos1WParser;
263 
264 public:
265  enum class Type {
266  Assign,
267  GreaterThan,
268  LessThan,
269  Not,
270  Equal,
271  LessThanOrEqual,
272  GreaterThanOrEqual,
273  NotEqual,
274  And,
275  Or,
276  BitwiseAnd,
277  BitwiseOr,
278  BitwiseXor,
279  BitwiseNot,
280  Add,
281  Subtract,
282  Multiply,
283  Divide,
284  Modulo,
285  Plus,
286  Minus,
287  InstanceOf
288  };
289 
290 private:
291  Operator(SourceRange loc, Type type)
292  : Node{loc, Node::Type::Operator}, type{type} {}
293 
294 public:
295  // Get the type of the operator
296  std::ostream& print(std::ostream& os) const override {
297  return os << to_string();
298  }
299  // Get the string representation of the operator
300  std::string to_string() const;
301 
302  Type get_type() const { return type; }
303 
304 protected:
305  void printDotNode(DotPrinter& dp) const override;
306 
307 private:
308  Type type;
309 };
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 
313 /// @brief A lex node in the parse tree representing a modifier.
314 class Modifier : public Node {
315  friend class ::Joos1WLexer;
316  friend class ::Joos1WParser;
317 
318 #define MODIFIER_TYPE_LIST(F)
319  F(Public)
320  F(Protected)
321  F(Static)
322  F(Abstract)
323  F(Final)
324  F(Native)
325 public:
326  /// @brief The enum for each modifier type
327  DECLARE_ENUM(Type, MODIFIER_TYPE_LIST)
328 private:
329  DECLARE_STRING_TABLE(Type, modifier_strings, MODIFIER_TYPE_LIST)
330 #undef MODIFIER_TYPE_LIST
331 
332 private:
333  Modifier(SourceRange loc, Type type)
334  : Node{loc, Node::Type::Modifier}, modty{type} {}
335 
336 public:
337  // Get the type of the modifier
338  Type get_type() const { return modty; }
339  // Print the string representation of the modifier
340  std::ostream& print(std::ostream& os) const override;
341 
342 protected:
343  void printDotNode(DotPrinter& dp) const override;
344 
345 private:
346  Type modty;
347 };
348 
349 ////////////////////////////////////////////////////////////////////////////////
350 
351 /// @brief A lex node in the parse tree representing a basic type.
352 class BasicType : public Node {
353  friend class ::Joos1WLexer;
354  friend class ::Joos1WParser;
355 
356 #define BASIC_TYPE_LIST(F)
357  F(Byte)
358  F(Short)
359  F(Int)
360  F(Char)
361  F(Boolean)
362 public:
363  /// @brief The enum for each basic type
364  DECLARE_ENUM(Type, BASIC_TYPE_LIST)
365 private:
366  DECLARE_STRING_TABLE(Type, basic_type_strings, BASIC_TYPE_LIST)
367 #undef BASIC_TYPE_LIST
368 
369 private:
370  BasicType(SourceRange loc, Type type)
371  : Node{loc, Node::Type::BasicType}, type{type} {}
372 
373 public:
374  // Get the type of the basic type
375  Type get_type() const { return type; }
376  // Print the string representation of the basic type
377  std::ostream& print(std::ostream& os) const override;
378 
379 protected:
380  void printDotNode(DotPrinter& dp) const override;
381 
382 private:
383  Type type;
384 };
385 
386 } // namespace parsetree