1pub mod types;
2pub mod parser;
3pub mod post_processing;
4pub mod scanner;
5pub mod validation;
6
7use post_processing::{ link_user_definitions, parse_define_statements };
8use scanner::Scanner;
9use std::{ fs::ReadDir, path::Path, process::exit };
10use types::Definitions;
11use validation::validate_struct_indexes;
12
13const ALLOCATION_SIZE: usize = 0x40;
14
15#[derive(Debug, Clone)]
16pub struct RuneFileDescription {
17 pub relative_path: String,
18 pub file_name: String,
19 pub definitions: Definitions
20}
21
22#[derive(Debug)]
23pub enum RuneParserError {
24 InvalidInputPath,
25}
26
27pub fn parser_rune_files(input_path: &Path) -> Result<Vec<RuneFileDescription>, RuneParserError> {
28 if !input_path.exists() || !input_path.is_dir() {
29 if !input_path.exists() {
30 println!("Input path \"{0}\" does not exist!", input_path.as_os_str().to_str().unwrap());
31 } else if !input_path.is_dir() {
32 println!("Input path \"{0}\" is not a directory!", input_path.as_os_str().to_str().unwrap());
33 }
34
35 return Err(RuneParserError::InvalidInputPath)
36 }
37
38 let mut rune_file_list: Vec<String> = Vec::with_capacity(ALLOCATION_SIZE);
43
44 get_rune_files(input_path, &mut rune_file_list);
45
46 if rune_file_list.is_empty() {
47 println!("Could not parse any rune files from folder");
48 return Ok(Vec::new())
49 }
50
51 println!("\nFound the following rune files:");
53 for i in 0..rune_file_list.len() {
54 println!(" {0}", rune_file_list[i]);
55 }
56
57 let mut definitions_list: Vec<RuneFileDescription> = Vec::with_capacity(ALLOCATION_SIZE);
61
62 for filepath in rune_file_list {
63 let file_path: &Path = Path::new(&filepath);
64
65 let file = match std::fs::read_to_string(file_path) {
66 Err(error) => panic!("Error in reading file to string. Got error {0}", error),
67 Ok(path) => path
68 };
69
70 let tokens = match Scanner::new(file.chars()).scan_all() {
71 Err(e) => {
72 eprintln!("Error while scanning file {}: {:#?}", filepath, e);
73 exit(-1);
74 }
75 Ok(t) => t,
76 };
77
78 let types: Definitions = match parser::parse_tokens(&mut tokens.into_iter().peekable()) {
79 Err(e) => {
80 eprintln!("Error while parsing file {}: {:#?}", filepath, e);
81 exit(-1);
82 }
83 Ok(t) => t,
84 };
85
86 let file_name: String = file_path.file_name().unwrap().to_str().unwrap().strip_suffix(".rune").unwrap().to_string();
88
89 let relative_path: String = filepath.strip_prefix(input_path.to_str().unwrap()).unwrap()
91 .strip_prefix("/").unwrap()
92 .strip_suffix(file_path.file_name().unwrap().to_str().unwrap()).unwrap().to_string();
93
94 definitions_list.push(
95 RuneFileDescription {
96 relative_path: relative_path,
97 file_name: file_name,
98 definitions: types,
99 }
100 );
101 }
102
103 parse_define_statements(&mut definitions_list);
108
109 link_user_definitions(&mut definitions_list);
111
112 validate_struct_indexes(&definitions_list);
116
117 Ok(definitions_list)
121}
122
123fn get_rune_files(folder_path: &Path, mut rune_file_list: &mut Vec<String>) {
124
125 let folder_iterator: ReadDir = match folder_path.read_dir() {
126 Err(error) => panic!("Could not read \"{0}\" directory. Got error {1}", folder_path.as_os_str().to_str().unwrap(), error),
127 Ok(value) => value
128 };
129
130 for item in folder_iterator {
131 match item {
132 Err(error) => println!("Got an error {0} in one of the items in \"{1}\" directory", error, folder_path.as_os_str().to_str().unwrap()),
133 Ok(item) => {
134 match item.file_type() {
135 Err(error) => println!("Got error {0} in getting file type of file \"{1}\"", error, item.file_name().to_str().unwrap()),
136 Ok(file_type) => {
137 if file_type.is_dir() {
138
139 println!("Found subdirectory named {0:?}", item.file_name());
143
144 let subfolder_string: String = format!("{0}/{1}", folder_path.as_os_str().to_str().unwrap(), item.file_name().to_str().unwrap());
145
146 let subfolder_path: &Path = Path::new(&subfolder_string);
147
148 get_rune_files(subfolder_path, &mut rune_file_list);
150
151 } else if file_type.is_file() {
152
153 let file_string = item.file_name().into_string().expect("Could not parse os string!");
157
158 if file_string.ends_with(".rune") {
159 rune_file_list.push(format!("{0}/{1}", folder_path.as_os_str().to_str().unwrap(), file_string));
160 }
161
162 } else {
163 }
165 }
166 }
167 }
168 };
169 }
170}