annotate 3rdparty/maddy/tableparser.h @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
rev   line source
ferencd@0 1 /*
ferencd@0 2 * This project is licensed under the MIT license. For more information see the
ferencd@0 3 * LICENSE file.
ferencd@0 4 */
ferencd@0 5 #pragma once
ferencd@0 6
ferencd@0 7 // -----------------------------------------------------------------------------
ferencd@0 8
ferencd@0 9 #include <functional>
ferencd@0 10 #include <string>
ferencd@0 11 #include <regex>
ferencd@0 12
ferencd@0 13 #include "maddy/blockparser.h"
ferencd@0 14
ferencd@0 15 // -----------------------------------------------------------------------------
ferencd@0 16
ferencd@0 17 namespace maddy {
ferencd@0 18
ferencd@0 19 // -----------------------------------------------------------------------------
ferencd@0 20
ferencd@0 21 /**
ferencd@0 22 * TableParser
ferencd@0 23 *
ferencd@0 24 * For more information, see the docs folder.
ferencd@0 25 *
ferencd@0 26 * @class
ferencd@0 27 */
ferencd@0 28 class TableParser : public BlockParser
ferencd@0 29 {
ferencd@0 30 public:
ferencd@0 31 /**
ferencd@0 32 * ctor
ferencd@0 33 *
ferencd@0 34 * @method
ferencd@0 35 * @param {std::function<void(std::string&)>} parseLineCallback
ferencd@0 36 * @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
ferencd@0 37 */
ferencd@0 38 TableParser(
ferencd@0 39 std::function<void(std::string&)> parseLineCallback,
ferencd@0 40 std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
ferencd@0 41 )
ferencd@0 42 : BlockParser(parseLineCallback, getBlockParserForLineCallback)
ferencd@0 43 , isStarted(false)
ferencd@0 44 , isFinished(false)
ferencd@0 45 , currentBlock(0)
ferencd@0 46 , currentRow(0)
ferencd@0 47 {}
ferencd@0 48
ferencd@0 49 /**
ferencd@0 50 * IsStartingLine
ferencd@0 51 *
ferencd@0 52 * If the line has exact `|table>`, then it is starting the table.
ferencd@0 53 *
ferencd@0 54 * @method
ferencd@0 55 * @param {const std::string&} line
ferencd@0 56 * @return {bool}
ferencd@0 57 */
ferencd@0 58 static bool
ferencd@0 59 IsStartingLine(const std::string& line)
ferencd@0 60 {
ferencd@0 61 static std::string matchString("|table>");
ferencd@0 62 return line == matchString;
ferencd@0 63 }
ferencd@0 64
ferencd@0 65 /**
ferencd@0 66 * AddLine
ferencd@0 67 *
ferencd@0 68 * Adding a line which has to be parsed.
ferencd@0 69 *
ferencd@0 70 * @method
ferencd@0 71 * @param {std::string&} line
ferencd@0 72 * @return {void}
ferencd@0 73 */
ferencd@0 74 void
ferencd@0 75 AddLine(std::string& line) override
ferencd@0 76 {
ferencd@0 77 if (!this->isStarted && line == "|table>")
ferencd@0 78 {
ferencd@0 79 this->isStarted = true;
ferencd@0 80 return;
ferencd@0 81 }
ferencd@0 82
ferencd@0 83 if (this->isStarted)
ferencd@0 84 {
ferencd@0 85 if (line == "- | - | -")
ferencd@0 86 {
ferencd@0 87 ++this->currentBlock;
ferencd@0 88 this->currentRow = 0;
ferencd@0 89 return;
ferencd@0 90 }
ferencd@0 91
ferencd@0 92 if (line == "|<table")
ferencd@0 93 {
ferencd@0 94 static std::string emptyLine = "";
ferencd@0 95 this->parseBlock(emptyLine);
ferencd@0 96 this->isFinished = true;
ferencd@0 97 return;
ferencd@0 98 }
ferencd@0 99
ferencd@0 100 if (this->table.size() < this->currentBlock + 1)
ferencd@0 101 {
ferencd@0 102 this->table.push_back(std::vector<std::vector<std::string>>());
ferencd@0 103 }
ferencd@0 104 this->table[this->currentBlock].push_back(std::vector<std::string>());
ferencd@0 105
ferencd@0 106 std::string segment;
ferencd@0 107 std::stringstream streamToSplit(line);
ferencd@0 108
ferencd@0 109 while (std::getline(streamToSplit, segment, '|'))
ferencd@0 110 {
ferencd@0 111 this->parseLine(segment);
ferencd@0 112 this->table[this->currentBlock][this->currentRow].push_back(segment);
ferencd@0 113 }
ferencd@0 114
ferencd@0 115 ++this->currentRow;
ferencd@0 116 }
ferencd@0 117 }
ferencd@0 118
ferencd@0 119 /**
ferencd@0 120 * IsFinished
ferencd@0 121 *
ferencd@0 122 * A table ends with `|<table`.
ferencd@0 123 *
ferencd@0 124 * @method
ferencd@0 125 * @return {bool}
ferencd@0 126 */
ferencd@0 127 bool
ferencd@0 128 IsFinished() const override
ferencd@0 129 {
ferencd@0 130 return this->isFinished;
ferencd@0 131 }
ferencd@0 132
ferencd@0 133 protected:
ferencd@0 134 bool
ferencd@0 135 isInlineBlockAllowed() const override
ferencd@0 136 {
ferencd@0 137 return false;
ferencd@0 138 }
ferencd@0 139
ferencd@0 140 bool
ferencd@0 141 isLineParserAllowed() const override
ferencd@0 142 {
ferencd@0 143 return true;
ferencd@0 144 }
ferencd@0 145
ferencd@0 146 void
ferencd@0 147 parseBlock(std::string&) override
ferencd@0 148 {
ferencd@0 149 result << "<table>";
ferencd@0 150
ferencd@0 151 bool hasHeader = false;
ferencd@0 152 bool hasFooter = false;
ferencd@0 153 bool isFirstBlock = true;
ferencd@0 154 uint32_t currentBlockNumber = 0;
ferencd@0 155
ferencd@0 156 if (this->table.size() > 1)
ferencd@0 157 {
ferencd@0 158 hasHeader = true;
ferencd@0 159 }
ferencd@0 160
ferencd@0 161 if (this->table.size() >= 3)
ferencd@0 162 {
ferencd@0 163 hasFooter = true;
ferencd@0 164 }
ferencd@0 165
ferencd@0 166 for (const std::vector<std::vector<std::string>>& block : this->table)
ferencd@0 167 {
ferencd@0 168 bool isInHeader = false;
ferencd@0 169 bool isInFooter = false;
ferencd@0 170 ++currentBlockNumber;
ferencd@0 171
ferencd@0 172 if (hasHeader && isFirstBlock)
ferencd@0 173 {
ferencd@0 174 result << "<thead>";
ferencd@0 175 isInHeader = true;
ferencd@0 176 }
ferencd@0 177 else if (hasFooter && currentBlockNumber == this->table.size())
ferencd@0 178 {
ferencd@0 179 result << "<tfoot>";
ferencd@0 180 isInFooter = true;
ferencd@0 181 }
ferencd@0 182 else
ferencd@0 183 {
ferencd@0 184 result << "<tbody>";
ferencd@0 185 }
ferencd@0 186
ferencd@0 187 for (const std::vector<std::string>& row : block)
ferencd@0 188 {
ferencd@0 189 result << "<tr>";
ferencd@0 190
ferencd@0 191 for (const std::string& column : row)
ferencd@0 192 {
ferencd@0 193 if (isInHeader)
ferencd@0 194 {
ferencd@0 195 result << "<th>";
ferencd@0 196 }
ferencd@0 197 else
ferencd@0 198 {
ferencd@0 199 result << "<td>";
ferencd@0 200 }
ferencd@0 201
ferencd@0 202 result << column;
ferencd@0 203
ferencd@0 204 if (isInHeader)
ferencd@0 205 {
ferencd@0 206 result << "</th>";
ferencd@0 207 }
ferencd@0 208 else
ferencd@0 209 {
ferencd@0 210 result << "</td>";
ferencd@0 211 }
ferencd@0 212 }
ferencd@0 213
ferencd@0 214 result << "</tr>";
ferencd@0 215 }
ferencd@0 216
ferencd@0 217 if (isInHeader)
ferencd@0 218 {
ferencd@0 219 result << "</thead>";
ferencd@0 220 }
ferencd@0 221 else if (isInFooter)
ferencd@0 222 {
ferencd@0 223 result << "</tfoot>";
ferencd@0 224 }
ferencd@0 225 else
ferencd@0 226 {
ferencd@0 227 result << "</tbody>";
ferencd@0 228 }
ferencd@0 229
ferencd@0 230 isFirstBlock = false;
ferencd@0 231 }
ferencd@0 232
ferencd@0 233 result << "</table>";
ferencd@0 234 }
ferencd@0 235
ferencd@0 236 private:
ferencd@0 237 bool isStarted;
ferencd@0 238 bool isFinished;
ferencd@0 239 uint32_t currentBlock;
ferencd@0 240 uint32_t currentRow;
ferencd@0 241 std::vector<std::vector<std::vector<std::string>>> table;
ferencd@0 242 }; // class TableParser
ferencd@0 243
ferencd@0 244 // -----------------------------------------------------------------------------
ferencd@0 245
ferencd@0 246 } // namespace maddy