use std::{
time::Instant,
vec,
};
//참된 AI 사용법.
static COLOR_REGEX: Lazy<Regex> = Lazy::new(|| {
// 정규식은 한 번만 컴파일
let color_pattern = r"#(?:[0-9a-f]{3}|[0-9a-f]{6})|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgrey|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|grey|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgrey|lightgreen|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen";
let full_pattern = format!(r"(?i)^({cp})(?:,({cp}))?$", cp = color_pattern);
Regex::new(&full_pattern).unwrap()
});
use once_cell::sync::Lazy;
use regex::Regex;
use crate::{parse_third::parse_third, parser_first::parse_first, renderobjs::RenderObject};
#[derive(Debug)]
pub struct Compiler {
pub(crate) index: usize,
pub array: Vec<Objects>,
pub(crate) expected: Vec<(Expect, usize, bool)>,
pub fixed_comments: Vec<String>,
pub redirect: Option<String>,
pub(crate) rollbacks: Option<usize>,
}
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub enum Objects {
Char(char),
RenderObject(RenderObject),
}
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub enum Expect {
None,
Link,
SyntaxTriple,
TripleWithNamuMark,
JustTriple,
NamuMacro,
List(usize),
Quote(usize),
Heading(usize),
Color,
Plus,
Minus,
Reference,
Bold,
Itelic,
DelTidal,
DelBar,
UnderLine,
Upper,
Lower,
Table,
}
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub enum ListType {
Hangul,
AlphaSmall,
AlphaBig,
RomanBig,
RomanSmall,
List,
Arabia,
}
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub enum NamuMacroType {
YouTube,
KakaoTV,
NicoVideo,
Vimeo,
NaverTV,
Include,
Age,
DDay,
PageCount,
Ruby,
Date,
TableOfContents,
Reference,
Br,
Clearfix,
}
impl Compiler {
pub(crate) fn get_before_earlyparse(&self, vec: Vec<Objects>) -> RenderObject {
RenderObject::AddBefore(vec)
}
pub fn from(string: String) -> Compiler {
let mut compiler = Compiler {
index: 0,
array: Vec::new(),
expected: Vec::new(),
fixed_comments: vec![String::new()],
redirect: None,
rollbacks: None,
};
for char in string.chars() {
compiler.array.push(Objects::Char(char));
}
compiler
}
pub fn parse(&mut self) {
let time = Instant::now();
parse_first(self, Expect::None);
println!("first:{:?}", time.elapsed());
self.index = 0;
self.expected.clear();
let time = Instant::now();
parse_third(self, Expect::None);
println!("second:{:?}", time.elapsed());
self.fixed_comments.pop();
}
pub(crate) fn get(&self, idx: usize) -> Option<&Objects> {
self.array.get(idx)
}
pub(crate) fn current(&self) -> Option<Objects> {
self.array.get(self.index).cloned()
}
pub(crate) fn peak_line(&mut self, str: &str) -> bool {
let mut idx = 0;
if self.index == 0 || self.get(self.index - 1) == Some(&Objects::Char('\n')) {
idx += 1;
} else {
return false;
}
for ch in str.chars() {
if let Some(Objects::Char(cha)) = self.get(self.index + idx - 1) {
if ch.to_lowercase().to_string() != *cha.to_lowercase().to_string() {
return false;
}
} else {
return false;
}
idx += 1;
}
true
}
pub(crate) fn contains_for_parsing(
&self,
closure: impl Fn(&Expect) -> bool,
) -> (bool, bool, usize) {
let a = self.contains_for_parsing_more(closure);
(a.0, a.1, a.2)
}
pub(crate) fn contains_for_parsing_more(
&self,
closure: impl Fn(&Expect) -> bool,
) -> (bool, bool, usize, Expect) {
let mut has_to_rollback = false;
let index = 0..self.expected.len();
for i in index {
let item = self.expected.get(i).unwrap();
if closure(&item.0) {
return (true, has_to_rollback, i + 1, item.0.clone());
} else if item.2 {
has_to_rollback = true;
}
}
(false, has_to_rollback, 0, Expect::None)
}
pub(crate) fn peak_repeat_line(&mut self, ch: char, end: Option<&str>) -> (bool, usize) {
if self.index == 0 || self.get(self.index - 1) == Some(&Objects::Char('\n')) {
let mut idx = 0;
loop {
if self.get(self.index + idx) == Some(&Objects::Char(ch)) {
idx += 1;
} else if end.is_none() && idx != 0 {
return (true, idx);
} else if end.is_some()
&& end.unwrap().len() + self.index + idx < self.array.len()
&& 에휴_진짜_왜그럼(
&self.array[self.index + idx..end.unwrap().len() + self.index + idx],
) == end.unwrap()
&& idx != 0
{
return (true, idx);
} else {
return (false, 0);
}
}
} else {
(false, 0)
}
}
pub(crate) fn is_color(&self) -> bool {
let prefix = ['{', '{', '{', '#'];
if !self.peak(&prefix) {
return false;
}
// 더 깔끔하게 문자열 수집
let mut string = String::new();
let mut offset = 4;
while let Some(Objects::Char(ch)) = self.get(self.index + offset) {
if *ch == ' ' {
break;
}
string.push(*ch);
offset += 1;
}
// 바로 bool 반환
COLOR_REGEX.is_match(&string)
}
pub(crate) fn peak(&self, str_: &[char]) -> bool {
let mut i = 0;
let len = str_.len();
loop {
if i == len {
break;
}
let Some(Objects::Char(cha)) = self.get(self.index + i) else {
return false;
};
if str_.get(i).unwrap().to_ascii_lowercase() != cha.to_ascii_lowercase() {
return false;
}
i += 1;
}
true
}
}
pub static LINK_OPEN: [char; 2] = ['[', '['];
pub static LINK_CLOSE: [char; 2] = [']', ']'];
pub static SPACE: [char; 1] = [' '];
pub static MACRO_CLOSE: [char; 1] = [']'];
pub static TRIPLE_OPEN: [char; 3] = ['{', '{', '{'];
pub static TRIPLE_CLOSE: [char; 3] = ['}', '}', '}'];
pub static BOLD: [char; 3] = ['\'', '\'', '\''];
pub static ITELIC: [char; 2] = ['\'', '\''];
pub static DELTITAL: [char; 2] = ['~', '~'];
pub static DELBAR: [char; 2] = ['-', '-'];
pub static UNDERLINE: [char; 2] = ['_', '_'];
pub static UPPER: [char; 2] = ['^', '^'];
pub static LOWER: [char; 2] = [',', ','];
pub static TABLE: [char; 2] = ['|', '|'];
pub static MACROARG_CLOSE: [char; 2] = [')', ']'];
pub static WIKI: [char; 10] = ['{', '{', '{', '#', '!', 'w', 'i', 'k', 'i', ' '];
pub static IF: [char; 8] = ['{', '{', '{', '#', '!', 'i', 'f', ' '];
pub static FOLDING: [char; 13] = [
'{', '{', '{', '#', '!', 'f', 'o', 'l', 'd', 'i', 'n', 'g', ' ',
];
pub static PLUS: [char; 4] = ['{', '{', '{', '+'];
pub static MINUS: [char; 4] = ['{', '{', '{', '-'];
pub static REFOPEN: [char; 2] = ['[', '*'];
pub static DATE: [char; 6] = ['[', 'd', 'a', 't', 'e', ']'];
pub static DATETIME: [char; 10] = ['[', 'd', 'a', 't', 'e', 't', 'i', 'm', 'e', ']'];
pub static 몪차: [char; 4] = ['[', '목', '차', ']'];
pub static TABLEOFCONTENTS: [char; 16] = [
'[', 't', 'a', 'b', 'l', 'e', 'o', 'f', 'c', 'o', 'n', 't', 'e', 'n', 't', 's',
];
pub static 깎쭈: [char; 4] = ['[', '각', '주', ']'];
pub static FOOTNOTE: [char; 10] = ['[', 'f', 'o', 'o', 't', 'n', 'o', 't', 'e', ']'];
pub static 뀨: [char; 4] = ['[', 'b', 'r', ']'];
pub static CLEARFIX: [char; 10] = ['[', 'c', 'l', 'e', 'a', 'r', 'f', 'i', 'x', ']'];
pub static YOUTUBE: [char; 9] = ['[', 'y', 'o', 'u', 't', 'u', 'b', 'e', '('];
pub static NICOVIDEO: [char; 11] = ['[', 'n', 'i', 'c', 'o', 'v', 'i', 'd', 'e', 'o', '('];
pub static VIMEO: [char; 7] = ['[', 'v', 'i', 'm', 'e', 'o', '('];
pub static NAVERTV: [char; 9] = ['[', 'n', 'a', 'v', 'e', 'r', 't', 'v', '('];
pub static KAKAOTV: [char; 9] = ['[', 'k', 'a', 'k', 'a', 'o', 't', 'v', '('];
pub static INCLUDE: [char; 9] = ['[', 'i', 'n', 'c', 'l', 'u', 'd', 'e', '('];
pub static AGE: [char; 5] = ['[', 'a', 'g', 'e', '('];
pub static DDAY: [char; 6] = ['[', 'd', 'd', 'a', 'y', '('];
pub static PAGECOUNT: [char; 11] = ['[', 'p', 'a', 'g', 'e', 'c', 'o', 'u', 'n', 't', '('];
pub static RUBY: [char; 6] = ['[', 'r', 'u', 'b', 'y', '('];
pub static NEWLINE: [char; 1] = ['\n'];
pub static EQNEWLINE: [char; 2] = ['=', '\n'];
pub static EQ: [char; 1] = ['='];
fn 에휴_진짜_왜그럼(sliceee: &[Objects]) -> String {
let mut result = String::new();
for obj in sliceee {
if let Objects::Char(ch) = obj {
result.push(*ch);
} else {
panic!();
}
}
result
}