| |
| |
| |
| |
| |
|
|
| from io import StringIO |
| from antlr4.Token import Token |
|
|
| |
| IntervalSet = None |
|
|
| class IntervalSet(object): |
| __slots__ = ('intervals', 'readonly') |
|
|
| def __init__(self): |
| self.intervals = None |
| self.readonly = False |
|
|
| def __iter__(self): |
| if self.intervals is not None: |
| for i in self.intervals: |
| for c in i: |
| yield c |
|
|
| def __getitem__(self, item): |
| i = 0 |
| for k in self: |
| if i==item: |
| return k |
| else: |
| i += 1 |
| return Token.INVALID_TYPE |
|
|
| def addOne(self, v:int): |
| self.addRange(range(v, v+1)) |
|
|
| def addRange(self, v:range): |
| if self.intervals is None: |
| self.intervals = list() |
| self.intervals.append(v) |
| else: |
| |
| k = 0 |
| for i in self.intervals: |
| |
| if v.stop<i.start: |
| self.intervals.insert(k, v) |
| return |
| |
| elif v.stop==i.start: |
| self.intervals[k] = range(v.start, i.stop) |
| return |
| |
| elif v.start<=i.stop: |
| self.intervals[k] = range(min(i.start,v.start), max(i.stop,v.stop)) |
| self.reduce(k) |
| return |
| k += 1 |
| |
| self.intervals.append(v) |
|
|
| def addSet(self, other:IntervalSet): |
| if other.intervals is not None: |
| for i in other.intervals: |
| self.addRange(i) |
| return self |
|
|
| def reduce(self, k:int): |
| |
| if k<len(self.intervals)-1: |
| l = self.intervals[k] |
| r = self.intervals[k+1] |
| |
| if l.stop >= r.stop: |
| self.intervals.pop(k+1) |
| self.reduce(k) |
| elif l.stop >= r.start: |
| self.intervals[k] = range(l.start, r.stop) |
| self.intervals.pop(k+1) |
|
|
| def complement(self, start, stop): |
| result = IntervalSet() |
| result.addRange(range(start,stop+1)) |
| for i in self.intervals: |
| result.removeRange(i) |
| return result |
|
|
| def __contains__(self, item): |
| if self.intervals is None: |
| return False |
| else: |
| return any(item in i for i in self.intervals) |
|
|
| def __len__(self): |
| return sum(len(i) for i in self.intervals) |
|
|
| def removeRange(self, v): |
| if v.start==v.stop-1: |
| self.removeOne(v.start) |
| elif self.intervals is not None: |
| k = 0 |
| for i in self.intervals: |
| |
| if v.stop<=i.start: |
| return |
| |
| elif v.start>i.start and v.stop<i.stop: |
| self.intervals[k] = range(i.start, v.start) |
| x = range(v.stop, i.stop) |
| self.intervals.insert(k, x) |
| return |
| |
| elif v.start<=i.start and v.stop>=i.stop: |
| self.intervals.pop(k) |
| k -= 1 |
| |
| elif v.start<i.stop: |
| self.intervals[k] = range(i.start, v.start) |
| |
| elif v.stop<i.stop: |
| self.intervals[k] = range(v.stop, i.stop) |
| k += 1 |
|
|
| def removeOne(self, v): |
| if self.intervals is not None: |
| k = 0 |
| for i in self.intervals: |
| |
| if v<i.start: |
| return |
| |
| elif v==i.start and v==i.stop-1: |
| self.intervals.pop(k) |
| return |
| |
| elif v==i.start: |
| self.intervals[k] = range(i.start+1, i.stop) |
| return |
| |
| elif v==i.stop-1: |
| self.intervals[k] = range(i.start, i.stop-1) |
| return |
| |
| elif v<i.stop-1: |
| x = range(i.start, v) |
| self.intervals[k] = range(v + 1, i.stop) |
| self.intervals.insert(k, x) |
| return |
| k += 1 |
|
|
|
|
| def toString(self, literalNames:list, symbolicNames:list): |
| if self.intervals is None: |
| return "{}" |
| with StringIO() as buf: |
| if len(self)>1: |
| buf.write("{") |
| first = True |
| for i in self.intervals: |
| for j in i: |
| if not first: |
| buf.write(", ") |
| buf.write(self.elementName(literalNames, symbolicNames, j)) |
| first = False |
| if len(self)>1: |
| buf.write("}") |
| return buf.getvalue() |
|
|
| def elementName(self, literalNames:list, symbolicNames:list, a:int): |
| if a==Token.EOF: |
| return "<EOF>" |
| elif a==Token.EPSILON: |
| return "<EPSILON>" |
| else: |
| if a<len(literalNames) and literalNames[a] != "<INVALID>": |
| return literalNames[a] |
| if a<len(symbolicNames): |
| return symbolicNames[a] |
| return "<UNKNOWN>" |
|
|