1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.Lex
 10 {
 11     public class Span
 12     {
 13         public Span() : pos(-1)len(-1)
 14         {
 15         }
 16         public Span(int pos_int len_) : pos(pos_)len(len_)
 17         {
 18         }
 19         public inline bool IsValid() const
 20         {
 21             return pos != -1;
 22         }
 23         public inline bool Contains(int pos_) const
 24         {
 25             return pos_ >= pos && pos_ < pos + len;
 26         }
 27         public inline void Union(const Span& that)
 28         {
 29             int end = that.pos + that.len;
 30             len = end - pos;
 31         }
 32         public int pos;
 33         public int len;
 34     }
 35 
 36     public bool operator==(const Span& leftconst Span& right)
 37     {
 38         return left.pos == right.pos && left.len == right.len;
 39     }
 40 
 41     public class LineColLen
 42     {
 43         public inline LineColLen() : line(0)col(0)len(0)
 44         {
 45         }
 46         public inline LineColLen(int line_int col_) : line(line_)col(col_)len(0)
 47         {
 48         }
 49         public inline LineColLen(int line_int col_int len_) : line(line_)col(col_)len(len_)
 50         {
 51         }
 52         public inline bool IsValid() const
 53         {
 54             return line != 0;
 55         }
 56         public int line;
 57         public int col;
 58         public int len;
 59     }
 60 
 61     public LineColLen SpanToLineColLen(const Span& spanconst List<int>& lineStarts)
 62     {
 63         if (!span.IsValid() || lineStarts.IsEmpty())
 64         {
 65             return LineColLen();
 66         }
 67         else
 68         {
 69             auto it = LowerBound(lineStarts.Begin()lineStarts.End()span.pos);
 70             int lineStart = 0;
 71             int line = 0;
 72             if (it != lineStarts.End())
 73             {
 74                 if (it != lineStarts.Begin() && *it > span.pos)
 75                 {
 76                     --it;
 77                 }
 78                 line = cast<int>(it - lineStarts.Begin());
 79                 lineStart = lineStarts[line];
 80             }
 81             else
 82             {
 83                 line = cast<int>(lineStarts.Count());
 84                 lineStart = lineStarts[line - 1];
 85             }
 86             int col = span.pos - lineStart + 1;
 87             int len = span.len;
 88             if (line == 0)
 89             {
 90                 ++line;
 91             }
 92             return LineColLen(linecollen);
 93         }
 94     }
 95 
 96     public int LineColLenToPos(const LineColLen& lineColLenconst List<int>& lineStarts)
 97     {
 98         if (!lineColLen.IsValid() || lineStarts.IsEmpty() || lineColLen.line >= lineStarts.Count())
 99         {
100             return -1;
101         }
102         int pos = lineStarts[lineColLen.line] + lineColLen.col - 1;
103         return pos;
104     }
105 
106     public class FullSpan
107     {
108         public FullSpan() : moduleId()fileIndex(-1)span() {}
109         public FullSpan(const Uuid& moduleId_int fileIndex_const Span& span_) : moduleId(moduleId_)fileIndex(fileIndex_)span(span_) {}
110         public Uuid moduleId;
111         public int fileIndex;
112         public Span span;
113     }
114 
115     public bool operator==(const FullSpan& leftconst FullSpan& right)
116     {
117         return left.moduleId == right.moduleId && left.fileIndex == right.fileIndex && left.span == right.span;
118     }
119