aboutsummaryrefslogtreecommitdiff
path: root/mammoth/styles/parser/tokeniser.py
blob: 2e8c2c24a3af9d75e5241928a1977a75856d9323 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import collections
import re


Token = collections.namedtuple("Token", ["character_index", "type", "value"])


def regex_tokeniser(rules):
    rules = [(token_type, _to_regex(regex)) for token_type, regex in rules]
    rules.append(("unknown", re.compile(".")))
    
    def tokenise(value):
        tokens = []
        index = 0
        while index < len(value):
            for token_type, regex in rules:
                match = regex.match(value, index)
                if match is not None:
                    tokens.append(Token(index, token_type, match.group(0)))
                    index = match.end()
                    break
            else:
                # Should be impossible
                raise Exception("Remaining: " + value[index:])

        tokens.append(Token(index, "end", ""))

        return tokens

    return tokenise
    

def _to_regex(value):
    if hasattr(value, "match"):
        return value
    else:
        return re.compile(value)


_string_prefix = r"'(?:\\.|[^'])*"
_identifier_character = r"(?:[a-zA-Z\-_]|\\.)"

tokenise = regex_tokeniser([
    ("identifier", _identifier_character + "(?:" + _identifier_character + "|[0-9])*"),
    ("symbol", r":|>|=>|\^=|=|\(|\)|\[|\]|\||!|\."),
    ("whitespace", r"\s+"),
    ("string", _string_prefix + "'"),
    ("unterminated string", _string_prefix),
    ("integer", "([0-9]+)"),
])