diff 3rdparty/maddy/blockparser.h @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3rdparty/maddy/blockparser.h	Tue Aug 17 11:19:54 2021 +0200
@@ -0,0 +1,203 @@
+/*
+ * This project is licensed under the MIT license. For more information see the
+ * LICENSE file.
+ */
+#pragma once
+
+// -----------------------------------------------------------------------------
+
+#include <functional>
+#include <sstream>
+#include <string>
+// windows compatibility includes
+#include <cctype>
+#include <algorithm>
+
+// -----------------------------------------------------------------------------
+
+namespace maddy {
+
+// -----------------------------------------------------------------------------
+
+/**
+ * BlockParser
+ *
+ * The code expects every child to have the following static function to be
+ * implemented:
+ * `static bool IsStartingLine(const std::string& line)`
+ *
+ * @class
+ */
+class BlockParser
+{
+public:
+  /**
+   * ctor
+   *
+   * @method
+   * @param {std::function<void(std::string&)>} parseLineCallback
+   * @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
+   */
+  BlockParser(
+    std::function<void(std::string&)> parseLineCallback,
+    std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
+  )
+    : result("", std::ios_base::ate | std::ios_base::in | std::ios_base::out)
+    , childParser(nullptr)
+    , parseLineCallback(parseLineCallback)
+    , getBlockParserForLineCallback(getBlockParserForLineCallback)
+  {}
+
+  /**
+   * dtor
+   *
+   * @method
+   */
+  virtual ~BlockParser() {}
+
+  /**
+   * AddLine
+   *
+   * Adding a line which has to be parsed.
+   *
+   * @method
+   * @param {std::string&} line
+   * @return {void}
+   */
+  virtual void
+  AddLine(std::string& line)
+  {
+    this->parseBlock(line);
+
+    if (this->isInlineBlockAllowed() && !this->childParser)
+    {
+      this->childParser = this->getBlockParserForLine(line);
+    }
+
+    if (this->childParser)
+    {
+      this->childParser->AddLine(line);
+
+      if (this->childParser->IsFinished())
+      {
+        this->result << this->childParser->GetResult().str();
+        this->childParser = nullptr;
+      }
+
+      return;
+    }
+
+    if (this->isLineParserAllowed())
+    {
+      this->parseLine(line);
+    }
+
+    this->result << line;
+  }
+
+  /**
+   * IsFinished
+   *
+   * Check if the BlockParser is done
+   *
+   * @method
+   * @return {bool}
+   */
+  virtual bool IsFinished() const = 0;
+
+  /**
+   * GetResult
+   *
+   * Get the parsed HTML output.
+   *
+   * @method
+   * @return {std::stringstream}
+   */
+  std::stringstream&
+  GetResult()
+  {
+    return this->result;
+  }
+
+  /**
+   * Clear
+   *
+   * Clear the result to reuse the parser object.
+   *
+   * It is only used by one test for now.
+   *
+   * @method
+   * @return {void}
+   */
+  void
+  Clear()
+  {
+    this->result.str("");
+  }
+
+protected:
+  std::stringstream result;
+  std::shared_ptr<BlockParser> childParser;
+
+  virtual bool isInlineBlockAllowed() const = 0;
+  virtual bool isLineParserAllowed() const = 0;
+  virtual void parseBlock(std::string& line) = 0;
+
+  void
+  parseLine(std::string& line)
+  {
+    if (parseLineCallback)
+    {
+      parseLineCallback(line);
+    }
+  }
+
+  uint32_t
+  getIndentationWidth(const std::string& line) const
+  {
+    bool hasMetNonSpace = false;
+
+    uint32_t indentation = static_cast<uint32_t>(
+      std::count_if(
+        line.begin(),
+        line.end(),
+        [&hasMetNonSpace](unsigned char c)
+        {
+          if (hasMetNonSpace)
+          {
+            return false;
+          }
+
+          if (std::isspace(c))
+          {
+            return true;
+          }
+
+          hasMetNonSpace = true;
+          return false;
+        }
+      )
+    );
+
+    return indentation;
+  }
+
+  std::shared_ptr<BlockParser>
+  getBlockParserForLine(const std::string& line)
+  {
+    if (getBlockParserForLineCallback)
+    {
+      return getBlockParserForLineCallback(line);
+    }
+
+    return nullptr;
+  }
+
+private:
+  std::function<void(std::string&)> parseLineCallback;
+  std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback;
+}; // class BlockParser
+
+// -----------------------------------------------------------------------------
+
+} // namespace maddy