summaryrefslogtreecommitdiff
path: root/mammoth/styles/parser/document_matcher_parser.py
blob: e0eb4e13863494c5223d2cc08401d3c12cdfc313 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
from ... import documents, document_matchers
from .errors import LineParseError
from .tokeniser import TokenType
from .token_parser import try_parse_class_name, parse_string


def parse_document_matcher(tokens):
    if tokens.try_skip(TokenType.IDENTIFIER, "p"):
        style_id = try_parse_class_name(tokens)
        style_name = _parse_style_name(tokens)
        numbering = _parse_numbering(tokens)

        return document_matchers.paragraph(
            style_id=style_id,
            style_name=style_name,
            numbering=numbering,
        )

    elif tokens.try_skip(TokenType.IDENTIFIER, "r"):
        style_id = try_parse_class_name(tokens)
        style_name = _parse_style_name(tokens)

        return document_matchers.run(
            style_id=style_id,
            style_name=style_name,
        )

    elif tokens.try_skip(TokenType.IDENTIFIER, "table"):
        style_id = try_parse_class_name(tokens)
        style_name = _parse_style_name(tokens)

        return document_matchers.table(
            style_id=style_id,
            style_name=style_name,
        )

    elif tokens.try_skip(TokenType.IDENTIFIER, "b"):
        return document_matchers.bold

    elif tokens.try_skip(TokenType.IDENTIFIER, "i"):
        return document_matchers.italic

    elif tokens.try_skip(TokenType.IDENTIFIER, "u"):
        return document_matchers.underline

    elif tokens.try_skip(TokenType.IDENTIFIER, "strike"):
        return document_matchers.strikethrough

    elif tokens.try_skip(TokenType.IDENTIFIER, "all-caps"):
        return document_matchers.all_caps

    elif tokens.try_skip(TokenType.IDENTIFIER, "small-caps"):
        return document_matchers.small_caps

    elif tokens.try_skip(TokenType.IDENTIFIER, "highlight"):
        return _parse_highlight(tokens)

    elif tokens.try_skip(TokenType.IDENTIFIER, "comment-reference"):
        return document_matchers.comment_reference

    elif tokens.try_skip(TokenType.IDENTIFIER, "br"):
        return _parse_break(tokens)

    else:
        raise LineParseError("Unrecognised document element: {0}".format(tokens.next_value(TokenType.IDENTIFIER)))

def _parse_style_name(tokens):
    if tokens.try_skip(TokenType.SYMBOL, "["):
        tokens.skip(TokenType.IDENTIFIER, "style-name")
        string_matcher = _parse_string_matcher(tokens)
        tokens.skip(TokenType.SYMBOL, "]")
        return string_matcher
    else:
        return None


def _parse_string_matcher(tokens):
    if tokens.try_skip(TokenType.SYMBOL, "="):
        return document_matchers.equal_to(parse_string(tokens))
    elif tokens.try_skip(TokenType.SYMBOL, "^="):
        return document_matchers.starts_with(parse_string(tokens))
    else:
        raise LineParseError("Unrecognised string matcher: {0}".format(tokens.next_value()))

def _parse_numbering(tokens):
    if tokens.try_skip(TokenType.SYMBOL, ":"):
        is_ordered = _parse_list_type(tokens)
        tokens.skip(TokenType.SYMBOL, "(")
        level = int(tokens.next_value(TokenType.INTEGER)) - 1
        tokens.skip(TokenType.SYMBOL, ")")
        return documents.numbering_level(level, is_ordered=is_ordered)


def _parse_list_type(tokens):
    list_type = tokens.next_value(TokenType.IDENTIFIER)
    if list_type == "ordered-list":
        return True
    elif list_type == "unordered-list":
        return False
    else:
        raise LineParseError("Unrecognised list type: {0}".format(list_type))


def _parse_highlight(tokens):
    if tokens.try_skip(TokenType.SYMBOL, "["):
        tokens.skip(TokenType.IDENTIFIER, "color")
        tokens.skip(TokenType.SYMBOL, "=")
        color = parse_string(tokens)
        tokens.skip(TokenType.SYMBOL, "]");
    else:
        color = None

    return document_matchers.highlight(color=color)


def _parse_break(tokens):
    tokens.skip(TokenType.SYMBOL, "[")
    tokens.skip(TokenType.IDENTIFIER, "type")
    tokens.skip(TokenType.SYMBOL, "=")
    type_name = parse_string(tokens)
    tokens.skip(TokenType.SYMBOL, "]");

    if type_name == "line":
        return document_matchers.line_break
    elif type_name == "page":
        return document_matchers.page_break
    elif type_name == "column":
        return document_matchers.column_break
    else:
        raise LineParseError("Unrecognised break type: {0}".format(type_name))