MoinLight

Annotated moinformat/parsers/table.py

38:427c66773470
2017-12-12 Paul Boddie Reorganised the parsers and serialisers, introducing the missing table parser for the test program. Added a quiet option in the test program.
paul@38 1
#!/usr/bin/env python
paul@38 2
paul@38 3
"""
paul@38 4
Moin wiki table parser.
paul@38 5
paul@38 6
Copyright (C) 2017 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@38 22
from moinformat.parsing import get_patterns
paul@38 23
from moinformat.tree import Table, TableAttrs, TableCell, TableRow, Text
paul@38 24
from moinformat import Parser
paul@38 25
paul@38 26
paul@38 27
paul@38 28
# Parser functionality.
paul@38 29
paul@38 30
class TableParser(Parser):
paul@38 31
paul@38 32
    "A parser for improved table syntax."
paul@38 33
paul@38 34
    # Principal parser methods.
paul@38 35
paul@38 36
    def parse_region_content(self, items, region):
paul@38 37
paul@38 38
        "Parse the data provided by 'items' to populate the given 'region'."
paul@38 39
paul@38 40
        self.set_region(items, region)
paul@38 41
        self.parse_table_region()
paul@38 42
paul@38 43
    def parse_table_region(self):
paul@38 44
paul@38 45
        # Start to populate table rows.
paul@38 46
paul@38 47
        cell = TableCell([])
paul@38 48
        row = TableRow([cell])
paul@38 49
        table = Table([row])
paul@38 50
        self.region.append(table)
paul@38 51
paul@38 52
        while True:
paul@38 53
            self.parse_region_details(cell, self.table_region_pattern_names)
paul@38 54
paul@38 55
            # Detect the end of the table.
paul@38 56
paul@38 57
            if self.read_matching() == "regionend":
paul@38 58
                break
paul@38 59
paul@38 60
            if self.read_matching() == "columnsep":
paul@38 61
                cell = TableCell([])
paul@38 62
                row.append(cell)
paul@38 63
paul@38 64
            elif self.read_matching() == "rowsep":
paul@38 65
                row = TableRow([])
paul@38 66
                table.append(row)
paul@38 67
                cell = TableCell([])
paul@38 68
                row.append(cell)
paul@38 69
paul@38 70
    # Parser handler methods.
paul@38 71
paul@38 72
    def parse_continuation(self, cell):
paul@38 73
        pass
paul@38 74
paul@38 75
    def parse_table_end(self, cell):
paul@38 76
paul@38 77
        "Handle the end of a region within 'cell'."
paul@38 78
paul@38 79
        feature = self.read_match()
paul@38 80
        if self.region.have_end(feature):
paul@38 81
            raise StopIteration
paul@38 82
        else:
paul@38 83
            cell.append_inline(Text(feature))
paul@38 84
paul@38 85
    # Regular expressions.
paul@38 86
paul@38 87
    syntax = {}
paul@38 88
    syntax.update(Parser.syntax)
paul@38 89
    syntax.update({
paul@38 90
        # At start of line:
paul@38 91
        "rowsep"        : r"^==(?!.*==\s*?$)(?=\N*?)",  # == not-heading ws-excl-nl
paul@38 92
        "continuation"  : r"^(\N*)\.\.(?!\.)(?=\N)",    # .. ws-excl-nl or .. not-dot
paul@38 93
paul@38 94
        # Within text:
paul@38 95
        "columnsep"     : r"\|\|(?!\|)(?=\N)",          # || ws-excl-nl or || not-pipe
paul@38 96
        })
paul@38 97
paul@38 98
    patterns = get_patterns(syntax)
paul@38 99
paul@38 100
paul@38 101
paul@38 102
    # Pattern details.
paul@38 103
paul@38 104
    table_region_pattern_names = Parser.region_pattern_names + [
paul@38 105
        "columnsep", "continuation", "regionend", "rowsep",
paul@38 106
        ]
paul@38 107
paul@38 108
paul@38 109
paul@38 110
    # Pattern handlers.
paul@38 111
paul@38 112
    handlers = {}
paul@38 113
    handlers.update(Parser.handlers)
paul@38 114
    handlers.update({
paul@38 115
        "columnsep" : Parser.end_region,
paul@38 116
        "continuation" : parse_continuation,
paul@38 117
        "rowsep" : Parser.end_region,
paul@38 118
        "regionend" : parse_table_end,
paul@38 119
        })
paul@38 120
paul@38 121
# vim: tabstop=4 expandtab shiftwidth=4