summaryrefslogtreecommitdiff
path: root/src/producer.cpp
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2019-11-08 19:49:40 +0300
committerAleksey Veresov <aleksey@veresov.pro>2019-11-08 19:56:11 +0300
commit3047ed6100a56a529f26e43ada0a3fc3c3815c3e (patch)
tree9648d5a74bae9cbd90670a8bfa0af47189e4536f /src/producer.cpp
parentc6419eed96f2832b1de2b94d711552efaa9b172d (diff)
downloadtexo-3047ed6100a56a529f26e43ada0a3fc3c3815c3e.tar
texo-3047ed6100a56a529f26e43ada0a3fc3c3815c3e.tar.xz
texo-3047ed6100a56a529f26e43ada0a3fc3c3815c3e.zip
[texo] Full rewrite of inner representation.
Diffstat (limited to 'src/producer.cpp')
-rw-r--r--src/producer.cpp311
1 files changed, 291 insertions, 20 deletions
diff --git a/src/producer.cpp b/src/producer.cpp
index 2c60d48..c650459 100644
--- a/src/producer.cpp
+++ b/src/producer.cpp
@@ -1,43 +1,314 @@
#include "producer.hpp"
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Texo Producer
+ */
TexoProducer::TexoProducer(TexoExporter &exporter): exporter(exporter)
-{}
+{} // Just save exporter for future use.
+
+
+bool TexoProducer::End()
+{ // By default, no checks performed, so no error produced.
+ return true;
+}
+
+
+bool TexoProducer::Put(char c)
+{ // By default characters are not escaped, error means error in exporter.
+ return exporter.Put(c);
+}
+
+
+// Block Signal Handlers
+// By default, nothing has to be done, and no error produced,
+// except for paragraphs, which must be implemented.
+bool TexoProducer::Code() { return true; }
+bool TexoProducer::Header(int level) { return true; }
+bool TexoProducer::Quote() { return true; }
+
+
+// Modificator Signal Handlers
+// By default, nothing has to be done, and no error produced.
+bool TexoProducer::Bold() { return true; }
+bool TexoProducer::Italic() { return true; }
+bool TexoProducer::Mono() { return true; }
+bool TexoProducer::Strike() { return true; }
+bool TexoProducer::Underline() { return true; }
-void TexoProducer::End()
+bool TexoProducer::Link(
+ const ScriptVariable &link,
+ const ScriptVariable &title
+)
+{
+ return true;
+}
+
+bool TexoProducer::Link()
+{
+ return true;
+}
+
+
+bool TexoProducer::PutImage(
+ const ScriptVariable &src,
+ const ScriptVariable &alt,
+ const ScriptVariable &title
+)
+{
+ return true;
+}
+
+bool TexoProducer::PutHorizontalRule()
+{
+ return true;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Texo Strict Producer
+ */
+TexoProducerStrict::TexoProducerStrict(TexoExporter &exporter):
+ TexoProducer(exporter), block(block_none), opened(0)
{}
-void TexoProducer::Put(char c)
+
+bool TexoProducerStrict::End()
{
- Put(Texo(c));
+ bool ok = CloseBlock();
+ block = block_none;
+ return ok;
}
-void TexoProducer::Put(const Texo &piece)
+
+bool TexoProducerStrict::Put(char c)
{
- exporter.Put(piece.c);
+ return Start() && TruePut(c);
}
-void TexoProducer::Put(const TexoHeader &piece)
+
+bool TexoProducerStrict::Code()
{
- Put(TexoParagraph());
+ if (CloseBlock()) {
+ block = code;
+ return StartCode();
+ } else {
+ return false;
+ }
}
-void TexoProducer::Put(const TexoQuote &piece)
+bool TexoProducerStrict::Header(int level)
{
- Put(TexoParagraph());
+ if (CloseBlock()) {
+ block = header;
+ header_level = level;
+ return StartHeader(level);
+ } else {
+ return false;
+ }
}
-void TexoProducer::Put(const TexoCode &piece)
+bool TexoProducerStrict::Paragraph()
{
- Put(TexoParagraph());
+ if (CloseBlock()) {
+ block = paragraph;
+ return StartParagraph();
+ } else {
+ return false;
+ }
}
-void TexoProducer::Put(const TexoMono &piece) {}
-void TexoProducer::Put(const TexoBold &piece) {}
-void TexoProducer::Put(const TexoItalic &piece) {}
-void TexoProducer::Put(const TexoUnderline &piece) {}
-void TexoProducer::Put(const TexoStrike &piece) {}
+bool TexoProducerStrict::Quote()
+{
+ if (CloseBlock()) {
+ block = quote;
+ return StartQuote();
+ } else {
+ return false;
+ }
+}
+
+
+bool TexoProducerStrict::Bold()
+{
+ return SwitchMod(bold);
+}
+
+bool TexoProducerStrict::Italic()
+{
+ return SwitchMod(italic);
+}
+
+bool TexoProducerStrict::Mono()
+{
+ return SwitchMod(mono);
+}
+
+bool TexoProducerStrict::Strike()
+{
+ return SwitchMod(strike);
+}
-void TexoProducer::Put(const TexoImage &piece) {}
-void TexoProducer::Put(const TexoLink &piece) {}
-void TexoProducer::Put(const TexoHorizontalRule &piece) {}
+bool TexoProducerStrict::Underline()
+{
+ return SwitchMod(underline);
+}
+
+bool TexoProducerStrict::Link(
+ const ScriptVariable &path,
+ const ScriptVariable &title
+)
+{
+ if (IsOpened(link)) {
+ int closed = CloseMods(link);
+ if (closed >= 0) {
+ return Reopen(closed);
+ } else {
+ return false;
+ }
+ } else {
+ link_link = &path;
+ link_title = &title;
+ return Start() && OpenMod(link);
+ }
+}
+
+bool TexoProducerStrict::Link()
+{
+ if (IsOpened(link)) {
+ int closed = CloseMods(link);
+ if (closed >= 0) {
+ return Reopen(closed);
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool TexoProducerStrict::PutImage(
+ const ScriptVariable &src,
+ const ScriptVariable &alt,
+ const ScriptVariable &title
+)
+{
+ return Start() && TruePutImage(src, alt, title);
+}
+
+bool TexoProducerStrict::PutHorizontalRule()
+{
+ return Start() && TruePutHorizontalRule();
+}
+
+
+bool TexoProducerStrict::Start()
+{
+ if (!block) {
+ block = paragraph;
+ return StartParagraph();
+ } else {
+ return true;
+ }
+}
+
+bool TexoProducerStrict::CloseBlock()
+{
+ if (CloseMods()) {
+ switch (block) {
+ case block_none: return true;
+ case code: return CloseCode();
+ case header: return CloseHeader(header_level);
+ case paragraph: return CloseParagraph();
+ case quote: return CloseQuote();
+ }
+ return true; // Inpossible, since all cases are in switch.
+ } else {
+ return false;
+ }
+}
+
+bool TexoProducerStrict::SwitchMod(Mod mod)
+{
+ if (IsOpened(mod)) {
+ int closed = CloseMods(mod);
+ if (closed >= 0) {
+ return Reopen(closed);
+ } else {
+ return false;
+ }
+ } else {
+ return Start() && OpenMod(mod);
+ }
+}
+
+bool TexoProducerStrict::OpenMod(Mod mod)
+{
+ mods[opened] = mod;
+ ++opened;
+ switch (mod) {
+ case bold: return StartBold();
+ case italic: return StartItalic();
+ case link: return StartLink(*link_link, *link_title);
+ case mono: return StartMono();
+ case strike: return StartStrike();
+ case underline: return StartUnderline();
+ }
+ return true; // Inpossible, since all cases are in switch.
+}
+
+bool TexoProducerStrict::CloseMod(Mod mod)
+{
+ switch (mod) {
+ case bold: return CloseBold();
+ case italic: return CloseItalic();
+ case link: return CloseLink(*link_link, *link_title);
+ case mono: return CloseMono();
+ case strike: return CloseStrike();
+ case underline: return CloseUnderline();
+ }
+ return true; // Inpossible, since all cases are in switch.
+}
+
+int TexoProducerStrict::CloseMods(Mod last)
+{
+ const int old = opened;
+ while (opened) {
+ Mod top = mods[--opened];
+ if (CloseMod(top)) {
+ if (top == last) {
+ return old - opened;
+ }
+ } else {
+ return -1;
+ }
+ }
+ return old - opened;
+}
+
+bool TexoProducerStrict::CloseMods()
+{
+ bool ok = true;
+ while (ok && opened) {
+ ok = CloseMod(mods[--opened]);
+ }
+ return ok;
+}
+
+bool TexoProducerStrict::Reopen(int closed)
+{
+ bool ok = true;
+ int new_opened = opened + closed;
+ while (ok && opened != new_opened) {
+ ok = OpenMod(mods[opened]);
+ }
+ return ok;
+}
+
+bool TexoProducerStrict::IsOpened(Mod mod) const
+{
+ bool is = false;
+ for (int i = opened - 1; !is && i >= 0; --i) {
+ is = mods[i] == mod;
+ }
+ return is;
+}