1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cassert> 20 #include <iosfwd> 21 #include <stdexcept> 22 23 namespace apache { 24 namespace thrift { 25 namespace compiler { 26 27 class t_program; 28 29 /** 30 * class source_loc 31 * 32 * Source location information of a parsed element. 33 */ 34 class source_loc final { 35 public: 36 constexpr source_loc() noexcept = default; 37 constexpr source_loc(source_loc const&) noexcept = default; 38 39 /** 40 * Constructor for source_loc 41 * 42 * @param program - The program this location belongs to. 43 * @param line - The 1-based line number. 44 * @param column - The 1-based column number. 45 */ source_loc(const t_program & program,size_t line,size_t column)46 constexpr source_loc( 47 const t_program& program, size_t line, size_t column) noexcept 48 : program_(&program), line_(line), col_(column) {} 49 50 // If the location is specified/known. has_loc()51 constexpr bool has_loc() const noexcept { return program_ != nullptr; } 52 53 // The program associated with the location. 54 // 55 // UB if `has_loc()` returns false. program()56 constexpr const t_program& program() const { 57 assert(program_ != nullptr); 58 return *program_; 59 } 60 61 // The 1-based line number. 62 // 63 // Returns 0 if unknown/not specified. line()64 size_t line() const noexcept { return line_; } 65 // The 1-based column number. 66 // 67 // Returns 0 if unknown/not specified. column()68 size_t column() const noexcept { return col_; } 69 70 // The 0-based byte offset from the beginning of the program. 71 // 72 // Returns t_program::noffset if unknown/not specified. 73 size_t offset() const noexcept; 74 75 constexpr explicit operator bool() const noexcept { return has_loc(); } 76 constexpr source_loc& operator=(const source_loc& loc) noexcept = default; 77 78 // Ordered by program (nullptr first, then ordered by program.path(), then 79 // &program), then line, then column. compare(const source_loc & rhs)80 int compare(const source_loc& rhs) const noexcept { 81 return compare(*this, rhs); 82 } 83 84 private: 85 const t_program* program_ = nullptr; 86 size_t line_ = 0; // 1-based 87 size_t col_ = 0; // Code units (bytes), 1-based 88 89 friend bool operator==(const source_loc& lhs, const source_loc& rhs) { 90 return lhs.program_ == rhs.program_ && lhs.line_ == rhs.line_ && 91 lhs.col_ == rhs.col_; 92 } 93 friend bool operator!=(const source_loc& lhs, const source_loc& rhs) { 94 return !(lhs == rhs); 95 } 96 97 static int compare(const source_loc& lhs, const source_loc& rhs) noexcept; 98 99 friend bool operator<(const source_loc& lhs, const source_loc& rhs) noexcept { 100 return compare(lhs, rhs) < 0; 101 } 102 friend bool operator<=( 103 const source_loc& lhs, const source_loc& rhs) noexcept { 104 return compare(lhs, rhs) <= 0; 105 } 106 friend bool operator>(const source_loc& lhs, const source_loc& rhs) noexcept { 107 return compare(lhs, rhs) > 0; 108 } 109 friend bool operator>=( 110 const source_loc& lhs, const source_loc& rhs) noexcept { 111 return compare(lhs, rhs) >= 0; 112 } 113 114 friend std::ostream& operator<<(std::ostream& os, const source_loc& rhs); 115 }; 116 117 /** 118 * class source_range 119 * 120 * Source range information of a parsed element. 121 */ 122 class source_range final { 123 public: 124 constexpr source_range() noexcept = default; 125 constexpr source_range(source_range const&) noexcept = default; 126 source_range(const t_program & program,size_t begin_line,size_t begin_column,size_t end_line,size_t end_column)127 constexpr source_range( 128 const t_program& program, 129 size_t begin_line, 130 size_t begin_column, 131 size_t end_line, 132 size_t end_column) noexcept 133 : program_(&program), 134 begin_line_(begin_line), 135 begin_col_(begin_column), 136 end_line_(end_line), 137 end_col_(end_column) {} 138 139 // Throws std::invalid_argument if begin and end refer to different programs. 140 source_range(const source_loc& begin, const source_loc& end); 141 begin()142 constexpr source_loc begin() const noexcept { 143 return {*program_, begin_line_, begin_col_}; 144 } end()145 constexpr source_loc end() const noexcept { 146 return {*program_, end_line_, end_col_}; 147 } program()148 constexpr const t_program& program() const { 149 assert(program_ != nullptr); 150 return *program_; 151 } 152 153 // If the range is specified/known. has_range()154 constexpr bool has_range() const noexcept { return program_ != nullptr; } 155 156 constexpr explicit operator bool() const noexcept { return has_range(); } 157 constexpr source_range& operator=(const source_range& range) noexcept = 158 default; 159 160 // Ordered by `begin` than `end`. compare(const source_range & rhs)161 int compare(const source_range& rhs) const noexcept { 162 return compare(*this, rhs); 163 } 164 165 private: 166 const t_program* program_ = nullptr; 167 size_t begin_line_ = 0; // 1-based 168 size_t begin_col_ = 0; // Code units (bytes), 1-based 169 size_t end_line_ = 0; // 1-based 170 size_t end_col_ = 0; // Code units (bytes), 1-based 171 172 friend bool operator==(const source_range& lhs, const source_range& rhs) { 173 return lhs.program_ == rhs.program_ && lhs.begin_line_ == rhs.begin_line_ && 174 lhs.begin_col_ == rhs.begin_col_ && lhs.end_line_ == rhs.end_line_ && 175 lhs.end_col_ == rhs.end_col_; 176 } 177 friend bool operator!=( 178 const source_range& lhs, const source_range& rhs) noexcept { 179 return !(lhs == rhs); 180 } 181 182 static int compare(const source_range& lhs, const source_range& rhs) noexcept; 183 184 friend bool operator<( 185 const source_range& lhs, const source_range& rhs) noexcept { 186 return compare(lhs, rhs) < 0; 187 } 188 friend bool operator<=( 189 const source_range& lhs, const source_range& rhs) noexcept { 190 return compare(lhs, rhs) <= 0; 191 } 192 friend bool operator>( 193 const source_range& lhs, const source_range& rhs) noexcept { 194 return compare(lhs, rhs) > 0; 195 } 196 friend bool operator>=( 197 const source_range& lhs, const source_range& rhs) noexcept { 198 return compare(lhs, rhs) >= 0; 199 } 200 }; 201 202 } // namespace compiler 203 } // namespace thrift 204 } // namespace apache 205