Completed
Push — 0.5.3 ( eba748...a7ccc1 )
by Felipe A.
01:14
created

StateMachine.__iter__()   A

Complexity

Conditions 4

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
dl 0
loc 17
rs 9.2
1
2
class StateMachine(object):
3
    '''
4
    Abstract simple character-driven state-machine with result transformations.
5
6
    Useful for implementig simple parsers.
7
    '''
8
    jumps = {}  # state machine jumps
9
    start = ''  # character which started current state
10
    current = ''  # initial and current state
11
    pending = ''  # buffer of current state data
12
13
    def transform(self, data, current, start, partial=False):
14
        method = getattr(self, 'transform_%s' % current, None)
15
        return method(data, current, start, partial=False) if method else data
16
17
    def look(self, value, current, start):
18
        offset = len(start)
19
        for mark, next in self.jumps[current].items():
20
            index = value.find(mark, offset)
21
            if -1 != index:
22
                yield index, mark, next
23
        yield len(value), '', None  # failing is also an option
24
25
    def finalize(self):
26
        if self.pending:
27
            yield self.transform(self.pending, self.current, self.start, True)
28
        self.pending = ''
29
        self.current = ''
30
31
    def __iter__(self):
32
        while True:
33
            index, mark, next = min(
34
                self.look(self.pending, self.current, self.start),
35
                key=lambda x: (x[0], -len(x[1]))
36
                )
37
            if next is None:
38
                break
39
            data = self.transform(
40
                self.pending[:index],
41
                self.current,
42
                self.start
43
                )
44
            self.start = mark
45
            self.current = next
46
            self.pending = self.pending[index:]
47
            yield data
48
49
50
class BlobTransform(StateMachine):
51
    jumps = {  # state machine jumps
52
        'escape': {
53
            '': 'literal',
54
            },
55
        'lit': {
56
            '\\': 'escape',
57
            }
58
        }
59