#[allow(unused_imports)]
use crate::{NotedownAST as AST, NotedownParser, NotedownRule, TextModeParser, TextModeRule};
#[cfg(feature = "colored")]
use colored::*;
use pest::iterators::{Pair, Pairs};
use pest::Parser;
use std::collections::HashMap;
#[cfg(feature = "colored")]
pub fn token_print(s: &str, rule: NotedownRule) {
let pairs: Pairs<NotedownRule> =
NotedownParser::parse(rule, s.replace("\t", " ")).unwrap_or_else(|e| panic!("{}", e));
for pair in pairs {
let rule = pair.as_rule();
match rule {
NotedownRule::NEWLINE | NotedownRule::EOI => continue,
_ => (),
}
println!("{} {:?}", "Rule:".green(), pair.as_rule());
println!("{} {:?}", "Span:".green(), pair.as_span());
println!("{} {}", "Text:".green(), pair.as_str());
for inner_pair in pair.into_inner() {
println!(" {} {:?}", "Inner:".cyan(), inner_pair.as_rule());
println!(" {:?}", inner_pair.as_span());
}
}
}
#[allow(unused_macros)]
macro_rules! declare {
($name:ident) => {
let mut $name: Vec<Pairs<NotedownRule>> = vec![]
};
{$($x:ident),*} => {
$(declare!($x);)*
};
}
#[allow(unused_macros)]
macro_rules! rules {
($rule:ident $name:ident) => {
$rule => $name.push(pair.into_inner()),
};
}
pub fn parse(s: &str) -> AST {
let pairs = NotedownParser::parse(NotedownRule::program, s).unwrap_or_else(|e| panic!("{}", e));
let mut nodes: Vec<AST> = vec![];
for pair in pairs {
let rule = pair.as_rule();
let node = match rule {
NotedownRule::EOI | NotedownRule::COMMENT | NotedownRule::NEWLINE => continue,
NotedownRule::Header => parse_header(pair.into_inner()),
NotedownRule::TextBlock => AST::Paragraph(Box::new(parse_text(pair.as_str()))),
NotedownRule::List => parse_list(&format!("\n{}", pair.as_str())),
_ => {
println!("unimplemented NotedownRule::{:?}", rule);
AST::None
}
};
nodes.push(node)
}
return AST::Statements(nodes);
}
fn parse_text(raw: &str) -> AST {
let s = raw.trim();
let pairs: Pairs<TextModeRule> =
TextModeParser::parse(TextModeRule::text_mode, &s).unwrap_or_else(|e| panic!("{}", e));
let mut nodes: Vec<AST> = vec![];
for pair in pairs {
let rule = pair.as_rule();
let node = match rule {
TextModeRule::EOI => continue,
TextModeRule::SPACE_SEPARATOR => continue,
TextModeRule::NEWLINE => AST::Newline,
TextModeRule::English => AST::Word(pair.as_str().to_string()),
TextModeRule::Word => AST::Word(pair.as_str().to_string()),
TextModeRule::Escaped => {
let s = pair.as_str();
let last = &s[s.len() - 1..];
AST::Escaped(last.to_string())
}
TextModeRule::Math => parse_math_inline(pair),
TextModeRule::Style => parse_style(pair),
TextModeRule::StyleRest => AST::Word(pair.as_str().to_string()),
_ => {
println!("unimplemented TextModeRule::{:?}", rule);
AST::None
}
};
nodes.push(node)
}
println!("{:?}", nodes);
return AST::Statements(nodes);
}
fn parse_header(pairs: Pairs<NotedownRule>) -> AST {
let mut level: Vec<Pair<NotedownRule>> = vec![];
let mut arguments: Vec<Pair<NotedownRule>> = vec![];
let mut content = "";
for pair in pairs.into_iter() {
match pair.as_rule() {
NotedownRule::Sharp => level.push(pair),
NotedownRule::arguments => arguments.push(pair),
NotedownRule::RestOfLine => content = pair.as_str(),
_ => unreachable!(),
}
}
println!("{:?}", level.len());
println!("{:?}", arguments);
let map: HashMap<String, String> = HashMap::new();
AST::Header(Box::new(parse_text(content)), level.len() as u8, map)
}
fn parse_arguments(pairs: Vec<Pair<NotedownRule>>) -> HashMap<String, String> {
let arguments: HashMap<String, String> = HashMap::new();
println!("{:?}", pairs);
arguments
}
fn parse_style(pair: Pair<TextModeRule>) -> AST {
let tokens: Vec<_> = pair.clone().into_inner().into_iter().collect();
let level = tokens[0].as_str().len() as u8;
let text = tokens[1].as_str();
let content = if text.trim().len() == 0 {
Box::new(AST::from(text))
} else {
Box::new(parse_text(text))
};
match level {
1 => AST::Italic(content, level),
2 => AST::Bold(content, level),
3 => {
let i = AST::Italic(content, 0);
AST::Bold(Box::new(i), level)
}
_ => {
println!("unknow *{}", level);
AST::Word(pair.as_str().to_string())
}
}
}
fn parse_math_inline(pair: Pair<TextModeRule>) -> AST {
let tokens: Vec<_> = pair.clone().into_inner().into_iter().collect();
let level = tokens[0].as_str().len() as u8;
let text = tokens[1].as_str();
let content = if text.trim().len() == 0 {
return AST::from(text);
};
match level {
1 => AST::MathInline(text.trim().to_string()),
2 => AST::MathInline(format!("\\displaystyle{}", text.trim())),
_ => {
println!("unknow ${}", level);
AST::Word(pair.as_str().to_string())
}
}
}
fn parse_list(raw: &str) -> AST {
let s = raw.trim();
let pairs: Pairs<TextModeRule> =
TextModeParser::parse(TextModeRule::text_mode, &s).unwrap_or_else(|e| panic!("{}", e));
let mut nodes: Vec<AST> = vec![];
for pair in pairs {
let rule = pair.as_rule();
let node = match rule {
TextModeRule::EOI => continue,
TextModeRule::SPACE_SEPARATOR => continue,
TextModeRule::NEWLINE => AST::Newline,
TextModeRule::English => AST::Word(pair.as_str().to_string()),
TextModeRule::Word => AST::Word(pair.as_str().to_string()),
TextModeRule::Escaped => {
let s = pair.as_str();
let last = &s[s.len() - 1..];
AST::Escaped(last.to_string())
}
TextModeRule::Math => parse_math_inline(pair),
TextModeRule::Style => parse_style(pair),
TextModeRule::StyleRest => AST::Word(pair.as_str().to_string()),
_ => {
println!("unimplemented TextModeRule::{:?}", rule);
AST::None
}
};
nodes.push(node)
}
println!("{:?}", nodes);
return AST::Statements(nodes);
}