1 /** 2 * Copyright (c) 2021-2022 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 20 namespace panda::es2panda::lexer { 21 AddCol(size_t offset)22void OffsetEntry::AddCol(size_t offset) 23 { 24 size_t diff = offset - offset_; 25 offset_ = offset; 26 27 if (ranges.empty()) { 28 ranges.emplace_back(Range {diff}); 29 return; 30 } 31 32 auto &range = ranges.back(); 33 34 if (diff == range.byteSize) { 35 range.cnt++; 36 } else { 37 ranges.emplace_back(Range {diff}); 38 } 39 } 40 LineIndex(const util::StringView & source)41LineIndex::LineIndex(const util::StringView &source) noexcept 42 { 43 auto iter = util::StringView::Iterator(source); 44 entrys_.emplace_back(0); 45 46 bool nextEntry = false; 47 while (true) { 48 if (!iter.HasNext()) { 49 if (!nextEntry) { 50 // Add the last entry if the ending character is not LEX_CHAR_LF / LEX_CHAR_PS / LEX_CHAR_LS 51 entrys_.emplace_back(iter.Index()); 52 } 53 return; 54 } 55 56 switch (iter.Next()) { 57 case LEX_CHAR_CR: { 58 if (iter.HasNext() && iter.Peek() == LEX_CHAR_LF) { 59 iter.Forward(1); 60 } 61 62 [[fallthrough]]; 63 } 64 case LEX_CHAR_LF: 65 case LEX_CHAR_PS: 66 case LEX_CHAR_LS: { 67 entrys_.emplace_back(iter.Index()); 68 nextEntry = true; 69 break; 70 } 71 default: { 72 entrys_.back().AddCol(iter.Index()); 73 nextEntry = false; 74 } 75 } 76 } 77 } 78 GetLocation(SourcePosition pos)79SourceLocation LineIndex::GetLocation(SourcePosition pos) noexcept 80 { 81 size_t line = pos.line; 82 83 size_t col = 0; 84 ASSERT(pos.line < entrys_.size()); 85 const auto &entry = entrys_[pos.line]; 86 size_t diff = pos.index - entry.lineStart; 87 88 for (const auto &range : entry.ranges) { 89 if (diff < (range.cnt * range.byteSize)) { 90 col += (diff / range.byteSize) ; 91 break; 92 } 93 94 diff -= range.cnt * range.byteSize; 95 col += range.cnt; 96 } 97 98 return SourceLocation(line + 1, col + 1); 99 } 100 101 } // namespace panda::es2panda::lexer 102