1 /** 2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "sourceLocation.h" 17 18 #include "lexer/token/letters.h" 19 #include "parser/program/program.h" 20 21 #include <cstdint> 22 23 namespace ark::es2panda::lexer { AddCol(size_t offset)24void OffsetEntry::AddCol(size_t offset) 25 { 26 size_t diff = offset - offset_; 27 offset_ = offset; 28 29 if (ranges.empty()) { 30 ranges.emplace_back(Range {diff}); 31 return; 32 } 33 34 auto &range = ranges.back(); 35 36 if (diff == range.byteSize) { 37 range.cnt++; 38 } else { 39 ranges.emplace_back(Range {diff}); 40 } 41 } 42 LineIndex(const util::StringView & source)43LineIndex::LineIndex(const util::StringView &source) noexcept 44 { 45 auto iter = util::StringView::Iterator(source); 46 entries_.emplace_back(0); 47 48 while (true) { 49 switch (iter.Next()) { 50 case util::StringView::Iterator::INVALID_CP: { 51 return; 52 } 53 case LEX_CHAR_CR: { 54 if (iter.HasNext() && iter.Peek() == LEX_CHAR_LF) { 55 iter.Forward(1); 56 } 57 58 [[fallthrough]]; 59 } 60 case LEX_CHAR_LF: 61 case LEX_CHAR_PS: 62 case LEX_CHAR_LS: { 63 entries_.emplace_back(iter.Index()); 64 break; 65 } 66 default: { 67 entries_.back().AddCol(iter.Index()); 68 } 69 } 70 } 71 } 72 GetLocation(SourcePosition pos) const73SourceLocation LineIndex::GetLocation(SourcePosition pos) const noexcept 74 { 75 size_t line = pos.line; 76 77 size_t col = 0; 78 79 // It can occur during stdlib parsing where entries does not uploaded 80 if (line > entries_.size()) { 81 return SourceLocation(line + 1, col + 1, pos.Program()); 82 } 83 84 if (line == entries_.size()) { 85 --line; 86 } 87 88 const auto &entry = entries_[line]; 89 size_t diff = pos.index - entry.lineStart; 90 91 for (const auto &range : entry.ranges) { 92 if (diff < range.cnt) { 93 col += diff; 94 break; 95 } 96 97 diff -= range.cnt * range.byteSize; 98 col += range.cnt; 99 } 100 101 return SourceLocation(line + 1, col + 1, pos.Program()); 102 } 103 GetOffset(SourceLocation loc) const104size_t LineIndex::GetOffset(SourceLocation loc) const noexcept 105 { 106 ES2PANDA_ASSERT(loc.line != 0); 107 ES2PANDA_ASSERT(loc.col != 0); 108 size_t line = loc.line - 1; 109 size_t col = loc.col - 1; 110 111 if (line >= entries_.size()) { 112 return 0; 113 } 114 115 const auto &entry = entries_[line]; 116 size_t offset = entry.lineStart; 117 118 for (const auto &range : entry.ranges) { 119 if (col < range.cnt) { 120 offset += col * range.byteSize; 121 break; 122 } 123 124 col -= range.cnt; 125 offset += range.cnt * range.byteSize; 126 } 127 128 return offset; 129 } 130 ToLocation() const131SourceLocation SourcePosition::ToLocation() const 132 { 133 return lexer::LineIndex(Program()->SourceCode()).GetLocation(*this); 134 } 135 Program() const136const parser::Program *SourcePosition::Program() const 137 { 138 if (program_ != nullptr) { 139 ES2PANDA_ASSERT(!program_->IsDied()); 140 } 141 return program_; 142 } 143 Program() const144const parser::Program *SourceLocation::Program() const 145 { 146 if (program_ != nullptr) { 147 ES2PANDA_ASSERT(!program_->IsDied()); 148 } 149 return program_; 150 } 151 152 } // namespace ark::es2panda::lexer 153