| | |
| | |
| | |
| | |
| | |
| |
|
| | 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>" |
| |
|