1use std::fmt;
8use regex::Regex;
9use std::fs::File;
10use std::fs::write;
11use colored::Colorize;
12use std::error::Error;
13use std::fs::read_to_string;
14use std::collections::HashMap;
15use serde_json::to_string_pretty;
16
17pub fn to_yaml(subject:HashMap<String, String>) -> String {
19 let mut result_list: Vec<String> = Vec::new();
20 for (key, value) in subject.into_iter() {
21 let code_string: String = format!("{}: \"{}\"", key, value);
22 result_list.push(code_string);
23 }
24 let result: String = result_list.join("\n");
25 return result;
26}
27
28pub fn to_toml(subject:HashMap<String, String>) -> String {
30 let mut result_list: Vec<String> = Vec::new();
31 for (key, value) in subject.into_iter() {
32 let code_string: String = format!("{} = \"{}\"", key, value);
33 result_list.push(code_string);
34 }
35 let result: String = result_list.join("\n");
36 return result;
37}
38
39pub fn to_aml(subject:HashMap<String, String>) -> String {
41 let mut result_list: Vec<String> = Vec::new();
42 for (key, value) in subject.into_iter() {
43 let code_string: String = format!("\'{}\' => \'{}\'", key, value);
44 result_list.push(code_string);
45 }
46 let result: String = result_list.join("\n");
47 return result;
48}
49
50pub fn file_is(filename: String) -> bool {
53 let mut result: Vec<bool> = Vec::new();
54 let contents = read_to_string(filename);
55 match contents {
56 Ok(_n) => result.push(true),
57 Err(_x) => result.push(false)
58 }
59 return result[0];
60}
61
62pub fn read_file(filename: String) -> String {
65 let mut result: String = String::from("");
66 let fname_copy: String = filename.clone();
67 if file_is(filename) == true {
68 result = read_to_string(fname_copy).unwrap();
69 }
70 else {}
71 return result;
72}
73
74pub fn has_index(subject: Vec<Token>, index: usize) -> bool {
76 let mut result: bool = false;
77 if index >= subject.len(){
78 result = true;
79 }
80 else {}
81 return result;
82}
83
84#[derive(Clone,Eq,PartialEq)]
87pub struct Token {
88 name: String,
89 value: String
90}
91
92impl Default for Token {
95 fn default () -> Token {
96 Token {
97 name: String::from(""),
98 value: String::from("")
99 }
100 }
101}
102
103impl Token {
104 pub fn to_string(&self) -> String {
105 return format!("{} : {}", self.name, self.value);
106 }
107}
108
109pub fn pattern_pool() -> HashMap<String, Regex>{
111 let mut pool: HashMap<String, Regex> = HashMap::new();
112 pool.insert(String::from("ENTITY"), Regex::new(r"'(.*)'").unwrap());
113 pool.insert(String::from("ASSIGN"), Regex::new(r"(=>)").unwrap());
114 pool.insert(String::from("COMMENT"), Regex::new(r"%(.*)").unwrap());
115 return pool;
116}
117
118pub fn lex(source_code: String) -> Vec<Token>{
122 let lines: Vec<String> = clean_split(source_code, String::from("\n"));
123 let mut result: Vec<Token> = Vec::new();
124 let pool: HashMap<String, Regex> = pattern_pool();
125 for line in lines {
126 let char_list: Vec<String> = clean_split(line, String::from(""));
127 let mut new_char_list: Vec<String> = Vec::new();
128 for char_item in char_list {
129 new_char_list.push(char_item);
130 let collected_chars: String = new_char_list.join("");
131 for (key,value) in pool.clone().into_iter() {
132 if value.is_match(&collected_chars) {
133 new_char_list.clear();
134 let captured = value.captures(&collected_chars).unwrap();
135 let new_token: Token = Token {
136 name: key,
137 value: captured.get(1).unwrap().as_str().to_string()
138 };
139 result.push(new_token);
140 }
141 else {}
142 }
143 }
144 }
145 return result;
146}
147
148pub fn clean_split(subject: String, split_char: String) -> Vec<String> {
151 let mut result: Vec<String> = Vec::new();
152 for item in subject.split(&split_char) {
153 let new_item: String = item.to_string();
154 result.push(new_item);
155 }
156 return result;
157}
158
159#[derive(Debug)]
163pub struct AngelMarkupError {
164 details: String
165}
166
167impl AngelMarkupError {
170 fn new(msg: &str) -> AngelMarkupError {
171 AngelMarkupError{details: msg.to_string()}
172 }
173}
174
175impl fmt::Display for AngelMarkupError {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 write!(f,"{}",self.details)
179 }
180}
181
182impl Error for AngelMarkupError {
184 fn description(&self) -> &str {
185 &self.details
186 }
187}
188
189pub fn serialize(src: String) -> Result<HashMap<String, String>,AngelMarkupError> {
191 let lexed_tokens: Vec<Token> = lex(src);
192 let lexed_tokens_clone_one: Vec<Token> = lexed_tokens.clone();
193 let lexed_tokens_clone_two: Vec<Token> = lexed_tokens_clone_one.clone();
194 let lexed_tokens_clone_three: Vec<Token> = lexed_tokens_clone_two.clone();
195 let lexed_tokens_clone_four: Vec<Token> = lexed_tokens_clone_three.clone();
196 let lexed_tokens_clone_five: Vec<Token> = lexed_tokens_clone_four.clone();
197 let lexed_tokens_clone_six: Vec<Token> = lexed_tokens_clone_five.clone();
198 let mut result: HashMap<String, String> = HashMap::new();
199 for (index,token) in lexed_tokens.into_iter().enumerate() {
200 if token.name == String::from("ASSIGN"){
201 let last_index: usize = index-1;
202 let next_index: usize = index+1;
203 if last_index < lexed_tokens_clone_three.len() && next_index < lexed_tokens_clone_four.len() {
204 let key: String = lexed_tokens_clone_five[last_index.clone()].clone().value;
205 let value: String = lexed_tokens_clone_six[next_index.clone()].clone().value;
206 result.insert(key,value);
207 }
208 else {
209 let msg: String = String::from("Syntax error detected!");
210 return Err(AngelMarkupError::new(&msg));
211 }
212 }
213 else if token.name == String::from("COMMENT") {}
214 else {}
215 }
216 if result.is_empty(){
217 let msg: String = String::from("Result is empty.");
218 return Err(AngelMarkupError::new(&msg));
219 }
220 else {}
221 Ok(result)
222}
223
224pub fn lint(src: String) -> bool {
228 let mut result: bool = false;
229 let match_op = serialize(src);
230 match match_op {
231 Ok(_x) => {
232 result = true;
233 },
234 Err(_e) => {}
235 };
236 return result;
237}
238
239pub fn create_file(filename: String) -> bool {
243 let mut result: Vec<bool> = Vec::new();
244 let new_file = File::create(filename);
245 match new_file {
246 Ok(_n) => result.push(true),
247 Err(_x) => result.push(false)
248 }
249 return result[0];
250}
251
252pub fn write_to_file(filename: String, contents: String) -> bool {
256 let mut result: Vec<bool> = Vec::new();
257 let fname_copy: String = filename.clone();
258 if file_is(filename) == true {
259 let write_op = write(fname_copy, contents);
260 match write_op {
261 Ok(_n) => result.push(true),
262 Err(_x) => result.push(false)
263 }
264 }
265 return result[0];
266}
267
268pub fn compile_to_json(src: String, target: String) {
270 let src_clone_one: String = src.clone();
271 let src_clone_two: String = src_clone_one.clone();
272 let target_clone_one: String = target.clone();
273 let target_clone_two: String = target_clone_one.clone();
274 if lint(read_file(src_clone_one)) == true {
275 let json_string: String = to_string_pretty(&serialize(read_file(src_clone_two)).unwrap()).unwrap();
276 create_file(target_clone_one);
277 write_to_file(target_clone_two, json_string);
278 }
279 else {
280 let msg: String = format!("An error occurred while parsing your Angelmarkup file.").red().to_string();
281 println!("{}", msg);
282 }
283}
284
285pub fn compile_to_yaml(src: String, target: String) {
287 let src_clone_one: String = src.clone();
288 let src_clone_two: String = src_clone_one.clone();
289 let target_clone_one: String = target.clone();
290 let target_clone_two: String = target_clone_one.clone();
291 if lint(read_file(src_clone_one)) == true {
292 let yml_string: String = to_yaml(serialize(read_file(src_clone_two)).unwrap());
293 create_file(target_clone_one);
294 write_to_file(target_clone_two, yml_string);
295 }
296 else {
297 let msg: String = format!("An error occurred while parsing your Angelmarkup file.").red().to_string();
298 println!("{}", msg);
299 }
300}
301
302pub fn compile_to_toml(src: String, target: String) {
304 let src_clone_one: String = src.clone();
305 let src_clone_two: String = src_clone_one.clone();
306 let target_clone_one: String = target.clone();
307 let target_clone_two: String = target_clone_one.clone();
308 if lint(read_file(src_clone_one)) == true {
309 let toml_string: String = to_toml(serialize(read_file(src_clone_two)).unwrap());
310 create_file(target_clone_one);
311 write_to_file(target_clone_two, toml_string);
312 }
313 else {
314 let msg: String = format!("An error occurred while parsing your Angelmarkup file.").red().to_string();
315 println!("{}", msg);
316 }
317}