1mod macros_lexer;
2use std::{collections::HashMap, fmt::Debug};
3
4use guarded::guarded_unwrap;
5use macro_token_iterator::MacroArgs;
6pub use macros_lexer::lex_rsml_macros;
7
8mod macros_parser;
9pub use macros_parser::parse_rsml_macros;
10
11mod macro_token_iterator;
12pub use macro_token_iterator::MacroTokenIterator;
13
14use crate::{lex_rsml, Token};
15
16pub type TokenPair<TokenType = Token> = (TokenType, String);
17
18#[derive(Debug, Clone)]
19pub struct Macro {
20 pub token_pairs: Vec<TokenPair>,
21 arg_places: Option<HashMap<usize, usize>>
22}
23impl<'a> Macro {
24 fn new(body: String, args: Option<HashMap<&'a str, usize>>) -> Self {
25 let mut lexer: logos::Lexer<'_, Token> = lex_rsml(&body);
26
27 let mut token_pairs: Vec<TokenPair> = vec![];
28
29 if let Some(args) = args {
30 let mut token_pairs_idx = 0usize;
31 let mut arg_places: HashMap<usize, usize> = HashMap::new();
32
33 loop {
34 let token = guarded_unwrap!(guarded_unwrap!(lexer.next(), break), continue);
35 let token_slice = lexer.slice();
36
37 if matches!(token, Token::ArgIdentifier) {
38 if let Some(Ok(next_token)) = lexer.next() {
39 let next_token_slice = lexer.slice();
40
41 if matches!(next_token, Token::Text) {
42 if let Some(arg_idx) = args.get(next_token_slice) {
43 arg_places.insert(token_pairs_idx, *arg_idx);
44
45 } else {
46 token_pairs.push((Token::Nil, "nil".to_string()));
47 token_pairs_idx += 1;
48 }
49
50 } else {
51 token_pairs.push((token, token_slice.to_string()));
52 token_pairs.push((next_token, next_token_slice.to_string()));
53 token_pairs_idx += 2;
54 }
55 }
56
57 } else {
58 token_pairs.push((token, token_slice.to_string()));
59 token_pairs_idx += 1;
60 }
61 }
62
63 Self {
64 token_pairs,
65 arg_places: Some(arg_places)
66 }
67
68 } else {
69 loop {
70 let token = guarded_unwrap!(guarded_unwrap!(lexer.next(), break), continue);
71 let slice = lexer.slice().to_string();
72 token_pairs.push((token, slice));
73 }
74
75 Self {
76 token_pairs,
77 arg_places: None
78 }
79 }
80 }
81
82 pub fn iter(
83 &'a self,
84 args_tokens: Option<Vec<Vec<(Token, &'a str)>>>
85 ) -> MacroTokenIterator<'a> {
86 if let Some(args_tokens) = args_tokens {
87 if let Some(arg_places) = &self.arg_places {
88 let args = Some(MacroArgs {
89 args_tokens, arg_places
90 });
91
92 return MacroTokenIterator::new(&self.token_pairs, args)
93 }
94 }
95
96 MacroTokenIterator::new(&self.token_pairs, None)
97 }
98}
99
100#[derive(Debug, Clone)]
101pub struct MacroGroup(HashMap<String, HashMap<usize, Macro>>);
102
103impl<'a> MacroGroup {
104 pub fn new() -> Self {
105 MacroGroup(HashMap::new())
106 }
107
108 fn insert(&mut self, name: &str, body: String, args: Option<HashMap<&'a str, usize>>) {
109 let macro_map = self.0.entry(name.into()).or_insert(HashMap::new());
110 if let Some(some_args) = &args {
111 macro_map.insert(
112 some_args.len(),
113 Macro::new(body, args)
114 );
115 } else {
116 macro_map.insert(0, Macro::new(body, None));
117 };
118 }
119
120 pub fn get(&self, macro_name: &str, args_len: usize) -> Option<&Macro> {
121 let macro_data = guarded_unwrap!(self.0.get(macro_name), return None);
122
123 macro_data.get(&args_len)
124 }
125}
126
127
128