class PositionFactory(object): """Tool used by a lexer to generate token's positions.""" class Position(object): """Represent a token's position in a file.""" __slots__ = ['__startpos', '__endpos'] def __init__(self, startpos, endpos): super(PositionFactory.Position, self).__init__() self.__startpos = startpos self.__endpos = endpos def __str__(self): """Return a string representation of a Position. Examples: 2:3 -> line 2, character 3 2:3-5 -> line 2, charactes 3 to 5 (not included) 3:4-5:2 -> from line 3 character 4 to line 5 character 2 """ #Short hands s = self.__startpos e = self.__endpos # Are we spread over multiple lines? if s[1] != e[1]: return "%d:%d-%d:%d" % (s[1], s[0], e[1], e[0]) else: # Are we spread over multiple columns? if s[0] == e[0]: return "%d:%d" % (e[1], e[0]) else: return "%d:%d-%d" %(e[1], s[0], e[0]) __slots__ = ['__startpos', '__endpos', '__curpos'] def __init__(self): super(PositionFactory, self).__init__() #Both position are in the (x, y) format self.__startpos = (1, 1) self.__endpos = (1, 1) self.__curpos = (1, 1) def mark(self): """Mark the current position as the begining of a token.""" self.__startpos = self.__curpos return def get(self): """Returns the token position. Automatically mark the end of the token as the begining of the next.""" self.__endpos = self.__curpos pos = self.Position(self.__startpos, self.__endpos) self.mark() return pos def colAdd(self, col): """Move the current column position 'col' columns further to the right.""" self.__curpos = (self.__curpos[0] + col, self.__curpos[1]) def lineAdd(self, line): """Move the current position 'line' lines down and reset the column position""" self.__curpos = (1, self.__curpos[1] + line) if __name__ == '__main__': tokens = [] pos = PositionFactory() print ' 1234567890' print '1: toto tata' print '2: titi' print '3: \'start' print '4: end\'' print ' 1234567890' pos.colAdd(len('toto')) tokens.append(Token('ID', pos.get(), 'toto')) pos.mark() pos.colAdd(len('tata')) tokens.append(Token('ID', pos.get(), 'tata')) pos.lineAdd(1) pos.mark() pos.colAdd(len('titi')) tokens.append(Token('ID', pos.get(), 'titi')) pos.lineAdd(1) pos.mark() pos.colAdd(len('\'start')) pos.lineAdd(1) pos.colAdd(len('end\'')) tokens.append(Token('ID', pos.get(), '\'start\nend\'')) del pos for i in tokens: print i