Joos1W Compiler Framework
All Classes Functions Typedefs Pages
Location.h
1 #pragma once
2 
3 #include <utils/Assert.h>
4 
5 #include <iostream>
6 #include <sstream>
7 
8 #include "diagnostics/SourceManager.h"
9 
10 class SourceLocation;
11 class SourceRange;
12 
13 /* ===--------------------------------------------------------------------=== */
14 // SourceLocation
15 /* ===--------------------------------------------------------------------=== */
16 
17 /// @brief A specific location (line, column) in a source file.
19  friend class SourceRange;
20  SourceLocation() : file_{}, line_{-1}, column_{-1} {}
21 
22 public:
23  SourceLocation(SourceFile file, int line, int column)
24  : file_{file}, line_{line}, column_{column} {}
25  std::ostream& print(std::ostream& os) const {
27  os << ":" << line_ << ":" << column_;
28  return os;
29  }
30  std::string toString() const {
31  std::ostringstream os;
32  print(os);
33  return os.str();
34  }
35 
36  /// @brief Returns true if the SourceLocation was not default constructed.
37  bool isValid() const { return line_ != -1; }
38 
39  SourceFile file() const { return file_; }
40  int line() const { return line_; }
41  int column() const { return column_; }
42 
43 private:
44  SourceFile file_;
45  int line_;
46  int column_;
47 };
48 
49 /* ===--------------------------------------------------------------------=== */
50 // SourceRange
51 /* ===--------------------------------------------------------------------=== */
52 
53 /// @brief A range of locations in a source file.
54 class SourceRange {
55 public:
56  /// @brief Construct a new SourceRange with no associated file.
57  SourceRange() : begin_{}, end_{} {}
58  SourceRange(SourceFile file) : begin_{file, 0, 0}, end_{file, 0, 0} {}
59 
60  /// @brief Construct a new SourceRange with the given begin and end
61  /// locations.
63  : begin_{begin}, end_{end} {
64  assert(begin.file_ == end.file_ && "SourceRange spans multiple files");
65  }
66 
67  /// @brief Returns true if the SourceRange was not default constructed.
68  /// Checks if each SourceLocation is valid.
69  bool isValid() const { return begin_.isValid() && end_.isValid(); }
70 
71  std::ostream& print(std::ostream& os) const {
72  begin_.print(os);
73  os << " - " << end_.line_ << ":" << end_.column_;
74  return os;
75  }
76 
77  std::string toString() const {
78  std::ostringstream os;
79  print(os);
80  return os.str();
81  }
82 
83  SourceLocation range_start() const { return begin_; }
84  SourceLocation range_end() const { return end_; }
85 
86  static SourceRange merge(SourceRange const& a, SourceRange const& b) {
87  assert(a.begin_.file_ == b.begin_.file_ &&
88  "Tried to merge SourceRanges from different files");
89  auto file = a.begin_.file_;
90  if(!a.isValid()) return b;
91  if(!b.isValid()) return a;
92  return SourceRange{
93  // Grab the smallest line & col
94  SourceLocation{file,
95  std::min(a.begin_.line_, b.begin_.line_),
96  std::min(a.begin_.column_, b.begin_.column_)},
97  // Grab the largest line & col
98  SourceLocation{file,
99  std::max(a.end_.line_, b.end_.line_),
100  std::max(a.end_.column_, b.end_.column_)}};
101  }
102 
103 private:
104  SourceLocation begin_;
105  SourceLocation end_;
106 };