MoinLight

Annotated moinformat/parsers/table.py

98:bf23f3f334c9
2018-07-28 Paul Boddie Tidied slightly, moving the general region end handler into the base class, also retaining the use of the same pattern name attribute for region parsing in the table parser (for clarity).
paul@38 1
#!/usr/bin/env python
paul@38 2
paul@38 3
"""
paul@38 4
Moin wiki table parser.
paul@38 5
paul@54 6
Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
paul@38 7
paul@38 8
This program is free software; you can redistribute it and/or modify it under
paul@38 9
the terms of the GNU General Public License as published by the Free Software
paul@38 10
Foundation; either version 3 of the License, or (at your option) any later
paul@38 11
version.
paul@38 12
paul@38 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@38 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@38 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@38 16
details.
paul@38 17
paul@38 18
You should have received a copy of the GNU General Public License along with
paul@38 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@38 20
"""
paul@38 21
paul@55 22
from moinformat.parsers.common import get_patterns, \
paul@55 23
                                      excl, expect, group
paul@42 24
from moinformat.parsers.moin import MoinParser
paul@83 25
from moinformat.tree.moin import Table, TableAttrs, TableCell, TableRow, Text
paul@83 26
from moinformat.tree.table import Continuation
paul@38 27
paul@55 28
join = "".join
paul@38 29
paul@38 30
# Parser functionality.
paul@38 31
paul@42 32
class TableParser(MoinParser):
paul@38 33
paul@38 34
    "A parser for improved table syntax."
paul@38 35
paul@38 36
    # Principal parser methods.
paul@38 37
paul@38 38
    def parse_region_content(self, items, region):
paul@38 39
paul@98 40
        """
paul@98 41
        Parse the data provided by 'items' to populate the given 'region'. For
paul@98 42
        table regions, normal region handling is wrapped by management of the
paul@98 43
        table structure.
paul@98 44
        """
paul@38 45
paul@38 46
        self.set_region(items, region)
paul@38 47
paul@38 48
        # Start to populate table rows.
paul@38 49
paul@38 50
        cell = TableCell([])
paul@38 51
        row = TableRow([cell])
paul@38 52
        table = Table([row])
paul@43 53
        self.append_node(self.region, table)
paul@38 54
paul@38 55
        while True:
paul@98 56
            self.parse_region_details(cell, self.region_pattern_names)
paul@38 57
paul@38 58
            # Detect the end of the table.
paul@38 59
paul@54 60
            pattern = self.matching_pattern()
paul@54 61
paul@54 62
            if pattern == "regionend":
paul@38 63
                break
paul@38 64
paul@54 65
            elif pattern == "columnsep":
paul@38 66
                cell = TableCell([])
paul@38 67
                row.append(cell)
paul@38 68
paul@54 69
            elif pattern == "rowsep":
paul@38 70
                row = TableRow([])
paul@38 71
                table.append(row)
paul@38 72
                cell = TableCell([])
paul@38 73
                row.append(cell)
paul@38 74
paul@38 75
    # Parser handler methods.
paul@38 76
paul@38 77
    def parse_continuation(self, cell):
paul@72 78
paul@72 79
        "Handle continuation padding."
paul@72 80
paul@72 81
        feature = self.match_group("feature")
paul@72 82
        cell.append(Continuation(feature))
paul@38 83
paul@38 84
paul@38 85
paul@38 86
    # Regular expressions.
paul@38 87
paul@38 88
    syntax = {}
paul@42 89
    syntax.update(MoinParser.syntax)
paul@38 90
    syntax.update({
paul@38 91
        # At start of line:
paul@55 92
paul@55 93
        "rowsep"        : join(("^==",                      # ==
paul@55 94
                                excl(r".*==\s*?$"),         # not-heading
paul@55 95
                                expect(r"\N*?"))),          # ws-excl-nl
paul@55 96
paul@72 97
        "continuation"  : group("feature",
paul@72 98
                          join(("^",
paul@55 99
                                group("indent", r"\N*"),    # ws... (optional)
paul@55 100
                                r"\.\.",                    # ..
paul@72 101
                                excl(r"\.")))),             # not-.
paul@38 102
paul@38 103
        # Within text:
paul@55 104
paul@55 105
        "columnsep"     : join((r"\|\|",                    # ||
paul@72 106
                                excl(r"\|"))),              # not-|
paul@38 107
        })
paul@38 108
paul@38 109
    patterns = get_patterns(syntax)
paul@38 110
paul@38 111
paul@38 112
paul@38 113
    # Pattern details.
paul@38 114
paul@98 115
    region_pattern_names = [
paul@55 116
        "columnsep", "continuation", "rowsep",
paul@73 117
        ] + MoinParser.region_without_table_pattern_names
paul@38 118
paul@38 119
paul@38 120
paul@38 121
    # Pattern handlers.
paul@38 122
paul@98 123
    end_region = MoinParser.end_region
paul@98 124
    parse_table_end = MoinParser.parse_region_end
paul@98 125
paul@38 126
    handlers = {}
paul@42 127
    handlers.update(MoinParser.handlers)
paul@38 128
    handlers.update({
paul@98 129
        "columnsep" : end_region,
paul@38 130
        "continuation" : parse_continuation,
paul@98 131
        "rowsep" : end_region,
paul@38 132
        "regionend" : parse_table_end,
paul@38 133
        })
paul@38 134
paul@40 135
parser = TableParser
paul@40 136
paul@38 137
# vim: tabstop=4 expandtab shiftwidth=4