1#[macro_use]
2use crate::*;
3
4#[cfg(not(feature = "no-std"))] use core::fmt;
5#[cfg(feature = "no-std")] use alloc::fmt;
6#[cfg(feature = "no-std")] use alloc::string::String;
7#[cfg(feature = "no-std")] use alloc::vec::Vec;
8use nom::{
9 IResult,
10 branch::alt,
11 sequence::tuple as nom_tuple,
12 combinator::{opt, eof, peek},
13 multi::{many1, many_till, many0, separated_list1,separated_list0},
14 bytes::complete::{take_until, take_while},
15 Err,
16 Err::Failure
17};
18
19use std::collections::HashMap;
20use colored::*;
21
22use crate::*;
23
24pub fn title(input: ParseString) -> ParseResult<Title> {
29 let (input, mut text) = many1(text)(input)?;
30 let (input, _) = new_line(input)?;
31 let (input, _) = many1(equal)(input)?;
32 let (input, _) = many0(space_tab)(input)?;
33 let (input, _) = new_line(input)?;
34 let (input, _) = many0(space_tab)(input)?;
35 let (input, _) = whitespace0(input)?;
36 let mut title = Token::merge_tokens(&mut text).unwrap();
37 title.kind = TokenKind::Title;
38 Ok((input, Title{text: title}))
39}
40
41pub struct MarkdownTableHeader {
42 pub header: Vec<(Token, Token)>,
43}
44
45pub fn no_alignment(input: ParseString) -> ParseResult<ColumnAlignment> {
46 let (input, _) = many1(dash)(input)?;
47 Ok((input, ColumnAlignment::Left))
48}
49
50pub fn left_alignment(input: ParseString) -> ParseResult<ColumnAlignment> {
51 let (input, _) = colon(input)?;
52 let (input, _) = many1(dash)(input)?;
53 Ok((input, ColumnAlignment::Left))
54}
55
56pub fn right_alignment(input: ParseString) -> ParseResult<ColumnAlignment> {
57 let (input, _) = many1(dash)(input)?;
58 let (input, _) = colon(input)?;
59 Ok((input, ColumnAlignment::Right))
60}
61
62pub fn center_alignment(input: ParseString) -> ParseResult<ColumnAlignment> {
63 let (input, _) = colon(input)?;
64 let (input, _) = many1(dash)(input)?;
65 let (input, _) = colon(input)?;
66 Ok((input, ColumnAlignment::Center))
67}
68
69pub fn alignment_separator(input: ParseString) -> ParseResult<ColumnAlignment> {
70 let (input, _) = many0(space_tab)(input)?;
71 let (input, separator) = alt((center_alignment, left_alignment, right_alignment, no_alignment))(input)?;
72 let (input, _) = many0(space_tab)(input)?;
73 Ok((input, separator))
74}
75
76pub fn markdown_table(input: ParseString) -> ParseResult<MarkdownTable> {
77 let (input, _) = whitespace0(input)?;
78 let (input, table) = alt((markdown_table_with_header, markdown_table_no_header))(input)?;
79 Ok((input, table))
80}
81
82pub fn markdown_table_with_header(input: ParseString) -> ParseResult<MarkdownTable> {
83 let (input, (header,alignment)) = markdown_table_header(input)?;
84 let (input, rows) = many1(markdown_table_row)(input)?;
85 Ok((input, MarkdownTable{header, rows, alignment}))
86}
87
88pub fn markdown_table_no_header(input: ParseString) -> ParseResult<MarkdownTable> {
89 let (input, rows) = many1(markdown_table_row)(input)?;
90 let header = vec![];
91 let alignment = vec![];
92 Ok((input, MarkdownTable{header, rows, alignment}))
93}
94
95pub fn markdown_table_header(input: ParseString) -> ParseResult<(Vec<Paragraph>,Vec<ColumnAlignment>)> {
96 let (input, _) = whitespace0(input)?;
97 let (input, header) = many1(tuple((bar, tuple((many0(space_tab), paragraph)))))(input)?;
98 let (input, _) = bar(input)?;
99 let (input, _) = whitespace0(input)?;
100 let (input, alignment) = many1(tuple((bar, tuple((many0(space_tab), alignment_separator)))))(input)?;
101 let (input, _) = bar(input)?;
102 let (input, _) = whitespace0(input)?;
103 let column_names: Vec<Paragraph> = header.into_iter().map(|(_,(_,tkn))| tkn).collect();
104 let column_alignments = alignment.into_iter().map(|(_,(_,tkn))| tkn).collect();
105 Ok((input, (column_names,column_alignments)))
106}
107
108pub fn empty_paragraph(input: ParseString) -> ParseResult<Paragraph> {
109 Ok((input, Paragraph{elements: vec![]}))
110}
111
112pub fn markdown_table_row(input: ParseString) -> ParseResult<Vec<Paragraph>> {
114 let (input, _) = whitespace0(input)?;
115 let (input, _) = bar(input)?;
116 let (input, row) = many1(tuple((alt((tuple((many0(space_tab), paragraph)),tuple((many1(space_tab), empty_paragraph)))),bar)))(input)?;
117 let (input, _) = whitespace0(input)?;
118 let row = row.into_iter().map(|((_,tkn),_)| tkn).collect();
119 Ok((input, row))
120}
121
122pub fn ul_subtitle(input: ParseString) -> ParseResult<Subtitle> {
124 let (input, _) = many1(digit_token)(input)?;
125 let (input, _) = period(input)?;
126 let (input, _) = many0(space)(input)?;
127 let (input, text) = paragraph(input)?;
128 let (input, _) = new_line(input)?;
129 let (input, _) = many1(dash)(input)?;
130 let (input, _) = many0(space_tab)(input)?;
131 let (input, _) = new_line(input)?;
132 let (input, _) = many0(space_tab)(input)?;
133 let (input, _) = whitespace0(input)?;
134 Ok((input, Subtitle{text, level: 2}))
135}
136
137pub fn subtitle(input: ParseString) -> ParseResult<Subtitle> {
139 let (input, _) = many0(space_tab)(input)?;
140 let (input, _) = left_parenthesis(input)?;
141 let (input, num) = separated_list1(period,alt((many1(alpha),many1(digit))))(input)?;
142 let (input, _) = right_parenthesis(input)?;
143 let (input, _) = many0(space_tab)(input)?;
144 let (input, text) = paragraph(input)?;
145 let (input, _) = many0(space_tab)(input)?;
146 let (input, _) = whitespace0(input)?;
147 let level: u8 = if num.len() < 3 { 3 } else { num.len() as u8 + 1 };
148 Ok((input, Subtitle{text, level}))
149}
150
151pub fn strong(input: ParseString) -> ParseResult<ParagraphElement> {
153 let (input, _) = tuple((asterisk,asterisk))(input)?;
154 let (input, text) = paragraph_element(input)?;
155 let (input, _) = tuple((asterisk,asterisk))(input)?;
156 Ok((input, ParagraphElement::Strong(Box::new(text))))
157}
158
159pub fn emphasis(input: ParseString) -> ParseResult<ParagraphElement> {
161 let (input, _) = asterisk(input)?;
162 let (input, text) = paragraph_element(input)?;
163 let (input, _) = asterisk(input)?;
164 Ok((input, ParagraphElement::Emphasis(Box::new(text))))
165}
166
167pub fn strikethrough(input: ParseString) -> ParseResult<ParagraphElement> {
169 let (input, _) = tilde(input)?;
170 let (input, text) = paragraph_element(input)?;
171 let (input, _) = tilde(input)?;
172 Ok((input, ParagraphElement::Strikethrough(Box::new(text))))
173}
174
175pub fn underline(input: ParseString) -> ParseResult<ParagraphElement> {
177 let (input, _) = underscore(input)?;
178 let (input, text) = paragraph_element(input)?;
179 let (input, _) = underscore(input)?;
180 Ok((input, ParagraphElement::Underline(Box::new(text))))
181}
182
183pub fn highlight(input: ParseString) -> ParseResult<ParagraphElement> {
185 let (input, _) = highlight_sigil(input)?;
186 let (input, text) = paragraph_element(input)?;
187 let (input, _) = highlight_sigil(input)?;
188 Ok((input, ParagraphElement::Highlight(Box::new(text))))
189}
190
191pub fn inline_code(input: ParseString) -> ParseResult<ParagraphElement> {
193 let (input, _) = grave(input)?;
194 let (input, text) = many0(tuple((is_not(grave),text)))(input)?;
195 let (input, _) = grave(input)?;
196 let mut text = text.into_iter().map(|(_,tkn)| tkn).collect();
197 let mut text = match Token::merge_tokens(&mut text) {
199 Some(t) => t,
200 None => {
201 return Ok((input, ParagraphElement::InlineCode(Token::default())));
202 }
203 };
204 text.kind = TokenKind::Text;
205 Ok((input, ParagraphElement::InlineCode(text)))
206}
207
208pub fn inline_equation(input: ParseString) -> ParseResult<ParagraphElement> {
210 let (input, _) = equation_sigil(input)?;
211 let (input, txt) = many0(tuple((is_not(equation_sigil),alt((backslash,text)))))(input)?;
212 let (input, _) = equation_sigil(input)?;
213 let mut txt = txt.into_iter().map(|(_,tkn)| tkn).collect();
214 let mut eqn = Token::merge_tokens(&mut txt).unwrap();
215 eqn.kind = TokenKind::Text;
216 Ok((input, ParagraphElement::InlineEquation(eqn)))
217}
218
219pub fn hyperlink(input: ParseString) -> ParseResult<ParagraphElement> {
221 let (input, _) = left_bracket(input)?;
222 let (input, link_text) = many1(tuple((is_not(right_bracket),text)))(input)?;
223 let (input, _) = right_bracket(input)?;
224 let (input, _) = left_parenthesis(input)?;
225 let (input, link) = many1(tuple((is_not(right_parenthesis),text)))(input)?;
226 let (input, _) = right_parenthesis(input)?;
227 let mut tokens = link.into_iter().map(|(_,tkn)| tkn).collect::<Vec<Token>>();
228 let link_merged = Token::merge_tokens(&mut tokens).unwrap();
229 let mut tokens = link_text.into_iter().map(|(_,tkn)| tkn).collect::<Vec<Token>>();
230 let text_merged = Token::merge_tokens(&mut tokens).unwrap();
231 Ok((input, ParagraphElement::Hyperlink((text_merged, link_merged))))
232}
233
234pub fn raw_hyperlink(input: ParseString) -> ParseResult<ParagraphElement> {
236 let (input, _) = peek(http_prefix)(input)?;
237 let (input, address) = many1(tuple((is_not(space), text)))(input)?;
238 let mut tokens = address.into_iter().map(|(_,tkn)| tkn).collect::<Vec<Token>>();
239 let url = Token::merge_tokens(&mut tokens).unwrap();
240 Ok((input, ParagraphElement::Hyperlink((url.clone(), url))))
241}
242
243pub fn img(input: ParseString) -> ParseResult<Image> {
245 let (input, _) = img_prefix(input)?;
246 let (input, caption_text) = paragraph(input)?;
247 let (input, _) = right_bracket(input)?;
248 let (input, _) = left_parenthesis(input)?;
249 let (input, src) = many1(tuple((is_not(right_parenthesis),text)))(input)?;
250 let (input, _) = right_parenthesis(input)?;
251 let merged_src = Token::merge_tokens(&mut src.into_iter().map(|(_,tkn)| tkn).collect::<Vec<Token>>()).unwrap();
252 Ok((input, Image{src: merged_src, caption: Some(caption_text)} ))
253}
254
255pub fn paragraph_text(input: ParseString) -> ParseResult<ParagraphElement> {
257 let (input, elements) = match many1(nom_tuple((is_not(alt((footnote_prefix, highlight_sigil, equation_sigil, img_prefix, http_prefix, left_brace, left_bracket, left_angle, right_bracket, tilde, asterisk, underscore, grave, define_operator, bar))),text)))(input) {
258 Ok((input, mut text)) => {
259 let mut text = text.into_iter().map(|(_,tkn)| tkn).collect();
260 let mut text = Token::merge_tokens(&mut text).unwrap();
261 text.kind = TokenKind::Text;
262 (input, ParagraphElement::Text(text))
263 },
264 Err(err) => {return Err(err);},
265 };
266 Ok((input, elements))
267}
268
269pub fn eval_inline_mech_code(input: ParseString) -> ParseResult<ParagraphElement> {
271 let (input, _) = left_brace(input)?;
272 let (input, expr) = expression(input)?;
273 let (input, _) = right_brace(input)?;
274 Ok((input, ParagraphElement::EvalInlineMechCode(expr)))
275}
276
277pub fn inline_mech_code(input: ParseString) -> ParseResult<ParagraphElement> {
279 let (input, _) = left_brace(input)?;
280 let (input, _) = left_brace(input)?;
281 let (input, expr) = mech_code_alt(input)?;
282 let (input, _) = right_brace(input)?;
283 let (input, _) = right_brace(input)?;
284 Ok((input, ParagraphElement::InlineMechCode(expr)))
285}
286
287pub fn footnote_reference(input: ParseString) -> ParseResult<ParagraphElement> {
289 let (input, _) = footnote_prefix(input)?;
290 let (input, text) = many1(tuple((is_not(right_bracket),text)))(input)?;
291 let (input, _) = right_bracket(input)?;
292 let mut tokens = text.into_iter().map(|(_,tkn)| tkn).collect::<Vec<Token>>();
293 let footnote_text = Token::merge_tokens(&mut tokens).unwrap();
294 Ok((input, ParagraphElement::FootnoteReference(footnote_text)))
295}
296
297pub fn reference(input: ParseString) -> ParseResult<ParagraphElement> {
299 let (input, _) = left_bracket(input)?;
300 let (input, mut txt) = many1(alphanumeric)(input)?;
301 let (input, _) = right_bracket(input)?;
302 let ref_text = Token::merge_tokens(&mut txt).unwrap();
303 Ok((input, ParagraphElement::Reference(ref_text)))
304}
305
306pub fn paragraph_element(input: ParseString) -> ParseResult<ParagraphElement> {
308 alt((hyperlink, reference, raw_hyperlink, highlight, footnote_reference, inline_mech_code, eval_inline_mech_code, inline_equation, paragraph_text, strong, highlight, emphasis, inline_code, strikethrough, underline))(input)
309}
310
311pub fn paragraph(input: ParseString) -> ParseResult<Paragraph> {
313 let (input, elements) = many1(paragraph_element)(input)?;
314 Ok((input, Paragraph{elements}))
315}
316
317pub fn ordered_list_item(input: ParseString) -> ParseResult<(Number,Paragraph)> {
319 let (input, number) = number(input)?;
320 let (input, _) = period(input)?;
321 let (input, list_item) = paragraph(input)?;
322 let (input, _) = new_line(input)?;
323 Ok((input, (number,list_item)))
324}
325
326pub fn checked_item(input: ParseString) -> ParseResult<(bool,Paragraph)> {
328 let (input, _) = dash(input)?;
329 let (input, _) = left_bracket(input)?;
330 let (input, _) = alt((tag("x"),tag("✓"),tag("✗")))(input)?;
331 let (input, _) = right_bracket(input)?;
332 let (input, list_item) = paragraph(input)?;
333 let (input, _) = new_line(input)?;
334 Ok((input, (true,list_item)))
335}
336
337pub fn unchecked_item(input: ParseString) -> ParseResult<(bool,Paragraph)> {
339 let (input, _) = dash(input)?;
340 let (input, _) = left_bracket(input)?;
341 let (input, _) = whitespace0(input)?;
342 let (input, _) = right_bracket(input)?;
343 let (input, list_item) = paragraph(input)?;
344 let (input, _) = new_line(input)?;
345 Ok((input, (false,list_item)))
346}
347
348pub fn check_list_item(input: ParseString) -> ParseResult<(bool,Paragraph)> {
350 let (input, item) = alt((checked_item, unchecked_item))(input)?;
351 Ok((input, item))
352}
353
354pub fn check_list(mut input: ParseString, level: usize) -> ParseResult<MDList> {
355 let mut items = vec![];
356 loop {
357 let mut indent = 0;
359 let mut current = input.peek(indent);
360 while current == Some(" ") || current == Some("\t") {
361 indent += 1;
362 current = input.peek(indent);
363 }
364 if indent < level {
366 break;
367 }
368 let (next_input, _) = many0(space_tab)(input.clone())?;
370 let (next_input, list_item) = match check_list_item(next_input.clone()) {
372 Ok((next_input, list_item)) => (next_input, list_item),
373 Err(err) => {
374 if !items.is_empty() {
375 break;
376 } else {
377 return Err(err);
378 }
379 }
380 };
381 let mut lookahead_indent = 0;
383 let mut current = next_input.peek(lookahead_indent);
384 while current == Some(" ") || current == Some("\t") {
385 lookahead_indent += 1;
386 current = next_input.peek(lookahead_indent);
387 }
388 input = next_input;
389 if lookahead_indent < level {
390 items.push((list_item, None));
392 break;
393 } else if lookahead_indent == level {
394 items.push((list_item, None));
396 continue;
397 } else {
398 let (next_input, sublist_md) = sublist(input.clone(), lookahead_indent)?;
400 items.push((list_item, Some(sublist_md)));
401 input = next_input;
402 }
403 }
404 Ok((input, MDList::Check(items)))
405}
406
407
408pub fn unordered_list(mut input: ParseString, level: usize) -> ParseResult<MDList> {
410 let mut items = vec![];
411 loop {
412 let mut indent = 0;
413 let mut current = input.peek(indent);
414 while current == Some(" ") || current == Some("\t") {
415 indent += 1;
416 current = input.peek(indent);
417 }
418 if indent < level {
420 return Ok((input, MDList::Unordered(items)));
421 }
422 let (next_input, _) = many0(space_tab)(input.clone())?;
423 let (next_input, list_item) = match unordered_list_item(next_input.clone()) {
425 Ok((next_input, list_item)) => (next_input, list_item),
426 Err(err) => {
427 if !items.is_empty() {
428 return Ok((input, MDList::Unordered(items)));
429 } else {
430 return Err(err);
431 }
432 }
433 };
434 let mut lookahead_indent = 0;
436 let mut current = next_input.peek(lookahead_indent);
437 while current == Some(" ") || current == Some("\t") {
438 lookahead_indent += 1;
439 current = next_input.peek(lookahead_indent);
440 }
441 input = next_input;
442 if lookahead_indent < level {
443 items.push((list_item, None));
445 return Ok((input, MDList::Unordered(items)));
446 } else if lookahead_indent == level {
447 items.push((list_item, None));
449 continue;
450 } else {
451 let (next_input, sub) = sublist(input.clone(), lookahead_indent)?;
453 items.push((list_item, Some(sub)));
454 input = next_input;
455 }
456 }
457}
458
459pub fn ordered_list(mut input: ParseString, level: usize) -> ParseResult<MDList> {
461 let mut items = vec![];
462 loop {
463 let mut indent = 0;
464 let mut current = input.peek(indent);
465 while current == Some(" ") || current == Some("\t") {
466 indent += 1;
467 current = input.peek(indent);
468 }
469 if indent < level {
471 let start = items.first()
472 .map(|item: &((Number, Paragraph), Option<MDList>)| item.0.0.clone())
473 .unwrap_or(Number::from_integer(1));
474 return Ok((input, MDList::Ordered(OrderedList { start, items })));
475 }
476 let (next_input, _) = many0(space_tab)(input.clone())?;
478 let (next_input, (list_item, _)) = match tuple((ordered_list_item, is_not(tuple((dash, dash)))))(next_input.clone()) {
480 Ok((next_input, res)) => (next_input, res),
481 Err(err) => {
482 if !items.is_empty() {
483 let start = items.first()
484 .map(|((number, _), _)| number.clone())
485 .unwrap_or(Number::from_integer(1));
486 return Ok((input, MDList::Ordered(OrderedList { start, items })));
487 } else {
488 return Err(err);
489 }
490 }
491 };
492
493 let mut lookahead_indent = 0;
495 let mut current = next_input.peek(lookahead_indent);
496 while current == Some(" ") || current == Some("\t") {
497 lookahead_indent += 1;
498 current = next_input.peek(lookahead_indent);
499 }
500
501 input = next_input;
502
503 if lookahead_indent < level {
504 items.push((list_item, None));
505 let start = items.first()
506 .map(|((number, _), _)| number.clone())
507 .unwrap_or(Number::from_integer(1));
508 return Ok((input, MDList::Ordered(OrderedList { start, items })));
509 } else if lookahead_indent == level {
510 items.push((list_item, None));
511 continue;
512 } else {
513 let (next_input, sub) = sublist(input.clone(), lookahead_indent)?;
515 items.push((list_item, Some(sub)));
516 input = next_input;
517 }
518 }
519}
520
521
522
523pub fn sublist(input: ParseString, level: usize) -> ParseResult<MDList> {
524 let (input, list) = match ordered_list(input.clone(), level) {
525 Ok((input, list)) => (input, list),
526 _ => match check_list(input.clone(), level) {
527 Ok((input, list)) => (input, list),
528 _ => match unordered_list(input.clone(), level) {
529 Ok((input, list)) => (input, list),
530 Err(err) => { return Err(err); }
531 }
532 }
533 };
534 Ok((input, list))
535}
536
537pub fn mechdown_list(input: ParseString) -> ParseResult<MDList> {
539 let (input, list) = match ordered_list(input.clone(), 0) {
540 Ok((input, list)) => (input, list),
541 _ => match check_list(input.clone(), 0) {
542 Ok((input, list)) => (input, list),
543 _ => match unordered_list(input.clone(), 0) {
544 Ok((input, list)) => (input, list),
545 Err(err) => { return Err(err); }
546 }
547 }
548 };
549 Ok((input, list))
550}
551
552pub fn unordered_list_item(input: ParseString) -> ParseResult<(Option<Token>,Paragraph)> {
554 let msg1 = "Expects space after dash";
555 let msg2 = "Expects paragraph as list item";
556 let (input, _) = dash(input)?;
557 let (input, bullet) = opt(tuple((left_parenthesis, emoji, right_parenthesis)))(input)?;
558 let (input, _) = labelr!(null(many1(space)), skip_nil, msg1)(input)?;
559 let (input, list_item) = label!(paragraph, msg2)(input)?;
560 let (input, _) = many0(new_line)(input)?;
561 let bullet = match bullet {
562 Some((_,b,_)) => Some(b),
563 None => None,
564 };
565 Ok((input, (bullet, list_item)))
566}
567
568
569pub fn skip_till_eol(input: ParseString) -> ParseResult<()> {
570
571 Ok((input, ()))
572}
573
574pub fn code_block(input: ParseString) -> ParseResult<SectionElement> {
576 let msg1 = "Expects 3 graves to start a code block";
577 let msg2 = "Expects new_line";
578 let msg3 = "Expects 3 graves followed by new_line to terminate a code block";
579 let (input, (_, r)) = range(nom_tuple((
580 grave,
581 label!(grave, msg1),
582 label!(grave, msg1),
583 )))(input)?;
584 let (input, code_id) = many0(text)(input)?;
585 let (input, _) = label!(new_line, msg2)(input)?;
586 let (input, (text,src_range)) = range(many0(nom_tuple((
587 is_not(nom_tuple((grave, grave, grave))),
588 any,
589 ))))(input)?;
590 let (input, _) = nom_tuple((grave, grave, grave))(input)?;
591 let (input, _) = many0(space_tab)(input)?;
592 let (input, _) = new_line(input)?;
593 let block_src: Vec<char> = text.into_iter().flat_map(|(_, s)| s.chars().collect::<Vec<char>>()).collect();
594 let code_token = Token::new(TokenKind::CodeBlock, src_range, block_src.clone());
595
596 let code_id = code_id.iter().flat_map(|tkn| tkn.chars.clone().into_iter().collect::<Vec<char>>()).collect::<String>();
597 match code_id.as_str() {
598 "ebnf" => {
599 let ebnf_text = block_src.iter().collect::<String>();
600 match parse_grammar(&ebnf_text) {
601 Ok(grammar_tree) => {return Ok((input, SectionElement::Grammar(grammar_tree)));},
602 Err(err) => {
603 println!("Error parsing EBNF grammar: {:?}", err);
604 todo!();
605 }
606 }
607 }
608 tag => {
609 if tag.starts_with("mech") || tag.starts_with("mec") || tag.starts_with("🤖") {
611
612 let rest = tag.trim_start_matches("mech").trim_start_matches("mec").trim_start_matches("🤖").trim_start_matches(":");
614
615 let config = if rest == "" {BlockConfig { namespace: 0, disabled: false}}
616 else if rest == "disabled" { BlockConfig { namespace: hash_str(rest), disabled: true }}
617 else { BlockConfig { namespace: hash_str(rest), disabled: false} };
618
619 let mech_src = block_src.iter().collect::<String>();
620 let graphemes = graphemes::init_source(&mech_src);
621 let parse_string = ParseString::new(&graphemes);
622
623 match many1(mech_code)(parse_string) {
624 Ok((_, mech_tree)) => {
625 return Ok((input, SectionElement::FencedMechCode((mech_tree,config))));
627 },
628 Err(err) => {
629 println!("Error parsing Mech code: {:?}", err);
630 todo!();
631 }
632 };
633 } else if tag.starts_with("equation") || tag.starts_with("eq") || tag.starts_with("math") || tag.starts_with("latex") || tag.starts_with("tex") {
634 return Ok((input, SectionElement::Equation(code_token)));
635 } else if tag.starts_with("diagram") || tag.starts_with("chart") || tag.starts_with("mermaid") {
636 return Ok((input, SectionElement::Diagram(code_token)));
637 } else {
638 }
640 }
641 }
642 Ok((input, SectionElement::CodeBlock(code_token)))
643}
644
645pub fn thematic_break(input: ParseString) -> ParseResult<SectionElement> {
646 let (input, _) = many1(asterisk)(input)?;
647 let (input, _) = many0(space_tab)(input)?;
648 let (input, _) = new_line(input)?;
649 Ok((input, SectionElement::ThematicBreak))
650}
651
652pub fn footnote(input: ParseString) -> ParseResult<Footnote> {
654 let (input, _) = footnote_prefix(input)?;
655 let (input, text) = many1(tuple((is_not(right_bracket),text)))(input)?;
656 let (input, _) = right_bracket(input)?;
657 let (input, _) = colon(input)?;
658 let (input, _) = whitespace0(input)?;
659 let (input, paragraph) = paragraph(input)?;
660 let mut tokens = text.into_iter().map(|(_,tkn)| tkn).collect::<Vec<Token>>();
661 let footnote_text = Token::merge_tokens(&mut tokens).unwrap();
662 let footnote = (footnote_text, paragraph);
663 Ok((input, footnote))
664}
665
666pub fn blank_line(input: ParseString) -> ParseResult<Vec<Token>> {
667 let (input, mut st) = many0(space_tab)(input)?;
668 let (input, n) = new_line(input)?;
669 st.push(n);
670 Ok((input, st))
671}
672
673pub fn question_block(input: ParseString) -> ParseResult<SectionElement> {
674 let (input, _) = query_sigil(input)?;
675 let (input, _) = many0(space_tab)(input)?;
676 let (input, first_para) = paragraph(input)?;
677
678 let (input, mut rest_paras) = many0(|input| {
680 let (input, _) = new_line(input)?;
681 let (input, _) = many0(space_tab)(input)?;
682 let (input, para) = paragraph(input)?;
683 Ok((input, para))
684 })(input)?;
685
686 let mut all_paragraphs = vec![first_para];
687 all_paragraphs.append(&mut rest_paras);
688
689 Ok((input, SectionElement::QuestionBlock(all_paragraphs)))
690}
691
692pub fn info_block(input: ParseString) -> ParseResult<SectionElement> {
693 let (input, _) = info_sigil(input)?;
694 let (input, _) = many0(space_tab)(input)?;
695 let (input, first_para) = paragraph(input)?;
696
697 let (input, mut rest_paras) = many0(|input| {
699 let (input, _) = new_line(input)?;
700 let (input, _) = many0(space_tab)(input)?;
701 let (input, para) = paragraph(input)?;
702 Ok((input, para))
703 })(input)?;
704
705 let mut all_paragraphs = vec![first_para];
706 all_paragraphs.append(&mut rest_paras);
707
708 Ok((input, SectionElement::InfoBlock(all_paragraphs)))
709}
710
711pub fn quote_block(input: ParseString) -> ParseResult<SectionElement> {
712 let (input, _) = quote_sigil(input)?;
713 let (input, _) = many0(space_tab)(input)?;
714 let (input, first_para) = paragraph(input)?;
715
716 let (input, mut rest_paras) = many0(|input| {
718 let (input, _) = new_line(input)?;
719 let (input, _) = many0(space_tab)(input)?;
720 let (input, para) = paragraph(input)?;
721 Ok((input, para))
722 })(input)?;
723
724 let mut all_paragraphs = vec![first_para];
725 all_paragraphs.append(&mut rest_paras);
726
727 Ok((input, SectionElement::QuoteBlock(all_paragraphs)))
728}
729
730pub fn abstract_el(input: ParseString) -> ParseResult<SectionElement> {
732 let (input, _) = abstract_sigil(input)?;
733 let (input, _) = many0(space_tab)(input)?;
734 let (input, first_para) = paragraph(input)?;
735
736 let (input, mut rest_paras) = many0(|input| {
738 let (input, _) = new_line(input)?;
739 let (input, _) = many0(space_tab)(input)?;
740 let (input, para) = paragraph(input)?;
741 Ok((input, para))
742 })(input)?;
743
744 let mut all_paragraphs = vec![first_para];
745 all_paragraphs.append(&mut rest_paras);
746
747 Ok((input, SectionElement::Abstract(all_paragraphs)))
748}
749
750pub fn equation(input: ParseString) -> ParseResult<Token> {
752 let (input, _) = equation_sigil(input)?;
753 let (input, mut txt) = many1(alt((backslash,text)))(input)?;
754 let mut eqn = Token::merge_tokens(&mut txt).unwrap();
755 Ok((input, eqn))
756}
757
758pub fn citation(input: ParseString) -> ParseResult<Citation> {
760 let (input, _) = left_bracket(input)?;
761 let (input, mut id) = many1(alphanumeric)(input)?;
762 let (input, _) = right_bracket(input)?;
763 let (input, _) = colon(input)?;
764 let (input, _) = whitespace0(input)?;
765 let (input, txt) = paragraph(input)?;
766 let (input, _) = whitespace0(input)?;
767 let id = Token::merge_tokens(&mut id).unwrap();
768 Ok((input, Citation{id, text: txt}))
769}
770
771pub fn float_sigil(input: ParseString) -> ParseResult<FloatDirection> {
773 let (input, d) = alt((float_left, float_right))(input)?;
774 let d = match d.kind {
775 TokenKind::FloatLeft => FloatDirection::Left,
776 TokenKind::FloatRight => FloatDirection::Right,
777 _ => unreachable!(),
778 };
779 Ok((input, d))
780}
781
782pub fn float(input: ParseString) -> ParseResult<(Box<SectionElement>,FloatDirection)> {
784 let (input, direction) = float_sigil(input)?;
785 let (input, _) = many0(space_tab)(input)?;
786 let (input, el) = section_element(input)?;
787 Ok((input, (Box::new(el), direction)))
788}
789
790pub fn section_element(input: ParseString) -> ParseResult<SectionElement> {
792 let (input, section_element) = match many1(mech_code)(input.clone()) {
793 Ok((input, code)) => (input, SectionElement::MechCode(code)),
794 _ => match mechdown_list(input.clone()) {
795 Ok((input, lst)) => (input, SectionElement::List(lst)),
796 _ => match footnote(input.clone()) {
797 Ok((input, ftnote)) => (input, SectionElement::Footnote(ftnote)),
798 _ => match citation(input.clone()) {
799 Ok((input, citation)) => (input, SectionElement::Citation(citation)),
800 _ => match abstract_el(input.clone()) {
801 Ok((input, abstrct)) => (input, abstrct),
802 _ => match img(input.clone()) {
803 Ok((input, img)) => (input, SectionElement::Image(img)),
804 _ => match equation(input.clone()) {
805 Ok((input, eqn)) => (input, SectionElement::Equation(eqn)),
806 _ => match markdown_table(input.clone()) {
807 Ok((input, table)) => (input, SectionElement::Table(table)),
808 _ => match float(input.clone()) {
809 Ok((input, flt)) => (input, SectionElement::Float(flt)),
810 _ => match quote_block(input.clone()) {
811 Ok((input, quote)) => (input, quote),
812 _ => match code_block(input.clone()) {
813 Ok((input, m)) => (input,m),
814 _ => match thematic_break(input.clone()) {
815 Ok((input, _)) => (input, SectionElement::ThematicBreak),
816 _ => match subtitle(input.clone()) {
817 Ok((input, subtitle)) => (input, SectionElement::Subtitle(subtitle)),
818 _ => match paragraph(input) {
819 Ok((input, p)) => (input, SectionElement::Paragraph(p)),
820 Err(err) => { return Err(err); }
821 }
822 }
823 }
824 }
825 }
826 }
827 }
828 }
829 }
830 }
831 }
832 }
833 }
834 };
835 let (input, _) = many0(blank_line)(input)?;
836 Ok((input, section_element))
837}
838
839pub fn section(input: ParseString) -> ParseResult<Section> {
841 let msg = "Expects user function, block, mech code block, code block, statement, paragraph, or unordered list";
842 let (input, subtitle) = ul_subtitle(input)?;
843 let (input, elements) = many0(tuple((is_not(ul_subtitle),section_element)))(input)?;
844 let elements = elements.into_iter().map(|(_,e)| e).collect();
845 Ok((input, Section{subtitle: Some(subtitle), elements}))
846}
847
848pub fn section_elements(input: ParseString) -> ParseResult<Section> {
850 let msg = "Expects user function, block, mech code block, code block, statement, paragraph, or unordered list";
851 let (input, elements) = many1(tuple((is_not(ul_subtitle),section_element)))(input)?;
852 let elements = elements.into_iter().map(|(_,e)| e).collect();
853 Ok((input, Section{subtitle: None, elements}))
854}
855
856pub fn body(input: ParseString) -> ParseResult<Body> {
858 let (input, _) = whitespace0(input)?;
859 let (input, sections) = many0(alt((section,section_elements)))(input)?;
860 let (input, _) = whitespace0(input)?;
861 Ok((input, Body{sections}))
862}