From 3047ed6100a56a529f26e43ada0a3fc3c3815c3e Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Fri, 8 Nov 2019 19:49:40 +0300 Subject: [texo] Full rewrite of inner representation. --- src/exporter.cpp | 11 +- src/exporter.hpp | 8 +- src/file.cpp | 10 +- src/file.hpp | 10 +- src/html.cpp | 235 ++++++++++++++++-------------------- src/html.hpp | 70 +++++------ src/importer.cpp | 49 ++++++-- src/importer.hpp | 24 +++- src/lines.cpp | 52 ++++---- src/lines.hpp | 25 ++-- src/markdown.cpp | 355 ++++++++++++++++++++++++++----------------------------- src/markdown.hpp | 49 +++++--- src/plain.cpp | 132 ++++++++++++--------- src/plain.hpp | 26 ++-- src/producer.cpp | 311 ++++++++++++++++++++++++++++++++++++++++++++---- src/producer.hpp | 189 ++++++++++++++++++++++++++--- src/script.cpp | 21 ++++ src/script.hpp | 25 ++++ src/str.cpp | 15 --- src/str.hpp | 19 --- src/texo.cpp | 8 -- src/texo.hpp | 61 ---------- 22 files changed, 1074 insertions(+), 631 deletions(-) create mode 100644 src/script.cpp create mode 100644 src/script.hpp delete mode 100644 src/str.cpp delete mode 100644 src/str.hpp delete mode 100644 src/texo.cpp delete mode 100644 src/texo.hpp diff --git a/src/exporter.cpp b/src/exporter.cpp index 3baa99e..b9a5b3f 100644 --- a/src/exporter.cpp +++ b/src/exporter.cpp @@ -1,10 +1,15 @@ #include "exporter.hpp" -void TexoExporter::Put(const ScriptVariable &str) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Exporter + */ +bool TexoExporter::Put(const ScriptVariable &str) { + bool ok = true; const int len = str.Length(); - for (int i = 0; i < len; ++i) { - Put(str[i]); + for (int i = 0; ok && i < len; ++i) { + ok = Put(str[i]); } + return ok; } diff --git a/src/exporter.hpp b/src/exporter.hpp index 6a0be93..a20f695 100644 --- a/src/exporter.hpp +++ b/src/exporter.hpp @@ -4,10 +4,14 @@ #include +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Exporter + * Texo interface for outputting. + */ class TexoExporter { public: - virtual void Put(char c) = 0; - virtual void Put(const ScriptVariable &str); + virtual bool Put(char c) = 0; + virtual bool Put(const ScriptVariable &str); }; diff --git a/src/file.cpp b/src/file.cpp index ae41bde..221ff81 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1,15 +1,21 @@ #include "file.hpp" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo File Exporter + */ TexoExporterFile::TexoExporterFile(FILE *file): file(file) {} -void TexoExporterFile::Put(char c) + +bool TexoExporterFile::Put(char c) { fputc(c, file); + return !ferror(file); } -void TexoExporterFile::Put(const ScriptVariable &str) +bool TexoExporterFile::Put(const ScriptVariable &str) { fwrite(str.c_str(), 1, str.Length(), file); + return !ferror(file); } diff --git a/src/file.hpp b/src/file.hpp index 1cfea0b..5f8adb6 100644 --- a/src/file.hpp +++ b/src/file.hpp @@ -5,12 +5,18 @@ #include +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo File Exporter + * Simple utility class to make output into FILE *variable. + */ class TexoExporterFile: public TexoExporter { public: TexoExporterFile(FILE *file); - void Put(char c); - void Put(const ScriptVariable &str); + + bool Put(char c); + bool Put(const ScriptVariable &str); + private: FILE *file; diff --git a/src/html.cpp b/src/html.cpp index f40b8bd..ed67781 100644 --- a/src/html.cpp +++ b/src/html.cpp @@ -2,188 +2,153 @@ TexoProducerHTML::TexoProducerHTML(TexoExporter &exporter): - TexoProducer(exporter), opened_block(none) + TexoProducerStrict(exporter) {} -void TexoProducerHTML::End() + +bool TexoProducerHTML::TruePut(char c) { - Close(); - opened_block = none; + switch (c) { + case '<': return exporter.Put("<"); break; + case '>': return exporter.Put(">"); break; + case '&': return exporter.Put("&"); break; + default: return exporter.Put(c); + } } -void TexoProducerHTML::Put(const Texo &piece) + +bool TexoProducerHTML::StartCode() { - switch (piece.c) { - case '<': exporter.Put("<"); break; - case '>': exporter.Put(">"); break; - case '&': exporter.Put("&"); break; - default: exporter.Put(piece.c); break; - } + return exporter.Put("\n
\n");
 }
 
-void TexoProducerHTML::Put(const TexoHeader &piece)
+bool TexoProducerHTML::StartHeader(int level)
 {
-    Close();
-    if (piece.level <= 1) {
-        exporter.Put("\n
\n"); - opened_block = header_6; - } else if (piece.level == 2) { - exporter.Put("\n
\n"); - opened_block = header_5; - } else if (piece.level == 3) { - exporter.Put("\n

\n"); - opened_block = header_4; - } else if (piece.level == 4) { - exporter.Put("\n

\n"); - opened_block = header_3; - } else if (piece.level == 5) { - exporter.Put("\n

\n"); - opened_block = header_2; + if (level <= 1) { + return exporter.Put("\n

\n"); + } else if (level == 2) { + return exporter.Put("\n
\n"); + } else if (level == 3) { + return exporter.Put("\n

\n"); + } else if (level == 4) { + return exporter.Put("\n

\n"); + } else if (level == 5) { + return exporter.Put("\n

\n"); } else { - exporter.Put("\n

\n"); - opened_block = header_1; + return exporter.Put("\n

\n"); } } -void TexoProducerHTML::Put(const TexoParagraph &piece) +bool TexoProducerHTML::StartParagraph() { - Close(); - opened_block = paragraph; - exporter.Put("\n

\n"); + return exporter.Put("\n

\n"); } -void TexoProducerHTML::Put(const TexoCode &piece) +bool TexoProducerHTML::StartQuote() { - Close(); - opened_block = code; - exporter.Put("\n

\n");
+    return exporter.Put("\n

\n"); } -void TexoProducerHTML::Put(const TexoQuote &piece) +bool TexoProducerHTML::CloseCode() { - Close(); - opened_block = quote; - exporter.Put("\n

\n"); + return exporter.Put("\n

\n"); } -void TexoProducerHTML::Put(const TexoMono &piece) +bool TexoProducerHTML::CloseHeader(int level) { - static bool closing = false; - if (closing) { - exporter.Put(""); + if (level <= 1) { + return exporter.Put("\n

\n"); + } else if (level == 2) { + return exporter.Put("\n\n"); + } else if (level == 3) { + return exporter.Put("\n\n"); + } else if (level == 4) { + return exporter.Put("\n\n"); + } else if (level == 5) { + return exporter.Put("\n\n"); } else { - exporter.Put(""); + return exporter.Put("\n\n"); } - closing = !closing; } -void TexoProducerHTML::Put(const TexoBold &piece) +bool TexoProducerHTML::CloseParagraph() { - static bool closing = false; - if (closing) { - exporter.Put(""); - } else { - exporter.Put(""); - } - closing = !closing; + return exporter.Put("\n

\n"); } -void TexoProducerHTML::Put(const TexoItalic &piece) +bool TexoProducerHTML::CloseQuote() { - static bool closing = false; - if (closing) { - exporter.Put(""); - } else { - exporter.Put(""); - } - closing = !closing; + return exporter.Put("\n

\n"); } -void TexoProducerHTML::Put(const TexoUnderline &piece) + +bool TexoProducerHTML::StartBold() { return exporter.Put(""); } +bool TexoProducerHTML::StartItalic() { return exporter.Put(""); } +bool TexoProducerHTML::StartMono() { return exporter.Put(""); } +bool TexoProducerHTML::StartStrike() { return exporter.Put(""); } +bool TexoProducerHTML::StartUnderline() { return exporter.Put(""); } + +bool TexoProducerHTML::CloseBold() { return exporter.Put(""); } +bool TexoProducerHTML::CloseItalic() { return exporter.Put(""); } +bool TexoProducerHTML::CloseMono() { return exporter.Put(""); } +bool TexoProducerHTML::CloseStrike() { return exporter.Put(""); } +bool TexoProducerHTML::CloseUnderline() { return exporter.Put(""); } + +bool TexoProducerHTML::StartLink( + const ScriptVariable &link, + const ScriptVariable &title +) { - static bool closing = false; - if (closing) { - exporter.Put(""); - } else { - exporter.Put(""); + bool ok = true; + if (link != "") { + ok = ok && exporter.Put(""); } - closing = !closing; + return ok; } -void TexoProducerHTML::Put(const TexoStrike &piece) +bool TexoProducerHTML::CloseLink( + const ScriptVariable &link, + const ScriptVariable &title +) { - static bool closing = false; - if (closing) { - exporter.Put(""); + if (link != "") { + return exporter.Put(""); } else { - exporter.Put(""); + return true; } - closing = !closing; } -void TexoProducerHTML::Put(const TexoImage &piece) -{ - if (piece.path != "") { - bool link = piece.link != ""; - bool title = piece.title != ""; - if (link) { - exporter.Put(""); - } - exporter.Put("");
-            exporter.Put(piece.alt);
-        }
-        if (title) {
-            exporter.Put(""); - if (link) { - exporter.Put(""); - } - } -} -void TexoProducerHTML::Put(const TexoLink &piece) +bool TexoProducerHTML::TruePutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title +) { - if (piece.text != "" && piece.link != "") { - exporter.Put(""); - exporter.Put(piece.text); - exporter.Put(""); + ok = ok && exporter.Put("'/>"); } + return ok; } -void TexoProducerHTML::Put(const TexoHorizontalRule &piece) -{ - exporter.Put("\n
\n"); -} - -void TexoProducerHTML::Close() +bool TexoProducerHTML::TruePutHorizontalRule() { - switch (opened_block) { - case none: break; - case header_1: exporter.Put("\n\n"); break; - case header_2: exporter.Put("\n\n"); break; - case header_3: exporter.Put("\n\n"); break; - case header_4: exporter.Put("\n\n"); break; - case header_5: exporter.Put("\n\n"); break; - case header_6: exporter.Put("\n\n"); break; - case paragraph: exporter.Put("\n

\n"); break; - case quote: exporter.Put("\n

\n"); break; - case code: exporter.Put("\n
\n"); break; - } + return exporter.Put("\n
\n"); } diff --git a/src/html.hpp b/src/html.hpp index b96200f..aa22cf1 100644 --- a/src/html.hpp +++ b/src/html.hpp @@ -6,44 +6,44 @@ #include "importer.hpp" -class TexoProducerHTML: public TexoProducer { +class TexoProducerHTML: public TexoProducerStrict { public: TexoProducerHTML(TexoExporter &exporter); - void End(); - - void Put(const Texo &piece); - - void Put(const TexoHeader &piece); - void Put(const TexoParagraph &piece); - void Put(const TexoCode &piece); - void Put(const TexoQuote &piece); - - void Put(const TexoMono &piece); - void Put(const TexoBold &piece); - void Put(const TexoItalic &piece); - void Put(const TexoUnderline &piece); - void Put(const TexoStrike &piece); - - void Put(const TexoImage &piece); - void Put(const TexoLink &piece); - void Put(const TexoHorizontalRule &piece); - -private: - void Close(); - - enum { - none = 0, - header_1, - header_2, - header_3, - header_4, - header_5, - header_6, - paragraph, - code, - quote - } opened_block; +protected: + bool TruePut(char c); + + bool StartCode(); + bool StartHeader(int level); + bool StartParagraph(); + bool StartQuote(); + + bool CloseCode(); + bool CloseHeader(int level); + bool CloseParagraph(); + bool CloseQuote(); + + bool StartBold(); + bool StartItalic(); + bool StartMono(); + bool StartStrike(); + bool StartUnderline(); + + bool CloseBold(); + bool CloseItalic(); + bool CloseMono(); + bool CloseStrike(); + bool CloseUnderline(); + + bool StartLink(const ScriptVariable &link, const ScriptVariable &title); + bool CloseLink(const ScriptVariable &link, const ScriptVariable &title); + + bool TruePutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title + ); + bool TruePutHorizontalRule(); }; diff --git a/src/importer.cpp b/src/importer.cpp index af475a5..73ff060 100644 --- a/src/importer.cpp +++ b/src/importer.cpp @@ -1,27 +1,58 @@ #include "importer.hpp" -TexoImporter::TexoImporter(TexoProducer &producer): producer(producer) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Importer + */ +TexoImporter::TexoImporter(TexoProducer &producer): + producer(producer), ok(true) {} -void TexoImporter::End() +TexoImporter::~TexoImporter() { End(); } + + +bool TexoImporter::End() +{ + return ok = ok && TrueEnd(); +} + +bool TexoImporter::Put(char c) +{ + return ok = ok && TruePut(c); +} + +bool TexoImporter::Put(const ScriptVariable &s) { - producer.End(); + return ok = ok && TruePut(s); } -void TexoImporter::Put(const ScriptVariable &str) +bool TexoImporter::Put(FILE *f) +{ + return ok = ok && TruePut(f); +} + + +bool TexoImporter::TrueEnd() +{ + return producer.End(); +} + + +bool TexoImporter::TruePut(const ScriptVariable &str) { const int len = str.Length(); - for (int i = 0; i < len; ++i) { - Put(str[i]); + for (int i = 0; ok && i < len; ++i) { + ok = TruePut(str[i]); } + return ok; } -void TexoImporter::Put(FILE *file) +bool TexoImporter::TruePut(FILE *file) { if (file) { - for (int c = fgetc(file); c != EOF; c = fgetc(file)) { - Put(c); + for (int c = fgetc(file); ok && c != EOF; c = fgetc(file)) { + ok = TruePut(c); } } + return ok; } diff --git a/src/importer.hpp b/src/importer.hpp index 3a31fab..9280a34 100644 --- a/src/importer.hpp +++ b/src/importer.hpp @@ -5,18 +5,34 @@ #include +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Importer + * Texo interface for parsers from input characters into inner representation, + * described by Texo Producer. + */ class TexoImporter { public: TexoImporter(TexoProducer &producer); + ~TexoImporter(); - virtual void End(); - virtual void Put(char c) = 0; - virtual void Put(const ScriptVariable &str); - virtual void Put(FILE *file); + bool End(); + bool Put(char c); + bool Put(const ScriptVariable &s); + bool Put(FILE *f); + protected: + virtual bool TrueEnd(); + + + virtual bool TruePut(char c) = 0; + virtual bool TruePut(const ScriptVariable &str); + virtual bool TruePut(FILE *file); + + TexoProducer &producer; + bool ok; }; diff --git a/src/lines.cpp b/src/lines.cpp index bacf048..c7b605b 100644 --- a/src/lines.cpp +++ b/src/lines.cpp @@ -1,85 +1,91 @@ #include "lines.hpp" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Lines Producer + */ TexoProducerLines::TexoProducerLines(TexoExporter &exporter): TexoProducer(exporter), newline(true) {} -void TexoProducerLines::End() + +bool TexoProducerLines::End() { if (!newline) { exporter.Put('\n'); newline = true; } + return true; } -void TexoProducerLines::Put(const Texo &piece) + +bool TexoProducerLines::Put(char c) { - if (piece.c == '\n') { + if (c == '\n') { if (!newline) { exporter.Put(' '); newline = true; } } else { - exporter.Put(piece.c); + exporter.Put(c); newline = false; } + return true; } -void TexoProducerLines::Put(const TexoParagraph &piece) + +bool TexoProducerLines::Paragraph() { if (!newline) { exporter.Put('\n'); newline = true; } + return true; } -void TexoProducerLines::Put(const TexoQuote &piece) +bool TexoProducerLines::Quote() { if (!newline) { exporter.Put('\n'); } exporter.Put("> "); newline = false; + return true; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Lines Importer + */ TexoImporterLines::TexoImporterLines(TexoProducer &producer): TexoImporter(producer), newline(true), quote(false) {} -void TexoImporterLines::Put(char c) + +bool TexoImporterLines::TruePut(char c) { if (c == '\n') { if (!newline) { newline = true; quote = false; } + return true; } else if (newline) { + newline = false; if (c == '>') { - producer.Put(TexoQuote()); quote = true; + return producer.Quote(); } else { - producer.Put(TexoParagraph()); - producer.Put(c); + return producer.Paragraph() && producer.Put(c); } - newline = false; } else if (quote) { if (c != ' ') { quote = false; - producer.Put(c); + return producer.Put(c); + } else { + return true; } } else { - producer.Put(c); + return producer.Put(c); } } - -void TexoImporterLines::Put(const ScriptVariable &str) -{ - TexoImporter::Put(str); -} - -void TexoImporterLines::Put(FILE *file) -{ - TexoImporter::Put(file); -} diff --git a/src/lines.hpp b/src/lines.hpp index d6ce555..7049919 100644 --- a/src/lines.hpp +++ b/src/lines.hpp @@ -6,29 +6,40 @@ #include "importer.hpp" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Lines Producer + */ class TexoProducerLines: public TexoProducer { public: TexoProducerLines(TexoExporter &exporter); - void End(); - void Put(const Texo &piece); + bool End(); + + + bool Put(char c); + + + bool Paragraph(); + bool Quote(); - void Put(const TexoParagraph &piece); - void Put(const TexoQuote &piece); private: bool newline; }; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Lines Importer + */ class TexoImporterLines: public TexoImporter { public: TexoImporterLines(TexoProducer &producer); - void Put(char c); - void Put(const ScriptVariable &str); - void Put(FILE *file); + +protected: + bool TruePut(char c); + private: bool newline; diff --git a/src/markdown.cpp b/src/markdown.cpp index facba67..6931461 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -6,186 +6,180 @@ TexoProducerMarkdown::TexoProducerMarkdown(TexoExporter &exporter): quoted(false), newline(false), header(false), code(false), nospace(true) {} -void TexoProducerMarkdown::End() +bool TexoProducerMarkdown::End() { if (!newline) { - exporter.Put('\n'); newline = true; + return exporter.Put('\n'); } + return true; } -void TexoProducerMarkdown::Put(const Texo &piece) +bool TexoProducerMarkdown::Put(char c) { - char c = piece.c; + bool ok = true; if (c == '\n') { if (code) { - exporter.Put('\n'); + ok = exporter.Put('\n'); } else if (quoted) { - exporter.Put("\n> "); + ok = exporter.Put("\n> "); } else if (!nospace) { if (header || newline) { - exporter.Put(' '); + ok = exporter.Put(' '); } else { - exporter.Put('\n'); + ok = exporter.Put('\n'); newline = true; } } } else { if (c == '*' || c == '_' || c == '`' || c == '+' || c == '~') { - exporter.Put('\\'); + ok = exporter.Put('\\'); } - exporter.Put(c); + ok = ok && exporter.Put(c); newline = false; nospace = false; } + return ok; } -void TexoProducerMarkdown::Put(const TexoHeader &piece) + +bool TexoProducerMarkdown::Code() { - Close(); - if (piece.level <= 1) { - exporter.Put("###### "); - } else if (piece.level == 2) { - exporter.Put("##### "); - } else if (piece.level == 3) { - exporter.Put("#### "); - } else if (piece.level == 4) { - exporter.Put("### "); - } else if (piece.level == 5) { - exporter.Put("## "); + bool ok = Close(); + code = true; + return ok && exporter.Put("```\n"); +} + +bool TexoProducerMarkdown::Header(int level) +{ + bool ok = Close(); + if (level <= 1) { + ok = ok && exporter.Put("###### "); + } else if (level == 2) { + ok = ok && exporter.Put("##### "); + } else if (level == 3) { + ok = ok && exporter.Put("#### "); + } else if (level == 4) { + ok = ok && exporter.Put("### "); + } else if (level == 5) { + ok = ok && exporter.Put("## "); } else { - exporter.Put("# "); + ok = ok && exporter.Put("# "); } - header = true; + header = true; + return ok; } -void TexoProducerMarkdown::Put(const TexoParagraph &piece) +bool TexoProducerMarkdown::Paragraph() { - Close(); + return Close(); } -void TexoProducerMarkdown::Put(const TexoCode &piece) +bool TexoProducerMarkdown::Quote() { - Close(); - exporter.Put("```\n"); - code = true; -} - -void TexoProducerMarkdown::Put(const TexoQuote &piece) -{ - Close(); - exporter.Put("> "); + bool ok = Close(); quoted = true; + return ok && exporter.Put("> "); } -void TexoProducerMarkdown::Put(const TexoMono &piece) -{ - exporter.Put("`"); - newline = false; - nospace = false; -} -void TexoProducerMarkdown::Put(const TexoBold &piece) -{ - exporter.Put("**"); - newline = false; - nospace = false; -} +bool TexoProducerMarkdown::Mono() { return Mod("`"); } +bool TexoProducerMarkdown::Bold() { return Mod("**"); } +bool TexoProducerMarkdown::Italic() { return Mod("_"); } +bool TexoProducerMarkdown::Underline() { return Mod("++"); } +bool TexoProducerMarkdown::Strike() { return Mod("~~"); } -void TexoProducerMarkdown::Put(const TexoItalic &piece) +bool TexoProducerMarkdown::Link( + const ScriptVariable &link, + const ScriptVariable &title +) { - exporter.Put("_"); - newline = false; - nospace = false; -} - -void TexoProducerMarkdown::Put(const TexoUnderline &piece) -{ - exporter.Put("++"); - newline = false; - nospace = false; -} - -void TexoProducerMarkdown::Put(const TexoStrike &piece) -{ - exporter.Put("~~"); - newline = false; - nospace = false; + bool ok = Link(); + if (link != "") { + ok = ok && exporter.Put('['); + link_link = link; + link_title = title; + } + return ok; } -void TexoProducerMarkdown::Put(const TexoImage &piece) +bool TexoProducerMarkdown::Link() { - if (piece.path != "") { - const bool link = piece.link != ""; - if (link) { - exporter.Put('['); - } - exporter.Put("!["); - exporter.Put(piece.alt); - exporter.Put("]("); - exporter.Put(piece.path); - if (piece.title != "") { - exporter.Put(" \""); - exporter.Put(piece.title); - exporter.Put('"'); - } - exporter.Put(')'); - if (link) { - exporter.Put("]("); - exporter.Put(piece.link); - if (piece.title != "") { - exporter.Put(" \""); - exporter.Put(piece.title); - exporter.Put('"'); - } - exporter.Put(')'); + bool ok = true; + if (link_link != "") { + ok = ok && exporter.Put("]("); + ok = ok && exporter.Put(link_link); + if (link_title != "") { + ok = ok && exporter.Put(" \""); + ok = ok && exporter.Put(link_title); + ok = ok && exporter.Put('"'); } + ok = ok && exporter.Put(')'); } - newline = false; - nospace = false; -} - -void TexoProducerMarkdown::Put(const TexoLink &piece) -{ - if (piece.text != "") { - exporter.Put('['); - exporter.Put(piece.text); - exporter.Put("]("); - exporter.Put(piece.link); - if (piece.title != "") { - exporter.Put(" \""); - exporter.Put(piece.title); - exporter.Put('"'); + return ok; +} + + +bool TexoProducerMarkdown::PutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title +) +{ + bool ok = true; + if (src != "") { + ok = ok && exporter.Put("!["); + ok = ok && exporter.Put(alt); + ok = ok && exporter.Put("]("); + ok = ok && exporter.Put(src); + if (title != "") { + ok = ok && exporter.Put(" \""); + ok = ok && exporter.Put(title); + ok = ok && exporter.Put('"'); } - exporter.Put(')'); + ok = ok && exporter.Put(')'); } newline = false; nospace = false; + return ok; } -void TexoProducerMarkdown::Put(const TexoHorizontalRule &piece) +bool TexoProducerMarkdown::PutHorizontalRule() { + bool ok = true; if (!newline && !nospace) { - exporter.Put('\n'); + ok = ok && exporter.Put('\n'); } - exporter.Put("--------------------------------------------------\n"); nospace = true; + return ok && exporter.Put( + "--------------------------------------------------\n" + ); } -void TexoProducerMarkdown::Close() + +bool TexoProducerMarkdown::Mod(const ScriptVariable &str) { + newline = false; + nospace = false; + return exporter.Put(str); +} + +bool TexoProducerMarkdown::Close() +{ + bool ok = true; if (code) { - exporter.Put("\n```"); + ok = exporter.Put("\n```"); code = false; nospace = false; newline = false; } if (!newline && !nospace) { - exporter.Put("\n\n"); + ok = ok && exporter.Put("\n\n"); } header = false; quoted = false; nospace = true; + return ok; } @@ -193,10 +187,10 @@ TexoImporterMarkdown::TexoImporterMarkdown(TexoProducer &producer): TexoImporter(producer), state(start) {} -void TexoImporterMarkdown::Put(char c) + +bool TexoImporterMarkdown::TruePut(char c) { switch (state) { - case error: break; case start: Start(c); break; case text: Text(c); break; case header_text: HeaderText(c); break; @@ -218,17 +212,9 @@ void TexoImporterMarkdown::Put(char c) case header_pre: HeaderPre(c); break; case code: Code(c); break; } + return ok; } -void TexoImporterMarkdown::Put(const ScriptVariable &str) -{ - TexoImporter::Put(str); -} - -void TexoImporterMarkdown::Put(FILE *file) -{ - TexoImporter::Put(file); -} void TexoImporterMarkdown::Start(char c) { @@ -238,17 +224,17 @@ void TexoImporterMarkdown::Start(char c) state = header; header_level = 6; } else if (c == '>') { - producer.Put(TexoQuote()); + ok = producer.Quote(); state = quote_pre; } else if (c == '-') { - producer.Put(TexoParagraph()); + ok = producer.Paragraph(); state = rule; rule_dash_count = 1; } else if (c == '`') { state = code; code_quote_count = 1; } else { - producer.Put(TexoParagraph()); + ok = producer.Paragraph(); state = text; Put(c); } @@ -258,14 +244,14 @@ void TexoImporterMarkdown::Text(char c) { back = text; switch (c) { - case '\\': state = backslash; break; - case '\n': state = newline; break; - case '*': state = asterisk; break; - case '_': state = underline; break; - case '+': state = plus; break; - case '~': state = tilde; break; - case '`': Backquote(); break; - default: producer.Put(c); + case '\\': state = backslash; break; + case '\n': state = newline; break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '+': state = plus; break; + case '~': state = tilde; break; + case '`': Backquote(); break; + default: ok = producer.Put(c); } } @@ -273,14 +259,14 @@ void TexoImporterMarkdown::HeaderText(char c) { back = header_text; switch (c) { - case '\\': state = backslash; break; - case '\n': state = paragraph; break; - case '*': state = asterisk; break; - case '_': state = underline; break; - case '+': state = plus; break; - case '~': state = tilde; break; - case '`': Backquote(); break; - default: producer.Put(c); + case '\\': state = backslash; break; + case '\n': state = paragraph; break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '+': state = plus; break; + case '~': state = tilde; break; + case '`': Backquote(); break; + default: ok = producer.Put(c); } } @@ -303,14 +289,14 @@ void TexoImporterMarkdown::QuoteText(char c) case '+': state = plus; break; case '~': state = tilde; break; case '`': Backquote(); break; - default: producer.Put(c); + default: ok = producer.Put(c); } } void TexoImporterMarkdown::QuoteNewline(char c) { if (c == '>') { - producer.Put('\n'); + ok = producer.Put('\n'); state = quote_pre; } else { state = paragraph; @@ -322,14 +308,13 @@ void TexoImporterMarkdown::CodeText(char c) { back = code_text; switch (c) { - case '\\': state = backslash; break; - case '\n': state = code_newline; break; - case '*': state = asterisk; break; - case '_': state = underline; break; - case '+': state = plus; break; - case '~': state = tilde; break; - case '`': state = error; break; - default: producer.Put(c); + case '\\': state = backslash; break; + case '\n': state = code_newline; break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '+': state = plus; break; + case '~': state = tilde; break; + default: ok = producer.Put(c); } } @@ -339,9 +324,9 @@ void TexoImporterMarkdown::CodeNewline(char c) state = code_end; code_quote_count = 1; } else { - producer.Put('\n'); + ok = producer.Put('\n'); state = code_text; - CodeText(c); + Put(c); } } @@ -353,16 +338,16 @@ void TexoImporterMarkdown::CodeEnd(char c) if (code_quote_count == 3) { state = paragraph; } else { - state = error; + ok = false; } } else { - state = error; + ok = false; } } void TexoImporterMarkdown::Backslash(char c) { - producer.Put(c); + ok = producer.Put(c); state = back; } @@ -370,9 +355,9 @@ void TexoImporterMarkdown::Asterisk(char c) { state = back; if (c == '*') { - producer.Put(TexoBold()); + ok = producer.Bold(); } else { - producer.Put(TexoItalic()); + ok = producer.Italic(); Put(c); } } @@ -381,9 +366,9 @@ void TexoImporterMarkdown::Underline(char c) { state = back; if (c == '_') { - producer.Put(TexoBold()); + ok = producer.Bold(); } else { - producer.Put(TexoItalic()); + ok = producer.Italic(); Put(c); } } @@ -392,9 +377,9 @@ void TexoImporterMarkdown::Plus(char c) { state = back; if (c == '+') { - producer.Put(TexoUnderline()); + ok = producer.Underline(); } else { - producer.Put('+'); + ok = producer.Put('+'); Put(c); } } @@ -403,9 +388,9 @@ void TexoImporterMarkdown::Tilde(char c) { state = back; if (c == '~') { - producer.Put(TexoStrike()); + ok = producer.Strike(); } else { - producer.Put('~'); + ok = producer.Put('~'); Put(c); } } @@ -418,7 +403,7 @@ void TexoImporterMarkdown::Newline(char c) state = header; header_level = 6; } else if (c == '>') { - producer.Put(TexoQuote()); + ok = producer.Quote(); state = quote_pre; } else if (c == '-') { state = rule; @@ -427,9 +412,9 @@ void TexoImporterMarkdown::Newline(char c) state = code; code_quote_count = 1; } else { - producer.Put('\n'); + ok = producer.Put('\n'); state = text; - Text(c); + Put(c); } } @@ -438,15 +423,15 @@ void TexoImporterMarkdown::Rule(char c) if (c == '-') { ++rule_dash_count; } else if (c == '\n' && rule_dash_count >= 3) { - producer.Put(TexoHorizontalRule()); + ok = producer.PutHorizontalRule(); state = newline; } else { - producer.Put(' '); - for (int i = 0; i < rule_dash_count; ++i) { - producer.Put('-'); + ok = producer.Put(' '); + for (int i = 0; ok && i < rule_dash_count; ++i) { + ok = producer.Put('-'); } state = text; - Text(c); + Put(c); } } @@ -456,19 +441,19 @@ void TexoImporterMarkdown::Paragraph(char c) state = header; header_level = 6; } else if (c == '>') { - producer.Put(TexoQuote()); + ok = producer.Quote(); state = quote_pre; } else if (c == '-') { - producer.Put(TexoParagraph()); + ok = producer.Paragraph(); state = rule; rule_dash_count = 1; } else if (c == '`') { state = code; code_quote_count = 1; } else if (c != '\n') { - producer.Put(TexoParagraph()); + ok = producer.Paragraph(); state = text; - Text(c); + Put(c); } } @@ -478,13 +463,13 @@ void TexoImporterMarkdown::Header(char c) if (header_level > 1) { --header_level; } else { - state = error; + ok = false; } } else if (c == ' ') { - producer.Put(TexoHeader(header_level)); + ok = producer.Header(header_level); state = header_pre; } else { - state = error; + ok = false; } } @@ -502,17 +487,17 @@ void TexoImporterMarkdown::Code(char c) ++code_quote_count; } else if (c == '\n') { if (code_quote_count == 3) { - producer.Put(TexoCode()); + ok = producer.Code(); state = code_text; } else { - state = error; + ok = false; } } else { - state = error; + ok = false; } } void TexoImporterMarkdown::Backquote() { - producer.Put(TexoMono()); + ok = producer.Mono(); } diff --git a/src/markdown.hpp b/src/markdown.hpp index f9b25f4..ee8aee8 100644 --- a/src/markdown.hpp +++ b/src/markdown.hpp @@ -10,33 +10,44 @@ class TexoProducerMarkdown: public TexoProducer { public: TexoProducerMarkdown(TexoExporter &exporter); - void End(); + bool End(); - void Put(const Texo &piece); + bool Put(char c); - void Put(const TexoHeader &piece); - void Put(const TexoParagraph &piece); - void Put(const TexoCode &piece); - void Put(const TexoQuote &piece); + bool Code(); + bool Header(int level); + bool Paragraph(); + bool Quote(); - void Put(const TexoMono &piece); - void Put(const TexoBold &piece); - void Put(const TexoItalic &piece); - void Put(const TexoUnderline &piece); - void Put(const TexoStrike &piece); + bool Bold(); + bool Italic(); + bool Mono(); + bool Strike(); + bool Underline(); - void Put(const TexoImage &piece); - void Put(const TexoLink &piece); - void Put(const TexoHorizontalRule &piece); + bool Link(const ScriptVariable &link, const ScriptVariable &title); + bool Link(); + + bool PutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title + ); + bool PutHorizontalRule(); private: - void Close(); + bool Mod(const ScriptVariable &str); + bool Close(); + bool CloseLink(); bool quoted; bool newline; bool header; bool code; bool nospace; + + ScriptVariable link_link; + ScriptVariable link_title; }; @@ -44,13 +55,13 @@ class TexoImporterMarkdown: public TexoImporter { public: TexoImporterMarkdown(TexoProducer &producer); - void Put(char c); - void Put(const ScriptVariable &str); - void Put(FILE *file); + +protected: + bool TruePut(char c); + private: enum State { - error, start, text, header_text, diff --git a/src/plain.cpp b/src/plain.cpp index 8b3d470..9e9280e 100644 --- a/src/plain.cpp +++ b/src/plain.cpp @@ -1,82 +1,100 @@ #include "plain.hpp" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Plain Producer + */ TexoProducerPlain::TexoProducerPlain(TexoExporter &exporter): TexoProducer(exporter), quoted(false), newline(false), nospace(true) {} -void TexoProducerPlain::End() + +bool TexoProducerPlain::End() { if (!newline) { exporter.Put('\n'); newline = true; } + return true; } -void TexoProducerPlain::Put(const Texo &piece) + +bool TexoProducerPlain::Put(char c) { - if (piece.c == '\n') { + if (c == '\n') { if (quoted) { - exporter.Put("\n> "); + return exporter.Put("\n> "); } else if (!nospace) { if (newline) { - exporter.Put(' '); + return exporter.Put(' '); } else { - exporter.Put('\n'); newline = true; + return exporter.Put('\n'); } + } else { + return true; } } else { - exporter.Put(piece.c); newline = false; nospace = false; + return exporter.Put(c); } } -void TexoProducerPlain::Put(const TexoParagraph &piece) + +bool TexoProducerPlain::Paragraph() { + quoted = false; if (!nospace) { - exporter.Put("\n\n"); + nospace = true; + return exporter.Put("\n\n"); + } else { + return true; } - quoted = false; - nospace = true; } -void TexoProducerPlain::Put(const TexoQuote &piece) +bool TexoProducerPlain::Quote() { + quoted = true; if (!nospace) { - exporter.Put("\n\n"); + return exporter.Put("\n\n> "); + } else { + return exporter.Put("> "); } - exporter.Put("> "); - quoted = true; } -void TexoProducerPlain::Put(const TexoHorizontalRule &piece) +bool TexoProducerPlain::PutHorizontalRule() { + bool ok = true; if (!newline && !nospace) { - exporter.Put('\n'); + ok = exporter.Put('\n'); } - exporter.Put("--------------------------------------------------\n"); nospace = true; + return ok && exporter.Put( + "--------------------------------------------------\n" + ); } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Plain Importer + */ TexoImporterPlain::TexoImporterPlain(TexoProducer &producer): TexoImporter(producer), state(text) -{ - producer.Put(TexoParagraph()); -} +{} + -void TexoImporterPlain::End() +bool TexoImporterPlain::TrueEnd() { if (state == rule) { - producer.Put(TexoHorizontalRule()); + ok = producer.PutHorizontalRule(); state = text; } - producer.End(); + return ok && producer.End(); } -void TexoImporterPlain::Put(char c) + +bool TexoImporterPlain::TruePut(char c) { switch (state) { case text: Text(c); break; @@ -88,23 +106,15 @@ void TexoImporterPlain::Put(char c) case rule: Rule(c); break; case paragraph_rule: ParagraphRule(c); break; } + return ok; } -void TexoImporterPlain::Put(const ScriptVariable &str) -{ - TexoImporter::Put(str); -} - -void TexoImporterPlain::Put(FILE *file) -{ - TexoImporter::Put(file); -} void TexoImporterPlain::Text(char c) { switch (c) { - case '\n': state = newline; break; - default: producer.Put(c); break; + case '\n': state = newline; break; + default: ok = producer.Put(c); break; } } @@ -114,26 +124,30 @@ void TexoImporterPlain::Newline(char c) state = paragraph; } else if (c == '-') { dash_count = 1; - state = rule; + state = rule; } else { - producer.Put('\n'); state = text; - Text(c); + ok = producer.Put('\n'); + if (ok) { + Text(c); + } } } void TexoImporterPlain::Paragraph(char c) { if (c == '>') { - producer.Put(TexoQuote()); + ok = producer.Quote(); state = quote_pre; } else if (c == '-') { dash_count = 1; - state = paragraph_rule; + state = paragraph_rule; } else if (c != '\n') { - producer.Put(TexoParagraph()); state = text; - Text(c); + ok = producer.Paragraph(); + if (ok) { + Text(c); + } } } @@ -148,49 +162,55 @@ void TexoImporterPlain::QuotePre(char c) void TexoImporterPlain::Quote(char c) { switch (c) { - case '\n': state = quote_newline; break; - default: producer.Put(c); break; + case '\n': state = quote_newline; break; + default: ok = producer.Put(c); break; } } void TexoImporterPlain::QuoteNewline(char c) { if (c == '>') { - producer.Put('\n'); + ok = producer.Put('\n'); state = quote_pre; } else if (c == '\n') { state = paragraph; } else if (c == '-') { dash_count = 1; - state = paragraph_rule; + state = paragraph_rule; } else { - producer.Put(TexoParagraph()); state = text; - Text(c); + ok = producer.Paragraph(); + if (ok) { + Text(c); + } } } void TexoImporterPlain::Rule(char c) { if (c == '\n') { - producer.Put(TexoHorizontalRule()); + ok = producer.PutHorizontalRule(); state = text; } else if (c == '-') { ++dash_count; } else { - producer.Put('\n'); - for (;dash_count > 0; --dash_count) { - producer.Put('-'); + ok = producer.Put('\n'); + for (; ok && dash_count > 0; --dash_count) { + ok = producer.Put('-'); } state = text; - Text(c); + if (ok) { + Text(c); + } } } void TexoImporterPlain::ParagraphRule(char c) { if (c == '\n') { - producer.Put(TexoParagraph()); + ok = producer.Paragraph(); + } + if (ok) { + Rule(c); } - Rule(c); } diff --git a/src/plain.hpp b/src/plain.hpp index 13a2c0c..66ee5f1 100644 --- a/src/plain.hpp +++ b/src/plain.hpp @@ -6,18 +6,21 @@ #include "importer.hpp" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Plain Producer + */ class TexoProducerPlain: public TexoProducer { public: TexoProducerPlain(TexoExporter &exporter); - void End(); + bool End(); - void Put(const Texo &piece); + bool Put(char c); - void Put(const TexoParagraph &piece); - void Put(const TexoQuote &piece); + bool Paragraph(); + bool Quote(); - void Put(const TexoHorizontalRule &piece); + bool PutHorizontalRule(); private: bool quoted; @@ -26,15 +29,20 @@ private: }; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Plain Importer + */ class TexoImporterPlain: public TexoImporter { public: TexoImporterPlain(TexoProducer &producer); - void End(); - void Put(char c); - void Put(const ScriptVariable &str); - void Put(FILE *file); +protected: + bool TrueEnd(); + + + bool TruePut(char c); + private: enum State { 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; +} diff --git a/src/producer.hpp b/src/producer.hpp index 62e098d..f55cb91 100644 --- a/src/producer.hpp +++ b/src/producer.hpp @@ -1,37 +1,192 @@ #ifndef TEXO_INCLUDED_PRODUCER #define TEXO_INCLUDED_PRODUCER -#include "texo.hpp" #include "exporter.hpp" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Producer + * Texo interface for producing output based on inner representation. + */ class TexoProducer { public: - TexoProducer(TexoExporter &exporter); + TexoProducer(TexoExporter &exporter); // Setup exporter used for output. - virtual void End(); - virtual void Put(char c); - virtual void Put(const Texo &piece); + virtual bool End(); // Notify producer, what input is ended. - virtual void Put(const TexoHeader &piece); - virtual void Put(const TexoParagraph &piece) = 0; - virtual void Put(const TexoCode &piece); - virtual void Put(const TexoQuote &piece); - virtual void Put(const TexoMono &piece); - virtual void Put(const TexoBold &piece); - virtual void Put(const TexoItalic &piece); - virtual void Put(const TexoUnderline &piece); - virtual void Put(const TexoStrike &piece); + virtual bool Put(char c); // Output c, possibly escaping it. + + + // Block Signal Handlers + // Only one can be opened at one moment. + virtual bool Code(); + virtual bool Header(int level); + virtual bool Paragraph() = 0; + virtual bool Quote(); + + + // Modificator Signal Handlers + // Independently switch one of text modificators. + virtual bool Bold(); + virtual bool Italic(); + virtual bool Mono(); + virtual bool Strike(); + virtual bool Underline(); + + // Switch link to given or switch it off, if no one is given. + virtual bool Link( + const ScriptVariable &link, + const ScriptVariable &title + ); + virtual bool Link(); + + + virtual bool PutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title + ); + virtual bool PutHorizontalRule(); - virtual void Put(const TexoImage &piece); - virtual void Put(const TexoLink &piece); - virtual void Put(const TexoHorizontalRule &piece); protected: TexoExporter &exporter; }; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo Strict Producer + * Converts switch-signal interface of Texo Producer into + * sequence of start/close signals with disjoint modificator sections, + * as well as block sections, which are provided on top level. + */ +class TexoProducerStrict: public TexoProducer { +public: + TexoProducerStrict(TexoExporter &exporter); + + + bool End(); + + + bool Put(char c); + + + bool Code(); + bool Header(int level); + bool Paragraph(); + bool Quote(); + + + bool Bold(); + bool Italic(); + bool Mono(); + bool Strike(); + bool Underline(); + + bool Link(const ScriptVariable &path, const ScriptVariable &title); + bool Link(); + + bool PutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title + ); + bool PutHorizontalRule(); + + +protected: + virtual bool TruePut(char c) = 0; + + virtual bool StartCode() = 0; + virtual bool StartHeader(int level) = 0; + virtual bool StartParagraph() = 0; + virtual bool StartQuote() = 0; + + virtual bool CloseCode() = 0; + virtual bool CloseHeader(int level) = 0; + virtual bool CloseParagraph() = 0; + virtual bool CloseQuote() = 0; + + + virtual bool StartBold() = 0; + virtual bool StartItalic() = 0; + virtual bool StartMono() = 0; + virtual bool StartStrike() = 0; + virtual bool StartUnderline() = 0; + + virtual bool CloseBold() = 0; + virtual bool CloseItalic() = 0; + virtual bool CloseMono() = 0; + virtual bool CloseStrike() = 0; + virtual bool CloseUnderline() = 0; + + virtual bool StartLink( + const ScriptVariable &link, + const ScriptVariable &title + ) = 0; + virtual bool CloseLink( + const ScriptVariable &link, + const ScriptVariable &title + ) = 0; + + + virtual bool TruePutImage( + const ScriptVariable &src, + const ScriptVariable &alt, + const ScriptVariable &title + ) = 0; + virtual bool TruePutHorizontalRule() = 0; + + +private: + enum Block { + block_none = 0, + code, + header, + paragraph, + quote + } block; + + int header_level; + + + enum Mod { + bold, + italic, + link, + mono, + strike, + underline + } mods[6]; + int opened; + + const ScriptVariable *link_link; + const ScriptVariable *link_title; + + + bool Start(); // Open paragraph if no block is opened. + + bool CloseBlock(); + + bool SwitchMod(Mod mod); + + bool OpenMod(Mod mod); + + bool CloseMod(Mod mod); + + // Close all opened mods sequentially, down to (including) last, + // returning count of closed mods, or negative number in case of error. + int CloseMods(Mod last); + + // Close all opened mods. + bool CloseMods(); + + bool Reopen(int closed); + + bool IsOpened(Mod mod) const; +}; + + #endif diff --git a/src/script.cpp b/src/script.cpp new file mode 100644 index 0000000..d335ff0 --- /dev/null +++ b/src/script.cpp @@ -0,0 +1,21 @@ +#include "script.hpp" + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo String Exporter + */ +TexoExporterString::TexoExporterString(ScriptVariable &str): str(str) +{} + + +bool TexoExporterString::Put(char c) +{ + str += c; + return true; +} + +bool TexoExporterString::Put(const ScriptVariable &addon) +{ + str += addon; + return true; +} diff --git a/src/script.hpp b/src/script.hpp new file mode 100644 index 0000000..77f75df --- /dev/null +++ b/src/script.hpp @@ -0,0 +1,25 @@ +#ifndef TEXO_INCLUDED_SCRIPT +#define TEXO_INCLUDED_SCRIPT + +#include "exporter.hpp" + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Texo String Exporter + * Simple utility class to make output into Script Variable, + * which can be easily transformed into C string via c_str method. + */ +class TexoExporterString: public TexoExporter { +public: + TexoExporterString(ScriptVariable &str); + + + bool Put(char c); + bool Put(const ScriptVariable &addon); + + +private: + ScriptVariable &str; +}; + + +#endif diff --git a/src/str.cpp b/src/str.cpp deleted file mode 100644 index 463a8dc..0000000 --- a/src/str.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "str.hpp" - - -TexoExporterString::TexoExporterString(ScriptVariable &str): str(str) -{} - -void TexoExporterString::Put(char c) -{ - str += c; -} - -void TexoExporterString::Put(const ScriptVariable &addon) -{ - str += addon; -} diff --git a/src/str.hpp b/src/str.hpp deleted file mode 100644 index c7cecfc..0000000 --- a/src/str.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TEXO_INCLUDED_STR -#define TEXO_INCLUDED_STR - -#include "exporter.hpp" - - -class TexoExporterString: public TexoExporter { -public: - TexoExporterString(ScriptVariable &str); - - void Put(char c); - void Put(const ScriptVariable &addon); - -private: - ScriptVariable &str; -}; - - -#endif diff --git a/src/texo.cpp b/src/texo.cpp deleted file mode 100644 index 99d74f8..0000000 --- a/src/texo.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "texo.hpp" - - -Texo::Texo(char c): c(c) -{} - -TexoHeader::TexoHeader(int level): level(level) -{} diff --git a/src/texo.hpp b/src/texo.hpp deleted file mode 100644 index b8ae394..0000000 --- a/src/texo.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef TEXO_INCLUDED_TEXO -#define TEXO_INCLUDED_TEXO - -#include - - -struct Texo { - Texo(char c); - char c; -}; - - -/* - * Texo Blocks - */ -struct TexoHeader { - TexoHeader(int level); - int level; // Number >= 1, bigger for bigger. -}; - -struct TexoParagraph {}; - -struct TexoCode {}; - -struct TexoQuote {}; - - -/* - * Texo Decorators - */ -struct TexoMono {}; - -struct TexoBold {}; - -struct TexoItalic {}; - -struct TexoUnderline {}; - -struct TexoStrike {}; - - -/* - * Texo Signals - */ -struct TexoImage { - ScriptVariable path; - ScriptVariable title; - ScriptVariable alt; - ScriptVariable link; -}; - -struct TexoLink { - ScriptVariable text; - ScriptVariable link; - ScriptVariable title; -}; - -struct TexoHorizontalRule {}; - - -#endif -- cgit v1.2.3