1use std::collections::HashMap;
2
3use crate::command::Command;
4
5#[derive(Debug)]
6pub enum TokenType {
7 Command,
8 Argument,
9 Operator,
10}
11
12impl Default for TokenType {
13 fn default() -> Self {
14 todo!()
15 }
16}
17
18#[derive(Debug, Default)]
19pub struct Token {
20 token_type: TokenType,
21 value: String,
22}
23
24#[derive(Debug)]
25pub enum ASTNode {
26 Command { name: String, args: Vec<ASTNode> },
27 Operator { op: String, args: Vec<ASTNode> },
28 Argument { value: String },
29 Pipe { left: Box<ASTNode>, right: Box<ASTNode> },
30}
31
32impl Default for ASTNode {
33 fn default() -> Self {
34 ASTNode::Argument { value: String::new() }
35 }
36}
37
38pub trait Lexer: Default {
39 fn _run(input: &str) -> Vec<Token>;
40}
41pub trait LexerTraitObject {
42 fn run(&self, input: &str) -> Vec<Token>;
43}
44impl<T: Lexer> LexerTraitObject for T {
45 fn run(&self, input: &str) -> Vec<Token> {
46 return <Self as Lexer>::_run(input);
47 }
48}
49
50#[derive(Default)]
51pub struct DefaultLexer;
52impl Lexer for DefaultLexer {
53 fn _run(input: &str) -> Vec<Token> {
54 let mut tokens = Vec::<Token>::new();
55
56 for word in input.split_whitespace() {
57 let token_type = match word {
58 "&&" | "||" | "|" | ">" | ">>" | "<" => TokenType::Operator,
59 _ if tokens.is_empty()
60 || matches!(
61 tokens.last().unwrap().token_type,
62 TokenType::Operator
63 ) =>
64 {
65 TokenType::Command
66 }
67 _ => TokenType::Argument,
68 };
69
70 tokens.push(Token { token_type, value: word.to_string() });
71 }
72
73 tokens
74 }
75}
76
77pub trait Parser: Default {
78 fn _run(tokens: Vec<Token>) -> ASTNode;
79}
80pub trait ParserTraitObject {
81 fn run(&self, tokens: Vec<Token>) -> ASTNode;
82}
83impl<T: Parser> ParserTraitObject for T {
84 fn run(&self, tokens: Vec<Token>) -> ASTNode {
85 return <Self as Parser>::_run(tokens);
86 }
87}
88
89#[derive(Default)]
90pub struct DefaultParser;
91impl Parser for DefaultParser {
92 fn _run(tokens: Vec<Token>) -> ASTNode {
93 let mut iter = tokens.into_iter().peekable();
94
95 let mut root = match iter.next() {
96 Some(Token { token_type: TokenType::Command, value }) => {
97 ASTNode::Command { name: value, args: vec![] }
98 }
99 _ => {
100 eprintln!("Invalid syntax");
101 return ASTNode::default();
102 }
103 };
104
105 while let Some(token) = iter.next() {
106 match token.token_type {
107 TokenType::Argument => {
108 if let ASTNode::Command { name, args } = &mut root {
109 args.push(ASTNode::Argument { value: token.value });
110 }
111 }
112 TokenType::Operator => {
113 let mut args = vec![root];
114 while let Some(Token { token_type: TokenType::Command, value }) =
115 iter.next()
116 {
117 let mut command_args = vec![];
118 while let Some(Token { token_type: TokenType::Argument, value }) =
119 iter.peek()
120 {
121 command_args.push(ASTNode::Argument { value: value.clone() });
122 iter.next();
123 }
124 args.push(ASTNode::Command { name: value, args: command_args });
125 if iter
126 .peek()
127 .map_or(true, |t| matches!(t.token_type, TokenType::Operator))
128 {
129 break;
130 }
131 }
132 if token.value == "|" {
133 let right = args.pop().unwrap();
134 let left = args.pop().unwrap();
135 root =
136 ASTNode::Pipe { left: Box::new(left), right: Box::new(right) };
137 } else {
138 root = ASTNode::Operator { op: token.value, args };
139 }
140 }
141 _ => eprintln!("Invalid syntax"),
142 }
143 }
144
145 root
146 }
147}
148
149pub trait Interpreter: Default {
150 fn _run(ast: ASTNode, custom_commands: &HashMap<String, Box<dyn Command>>);
151}
152pub trait InterpreterTraitObject {
153 fn run(
154 &self,
155 ast: ASTNode,
156 custom_commands: &HashMap<String, Box<dyn Command>>,
157 );
158}
159impl<T: Interpreter> InterpreterTraitObject for T {
160 fn run(
161 &self,
162 ast: ASTNode,
163 custom_commands: &HashMap<String, Box<dyn Command>>,
164 ) {
165 <Self as Interpreter>::_run(ast, custom_commands);
166 }
167}
168
169#[derive(Default)]
170pub struct DefaultInterpreter;
171impl Interpreter for DefaultInterpreter {
172 fn _run(ast: ASTNode, custom_commands: &HashMap<String, Box<dyn Command>>) {
173 match ast {
174 ASTNode::Command { name, args } => {
175 let args: Vec<String> = args
176 .into_iter()
177 .map(|arg| {
178 if let ASTNode::Argument { value } = arg {
179 value
180 } else {
181 eprintln!("Invalid syntax");
182 "".to_owned()
183 }
184 })
185 .collect();
186
187 let args_str = &args.join(" ");
188
189 if let Some(custom_command) = custom_commands.get(&name) {
190 let _ = custom_command
191 .run(args_str)
192 .map(|output| {
193 if !output.is_empty() {
194 println!("{output}");
195 }
196 })
197 .map_err(|e| eprintln!("{e}"));
198
199 return;
200 }
201
202 if let Ok(lock) = crate::command::DEFAULT_COMMANDS.lock() {
203 if let Ok(commands) = lock.as_ref() {
204 if let Some(command) = commands.get(&name) {
205 let _ = command
206 .run(args_str)
207 .map(|output| {
208 if !output.is_empty() {
209 println!("{output}");
210 }
211 })
212 .map_err(|e| eprintln!("{e}"));
213
214 return;
215 }
216 }
217 }
218
219 let command = name.as_str();
220 {
221 let child = std::process::Command::new(command).args(args).spawn();
222
223 match child {
224 Ok(mut child) => {
225 child.wait().unwrap();
226 }
227 Err(e) => eprintln!("{}", e),
228 }
229 }
230 }
231 ASTNode::Operator { op, args } => match op.as_str() {
232 "&&" => {
233 for arg in args {
234 DefaultInterpreter::_run(arg, custom_commands);
235 }
236 }
237 _ => eprintln!("Unknown operator"),
238 },
239 ASTNode::Pipe { left, right } => {
240 let first_command_output =
241 if let ASTNode::Command { name, args } = *left {
242 let args: Vec<String> = args
243 .into_iter()
244 .map(|arg| {
245 if let ASTNode::Argument { value } = arg {
246 value
247 } else {
248 eprintln!("Invalid syntax");
249 "".to_owned()
250 }
251 })
252 .collect();
253
254 let args_str = &args.join(" ");
255
256 if let Some(custom_command) = custom_commands.get(&name) {
257 custom_command.run(args_str).unwrap_or_default()
258 } else if let Ok(lock) = crate::command::DEFAULT_COMMANDS.lock() {
259 if let Ok(commands) = lock.as_ref() {
260 if let Some(command) = commands.get(&name) {
261 command.run(args_str).unwrap_or_default()
262 } else {
263 {
264 let child =
265 std::process::Command::new(&name).args(args).spawn();
266
267 match child {
268 Ok(mut child) => {
269 child.wait().unwrap();
270 }
271 Err(e) => eprintln!("{}", e),
272 }
273 }
274
275 return;
276 }
277 } else {
278 eprintln!("Failed to acquire lock");
279 return;
280 }
281 } else {
282 eprintln!("Failed to acquire lock");
283 return;
284 }
285 } else {
286 return;
287 };
288
289 if let ASTNode::Command { name, args } = *right {
290 let args: Vec<String> = args
291 .into_iter()
292 .map(|arg| {
293 if let ASTNode::Argument { value } = arg {
294 value
295 } else {
296 eprintln!("Invalid syntax");
297 "".to_owned()
298 }
299 })
300 .collect();
301
302 let args_str = &args.join(" ");
303
304 if let Some(custom_command) = custom_commands.get(&name) {
305 let _ = custom_command
306 .run(&format!("\"{}\" \"{}\"", args_str, first_command_output))
307 .map(|output| {
308 if !output.is_empty() {
309 println!("{output}");
310 }
311 })
312 .map_err(|e| eprintln!("{e}"));
313 } else if let Ok(lock) = crate::command::DEFAULT_COMMANDS.lock() {
314 if let Ok(commands) = lock.as_ref() {
315 if let Some(command) = commands.get(&name) {
316 let _ = command
317 .run(&format!(
318 "\"{}\" \"{}\"",
319 args_str, first_command_output
320 ))
321 .map(|output| {
322 if !output.is_empty() {
323 println!("{output}");
324 }
325 })
326 .map_err(|e| eprintln!("{e}"));
327 } else {
328 {
329 let child =
330 std::process::Command::new(&name).args(args).spawn();
331
332 match child {
333 Ok(mut child) => {
334 child.wait().unwrap();
335 }
336 Err(e) => eprintln!("{}", e),
337 }
338 }
339
340 return;
341 }
342 } else {
343 eprintln!("Failed to acquire lock");
344 }
345 } else {
346 eprintln!("Failed to acquire lock");
347 }
348 } else {
349 return;
350 }
351 }
352 _ => eprintln!("Invalid syntax"),
353 }
354 }
355}