aboutsummaryrefslogtreecommitdiff
path: root/mammoth/style_reader/html_path_reader.py
blob: 0f1331ba13a370c057c82ed9e40e3cc9d91a1108 (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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from parsimonious.grammar import Grammar

from .. import html_paths


def read_html_path(string):
    path_node = _grammar.parse(string)
    return read_html_path_node(path_node)


def read_html_path_node(path_node):
    elements = [
        _read_element_node(child)
        for child in _repeated_children_with_separator(path_node, has_whitespace=True)
    ]
    return html_paths.path(elements)


def _read_element_node(node):
    tag_names = _read_tag_names_node(node.children[0])
    class_names = _read_class_names_node(node.children[1])
    fresh = _read_fresh_node(node.children[2])
    return html_paths.element(tag_names, class_names=class_names, fresh=fresh)


def _read_tag_names_node(node):
    return [
        child.text
        for child in _repeated_children_with_separator(node, has_whitespace=False)
    ]


def _read_class_names_node(class_names_node):
    return [
        _read_class_name_node(node)
        for node in class_names_node.children
    ]


def _read_class_name_node(node):
    return node.children[1].text


def _read_fresh_node(node):
    return len(node.children) > 0


def _repeated_children_with_separator(node, has_whitespace):
    yield node.children[0]
    
    if has_whitespace:
        sequence_node_index = 2
    else:
        sequence_node_index = 1
    
    sequence_node = node.children[sequence_node_index]
    for child in sequence_node.children:
        yield child.children[sequence_node_index]


grammar_text = r"""

html_path = element whitespace* (">" whitespace* element)*

element = tag_names class_name* fresh?

tag_names = identifier ("|" identifier)*

class_name = "." identifier

fresh = ":fresh"

identifier = ~"[A-Z0-9]*"i

whitespace = ~"\s"*

"""

_grammar = Grammar(grammar_text)