summaryrefslogtreecommitdiff
path: root/src/markdown.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/markdown.cpp')
-rw-r--r--src/markdown.cpp261
1 files changed, 211 insertions, 50 deletions
diff --git a/src/markdown.cpp b/src/markdown.cpp
index 0593eb9..fb538fc 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -169,15 +169,19 @@ void TexoProducerMarkdown::Put(const TexoHorizontalRule &piece)
TexoImporterMarkdown::TexoImporterMarkdown(TexoProducer &producer):
- TexoImporter(producer), state(text)
+ TexoImporter(producer), state(start), wrapping_state(error), mod_pos(-1)
{}
TexoImporterMarkdown::~TexoImporterMarkdown()
-{}
+{
+ EndBlock();
+}
void TexoImporterMarkdown::Put(char c)
{
switch (state) {
+ case error: break;
+ case start: Start(c); break;
case text: Text(c); break;
case header_text: HeaderText(c); break;
case quote_text: QuoteText(c); break;
@@ -191,10 +195,10 @@ void TexoImporterMarkdown::Put(char c)
case plus: Plus(c); break;
case tilde: Tilde(c); break;
case newline: Newline(c); break;
+ case rule: Rule(c); break;
case paragraph: Paragraph(c); break;
case header: Header(c); break;
case code: Code(c); break;
- case quote: Quote(c); break;
}
}
@@ -208,14 +212,36 @@ void TexoImporterMarkdown::Put(FILE *file)
TexoImporter::Put(file);
}
+void TexoImporterMarkdown::Start(char c)
+{
+ if (c == '\n') {
+ state = paragraph;
+ } else if (c == '#') {
+ state = header;
+ header_level = 6;
+ } else if (c == '>') {
+ BlockState(quote_text);
+ } else if (c == '-') {
+ BlockState(text);
+ state = rule;
+ rule_dash_count = 1;
+ } else if (c == '`') {
+ state = code;
+ code_quote_count = 1;
+ } else {
+ BlockState(text);
+ Put(c);
+ }
+}
+
void TexoImporterMarkdown::Text(char c)
{
- wrapping_state = 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);
@@ -224,12 +250,12 @@ void TexoImporterMarkdown::Text(char c)
void TexoImporterMarkdown::HeaderText(char c)
{
- wrapping_state = header_text;
switch (c) {
case '\\': state = backslash; break;
- case '\n': EndHeader(); 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);
@@ -238,22 +264,69 @@ void TexoImporterMarkdown::HeaderText(char c)
void TexoImporterMarkdown::QuoteText(char c)
{
- wrapping_state = header_text;
switch (c) {
case '\\': state = backslash; break;
case '\n': state = quote_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);
}
}
-void TexoImporterMarkdown::QuoteNewline(char c);
-void TexoImporterMarkdown::CodeText(char c);
-void TexoImporterMarkdown::CodeNewline(char c);
-void TexoImporterMarkdown::CodeEnd(char c);
+void TexoImporterMarkdown::QuoteNewline(char c)
+{
+ if (c == '>') {
+ state = quote_text;
+ } else {
+ state = paragraph;
+ Put(c);
+ }
+}
+
+void TexoImporterMarkdown::CodeText(char c)
+{
+ 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);
+ }
+}
+
+void TexoImporterMarkdown::CodeNewline(char c)
+{
+ if (c == '`') {
+ state = code_end;
+ code_quote_count = 1;
+ } else {
+ producer.Put('\n');
+ state = code_text;
+ Put(c);
+ }
+}
+
+void TexoImporterMarkdown::CodeEnd(char c)
+{
+ if (c == '`') {
+ ++code_quote_count;
+ } else if (c == '\n') {
+ if (code_quote_count == 3) {
+ state = paragraph;
+ Put(c);
+ } else {
+ state = error;
+ }
+ } else {
+ state = error;
+ }
+}
void TexoImporterMarkdown::Backslash(char c)
{
@@ -265,12 +338,18 @@ void TexoImporterMarkdown::Asterisk(char c)
{
state = wrapping_state;
if (c == '*') {
- producer.Put(TexoBold(is_bold));
- is_bold = !is_bold;
+ if (CheckMods(bold)) {
+ producer.Put(TexoBold(Mod(bold)));
+ } else {
+ state = error;
+ }
} else {
- producer.Put(TexoItalic(is_italic));
- is_italic = !is_italic;
- Put(c);
+ if (CheckMods(italic)) {
+ producer.Put(TexoItalic(Mod(italic)));
+ Put(c);
+ } else {
+ state = error;
+ }
}
}
@@ -278,12 +357,18 @@ void TexoImporterMarkdown::Underline(char c)
{
state = wrapping_state;
if (c == '_') {
- producer.Put(TexoBold(is_bold));
- is_bold = !is_bold;
+ if (CheckMods(bold)) {
+ producer.Put(TexoBold(Mod(bold)));
+ } else {
+ state = error;
+ }
} else {
- producer.Put(TexoItalic(is_italic));
- is_italic = !is_italic;
- Put(c);
+ if (CheckMods(italic)) {
+ producer.Put(TexoItalic(Mod(italic)));
+ Put(c);
+ } else {
+ state = error;
+ }
}
}
@@ -291,8 +376,11 @@ void TexoImporterMarkdown::Plus(char c)
{
state = wrapping_state;
if (c == '+') {
- producer.Put(TexoUnderline(is_underline));
- is_underline = !is_underline;
+ if (CheckMods(underlined)) {
+ producer.Put(TexoUnderline(Mod(underlined)));
+ } else {
+ state = error;
+ }
} else {
producer.Put('+');
Put(c);
@@ -303,20 +391,17 @@ void TexoImporterMarkdown::Tilde(char c)
{
state = wrapping_state;
if (c == '~') {
- producer.Put(TexoStrike(is_strike));
- is_strike = !is_strike;
+ if (CheckMods(strike)) {
+ producer.Put(TexoStrike(Mod(strike)));
+ } else {
+ state = error;
+ }
} else {
producer.Put('~');
Put(c);
}
}
-void TexoImporterMarkdown::Backquote()
-{
- producer.Put(TexoMono(is_mono));
- is_mono = !is_mono;
-}
-
void TexoImporterMarkdown::Newline(char c)
{
if (c == '\n') {
@@ -325,7 +410,7 @@ void TexoImporterMarkdown::Newline(char c)
state = header;
header_level = 6;
} else if (c == '>') {
- state = quote;
+ BlockState(quote_text);
} else if (c == '-') {
state = rule;
rule_dash_count = 1;
@@ -343,37 +428,35 @@ void TexoImporterMarkdown::Rule(char c)
{
if (c == '-') {
++rule_dash_count;
+ } else if (c == '\n' && rule_dash_count >= 3) {
+ producer.Put(TexoHorizontalRule());
+ state = newline;
} else {
- if (rule_dash_count >= 3) {
- producer.Put(TexoHorizontalRule());
- } else {
- if (wrapping_state == paragraph) {
- producer.Put(TexoParagraph());
- }
- for (int i = 0; i < rule_dash_count; ++i) {
- producer.Put('-');
- }
+ producer.Put(' ');
+ for (int i = 0; i < rule_dash_count; ++i) {
+ producer.Put('-');
}
+ state = wrapping_state;
+ Put(c);
}
}
void TexoImporterMarkdown::Paragraph(char c)
{
- wrapping_state = paragraph;
if (c == '#') {
state = header;
header_level = 6;
} else if (c == '>') {
- state = quote;
+ BlockState(quote_text);
} else if (c == '-') {
+ BlockState(text);
state = rule;
rule_dash_count = 1;
} else if (c == '`') {
state = code;
code_quote_count = 1;
} else {
- producer.Put(TexoParagraph());
- state = text;
+ BlockState(text);
Put(c);
}
}
@@ -383,15 +466,93 @@ void TexoImporterMarkdown::Header(char c)
if (c == '#') {
if (header_level > 1) {
--header_level;
+ } else {
+ state = error;
}
} else {
- producer.Put(TexoHeader(header_level));
- state = header_text;
+ BlockState(header_text);
+ header_level_last = header_level;
+ Put(c);
}
}
-void TexoImporterMarkdown::EndHeader()
+void TexoImporterMarkdown::Code(char c)
{
- producer.Put(TexoHeader(header_level, true));
- state = paragraph;
+ if (c == '`') {
+ ++code_quote_count;
+ } else if (c == '\n') {
+ if (code_quote_count == 3) {
+ BlockState(code_text);
+ } else {
+ state = error;
+ }
+ } else {
+ state = error;
+ }
+}
+
+void TexoImporterMarkdown::Backquote()
+{
+ if (CheckMods(mono)) {
+ producer.Put(TexoMono(Mod(mono)));
+ } else {
+ state = error;
+ }
+}
+
+bool TexoImporterMarkdown::CheckMods(Modificator mod)
+{
+ bool ok = true;
+ for (int i = 0; ok && i < mod_pos; ++i) {
+ ok = mods[i] != mod;
+ }
+ return ok;
+}
+
+bool TexoImporterMarkdown::Mod(Modificator mod)
+{
+ if (mod_pos == -1 || mods[mod_pos] != mod) {
+ ++mod_pos;
+ mods[mod_pos] = mod;
+ return false;
+ }
+ --mod_pos;
+ return true;
+}
+
+void TexoImporterMarkdown::BlockState(State st)
+{
+ if (mod_pos == -1) {
+ state = st;
+ EndBlock();
+ if (st == text) {
+ producer.Put(TexoParagraph());
+ } else if (st == quote_text) {
+ producer.Put(TexoQuote());
+ } else if (st == code_text) {
+ producer.Put(TexoCode());
+ } else if (st == header_text) {
+ producer.Put(TexoHeader(header_level));
+ } else {
+ state = error;
+ }
+ wrapping_state = st;
+ } else {
+ state = error;
+ }
+}
+
+void TexoImporterMarkdown::EndBlock()
+{
+ if (wrapping_state == text) {
+ producer.Put(TexoParagraph(true));
+ } else if (wrapping_state == quote_text) {
+ producer.Put(TexoQuote(true));
+ } else if (wrapping_state == code_text) {
+ producer.Put(TexoCode(true));
+ } else if (wrapping_state == header_text) {
+ producer.Put(TexoHeader(header_level_last, true));
+ } else if (wrapping_state != error) {
+ state = error;
+ }
}