ccdb_script/
parser.rs

1//use crate::small;
2use crate::lexer;
3use crate::lexer::TT;
4
5#[derive(Clone, Debug, PartialEq)]
6pub enum Misc {
7    Stop,
8    IfStop,
9    Unknown,
10}
11#[derive(Clone, Debug, PartialEq)]
12pub enum Var {
13    Sstring(String),
14    Var(String),
15}
16
17#[derive(Clone, Debug, PartialEq)]
18pub enum Math {
19    Eq(i64),
20    Pass,
21    Plus(i64),
22    Minus(i64),
23    Div(i64),
24    Times(i64),
25
26
27}
28
29
30#[derive(Clone, Debug, PartialEq)]
31pub enum Command {
32    Prints(Var),
33    If(Var, String, Var),
34
35    Fn(String, [i64; 2], Vec<String>),
36    Loop(String, [i64; 2], Vec<String>, Vec<String>, i64),
37    Run(String, [i64; 2], Vec<String>, Vec<String>),
38
39    Misc(Misc),
40    Get(String),
41
42    Var([String; 2]),
43    Change(String, Var, Math),
44    Delete(String),
45    Cus(String,Vec<Var>),
46}
47#[derive(Clone)]
48pub struct Parse {
49    pub parsed_data: Vec<Command>,
50}
51impl Parse {
52    pub fn new() -> Parse {
53        Parse {
54            parsed_data: Vec::new(),
55        }
56    }
57    pub fn push(&mut self, ty: Command) {
58        self.parsed_data.push(ty);
59    }
60    pub fn find_fn(&mut self, name: &str) -> Command {
61        for x in 0..self.parsed_data.len() {
62            match self.parsed_data[x].clone() {
63                Command::Fn(a, _b, _c) => {
64                    if a == name {
65                        return self.parsed_data[x].clone();
66                    }
67                }
68                _ => {}
69            }
70        }
71        panic!("no function")
72    }
73}
74// parses the garbage that comes out of the lexer
75pub fn parser(code: lexer::Coder) -> Parse {
76    let mut parsed = Parse::new();
77    #[allow(unused_variables)]
78    let curlin = 0;
79    let mut modif = 0;
80    // unified panic in the main parser
81    fn unif_pan(a: TT){
82        panic!("MP command not found {:#?}", a)
83    }
84
85    for line in 0..code.lex.clone().len() {
86        let line = line + modif;
87        if line >= code.lex.clone().len() {
88            break;
89        }
90        match code.lex[line].clone() {
91            TT::Char(a) =>{
92                // skip line if the first char is /
93                if a.as_str() == "/"{
94                    let next_rb = code.next(TT::LBracket, line);
95                    modif += next_rb -1  - line;
96                }else{
97                    unif_pan(TT::Char(a));
98                }
99            }
100            TT::LBracket => {
101                //let codes = code.lex.clone();
102                let code = code.clone();
103                // lesson to self never write (self) in a struct its just stupid
104                let next_rb = code.next(TT::RBracket, line);
105                // calls the sub parser
106                let x = sub_parser([line + 1, next_rb], code.clone());
107                // push whatever comes out of sub parser to the Parsed struct
108                parsed.push(x);
109                // find the next line
110                modif += next_rb - line;
111            }
112            TT::WhiteSpace=>{
113
114            }
115            a => unif_pan(a),
116        }
117        //curlin += 1;
118    }
119    return parsed;
120}
121// this thing actually does the most
122pub fn sub_parser(pos: [usize; 2], code: lexer::Coder) -> Command {
123    let curlin = pos[0];
124    //for line in pos[0]..pos[1] {
125    #[allow(unused_assignments)]
126    let mut command_return: Command = Command::Misc(Misc::Unknown);
127    match code.lex[pos[0]].clone() {
128        TT::LParen => {
129            // LParen is for when the new function comes ()
130            let code = code.clone();
131            // com and args vectors
132            // args is what gets the things after com gets parsed into so like [(com)args]
133            let mut com: Vec<String> = Vec::new();
134            let mut args: Vec<String> = Vec::new();
135            //assembles together the com it only accepts letters and spaces
136         
137            for codes in curlin + 1..code.next(TT::RParen, pos[0]) {
138                //
139                match code.lex[codes].clone() {
140                    TT::Letter(a) => {
141                        com.push(a);
142                    }
143                   
144                    TT::WhiteSpace => {
145                        com.push(" ".to_string());
146                    }
147                    TT::Num (a) =>{
148                        com.push(a);
149
150                    }
151                    _ => panic!("sub parsing error "),
152                }
153            }
154
155            let com = com.join("");
156           
157            // then finds the right fit from com. kinda like thoes shitty find love programs
158            match com.as_str() {
159                "print" => {
160                    // this makes the print it first gets and sees if its a variable in the args compartment or a string
161                    // it then pushes that to the parsed code
162                    let mut is_str = false;
163                    let mut ne_q = code.next(TT::RParen, pos[0]) + 1;
164                    let mut ne_q2 = code.next(TT::RBracket, pos[0]);
165                    for x in code.next(TT::RParen, pos[0]) + 1..code.next(TT::RBracket, pos[0]) {
166                        if code.lex[x] == TT::Quotation {
167                            is_str = true;
168                        }
169                    }
170                    if is_str {
171                        ne_q = code.next(TT::Quotation, pos[0]) + 1;
172                        ne_q2 = code.next(TT::Quotation, ne_q);
173                    }
174
175                    for codes in ne_q..ne_q2 {
176                        //
177                        //println!("{},{}",code.next(TT::RParen)+1,pos[1]-1);
178
179                        match code.lex[codes].clone() {
180                            TT::Letter(a) => {
181                                args.push(a);
182                            }
183                            TT::Num(a) => {
184                                args.push(a);
185                            }
186                            TT::WhiteSpace => {
187                                args.push(" ".to_string());
188                            }
189                            TT::Char(a) => {
190                                args.push(a);
191                            }
192                            a => panic!("sub parsing error 2: {:#?}", a),
193                        }
194                    }
195                    let args = args.join("");
196                    if is_str {
197                        command_return = Command::Prints(Var::Sstring(args));
198                    } else {
199                        command_return = Command::Prints(Var::Var(args));
200                    }
201                }
202                "var" => {
203                    // assembles together the variable
204                    // ! rewrite later
205                    let ne_q = code.next(TT::RParen, pos[0]) + 1;
206                    let ne_q2 = code.next(TT::RBracket, pos[0]);
207                    let mut val: Vec<String> = Vec::new();
208                    let mut push_to_val: bool = false;
209
210                    for codes in ne_q..ne_q2 {
211                        //
212                        //println!("{},{}",code.next(TT::RParen)+1,pos[1]-1);
213
214                        match code.lex[codes].clone() {
215                            TT::Letter(a) => {
216                                if push_to_val {
217                                    val.push(a);
218                                } else {
219                                    args.push(a);
220                                }
221                            }
222                            TT::Num(a) => {
223                                if push_to_val {
224                                    val.push(a);
225                                } else {
226                                    args.push(a);
227                                }
228                            }
229                            TT::WhiteSpace => {
230                                if push_to_val {
231                                    val.push(" ".to_string());
232                                } else {
233                                }
234                                //args.push(" ".to_string());
235                            }
236                            TT::Char(a) => {
237                                args.push(a);
238                            }
239                            TT::Quotation => {
240                                push_to_val = true;
241                            }
242                            a => panic!("sub parsing error 2: {:#?}", a),
243                        }
244                    }
245
246                    let args = args.join("");
247                    let val = val.join("");
248
249                    //args.split("");
250
251                    command_return = Command::Var([args, val]);
252                }
253                "if" => {
254                    // parses together the if statement
255                    let ne_q = code.next(TT::RParen, pos[0]) + 1;
256                    let ne_q2 = code.next(TT::WhiteSpace, ne_q);
257                    let x1 = collect_str([ne_q, ne_q2], code.clone());
258                    let x1 = parse_str_var(x1);
259                    // above: gets the first argument below: gets the if statement like == or !=
260                    let ne_q = ne_q2 + 1;
261                    let ne_q2 = code.next(TT::WhiteSpace, ne_q);
262                    let _xe = collect_str([ne_q, ne_q2], code.clone());
263                    //let _xe = parse_str_var(_xe);
264                    // below: gets the last argument
265                    let ne_q = ne_q2 + 1;
266                    let ne_q2 = code.next(TT::RBracket, ne_q);
267                    let x2 = collect_str([ne_q, ne_q2], code.clone());
268                    let x2 = parse_str_var(x2);
269                    //println!("if {:#?} {:#?} {:#?}",x1,_xe,x2);
270
271                    command_return = Command::If(x1, _xe, x2);
272                }
273                "if stop" => {
274                    // just the stop
275                    command_return = Command::Misc(Misc::IfStop);
276                }
277                "edit" | "cha" => match var_par([pos[0], pos[1]], code) {
278                    // finds the edit and if its a variable that wants to be the new value
279                    // or just text
280                    Command::Change(a, b, c) => {
281                        command_return = Command::Change(a, b, c);
282                    }
283                    _ => {
284                        panic!("this should never happen");
285                    }
286                },
287                "drop" | "dump" => {
288                    let var = collect_str([code.next(TT::RParen, pos[0]) + 1, pos[1]], code);
289                    match parse_str_var(var.clone()) {
290                        Var::Sstring(_) => {
291                            panic!("To dump a variable it needs to be a variable not a string");
292                        }
293                        _ => {}
294                    }
295                    command_return = Command::Delete(var);
296                }
297                "com" =>{
298
299                }
300                a => {
301                    //println!();
302
303                    //panic!(format!("command not found {}", a))
304                    let cus = collect_str([code.next(TT::RParen, pos[0]) + 1, pos[1]], code);
305                    let cus: Vec<String> = cus.split(",<").collect::<Vec<&str>>().into_iter().map(|x|x.to_string()).collect();
306                    
307
308                    //println!("{:#?}",custom_arg);
309                    /*let mut run = true;
310                    let mut di = 1;
311                    let code = code.clone();
312
313                    while run{
314                        let mut code  = &code.clone().to_owned();
315                        let x = code.next(TT::Quotation, pos[0]);
316                        cus.push(collect_str([x + di, code.next(TT::Quotation, x+di)], code.clone()));
317                        di += 1;
318                        if x >= pos[1]{
319                            run = false;
320                        }
321                    }*/
322
323                    let mut custom_arg:  Vec<Var> = Vec::new();
324                    for x in cus{
325                        custom_arg.push(parse_str_var(x));
326                    }
327                    
328                    command_return = Command::Cus(a.to_string(),custom_arg)
329
330                }
331            }
332        }
333        a => panic!("SP command not found {:#?} line {}", a, curlin),
334    }
335    //curlin += 1;
336
337    //}
338
339    return command_return;
340}
341
342fn parse_str_var(str: String) -> Var {
343    //parse string and retruns var that contains Sstring and Var
344    let mut str = str;
345    let mut am_of = 0;
346    let mut _am_of_le = 0;
347
348    for x in str.chars() {
349        match x {
350            '"' => am_of += 1,
351            _ => _am_of_le += 1,
352        }
353    }
354    if am_of == 2 {
355        str.retain(|x| x != '"');
356
357        Var::Sstring(str)
358    } else {
359        Var::Var(str)
360    }
361}
362fn collect_str(pos: [usize; 2], code: lexer::Coder) -> String {
363    let mut args: Vec<String> = Vec::new();
364    // collect a str from random lexer garbage between pos[0] and pos[1]
365    for codes in pos[0]..pos[1] {
366        //
367        //println!("{},{}",code.next(TT::RParen)+1,pos[1]-1);
368
369        match code.lex[codes].clone() {
370            TT::Letter(a) => {
371                args.push(a);
372            }
373            TT::Num(a) => {
374                args.push(a);
375            }
376            TT::WhiteSpace => {
377                args.push(" ".to_string());
378            }
379            TT::Char(a) => {
380                args.push(a);
381            }
382            TT::Quotation => {
383                args.push(r#"""#.to_string());
384            }
385            a => panic!("sub_ parsing error 1: {:#?}", a),
386        }
387    }
388    args.join("")
389}
390
391fn var_par(pos: [usize; 2], code: lexer::Coder) -> Command {
392    // this does what var up in the sub parser does
393    let ne_q = code.next(TT::RParen, pos[0]) + 1;
394    let ne_q2 = code.next(TT::RBracket, pos[0]);
395    let mut val: Vec<String> = Vec::new();
396    let mut args: Vec<String> = Vec::new();
397
398    let mut push_to_val: bool = false;
399    let mut math: bool = true;
400    let mut math_tp:&str = "_";
401
402    for codes in ne_q..ne_q2 {
403        //
404        //println!("{},{}",code.next(TT::RParen)+1,pos[1]-1);
405
406        match code.lex[codes].clone() {
407            TT::Letter(a) => {
408                if push_to_val {
409                    val.push(a);
410                } else {
411                    args.push(a);
412                }
413            }
414            TT::Num(a) => {
415                if push_to_val {
416                    val.push(a);
417                } else {
418                    args.push(a);
419                }
420            }
421            TT::WhiteSpace => {
422                if push_to_val {
423                    val.push(" ".to_string());
424                } else {
425                    push_to_val = true;
426                }
427                //args.push(" ".to_string());
428            }
429            TT::Char(a) => {
430                if push_to_val | math{
431                    match a.as_str() {
432                        "-" =>{
433                            math_tp = "-";
434                            math = false;
435                        }
436                        "+" =>{
437                            math_tp = "+";
438                            math = false;
439                        }
440                        "/" =>{
441                            math_tp = "/";
442                            math = false;
443                        }
444                        "*"|";" =>{
445                            math_tp = "*";
446                            math = false;
447                        }
448                        _=> args.push(a)
449                    }
450                }else{
451                    args.push(a);
452                }
453            }
454            TT::Quotation => {
455                if push_to_val{
456                    math = false;
457                    val.push(r#"""#.to_string());
458                } else {
459                }
460            }
461            a => panic!("sub parsing error 2: {:#?}", a),
462        }
463    }
464    // it just returns Command::Change instead
465    let args = args.join("");
466    let vals = val.join("");
467    let val = parse_str_var(vals.clone());
468
469    let mut mth = Math::Pass;
470    match math_tp{
471        "-" =>{
472            mth = Math::Minus(vals.parse::<i64>().unwrap())
473        }
474        "/" =>{
475            mth = Math::Div(vals.parse::<i64>().unwrap())
476        }
477        "+" =>{
478
479            mth = Math::Plus(vals.parse::<i64>().unwrap())
480        }
481        "*" =>{
482            mth = Math::Times(vals.parse::<i64>().unwrap())
483        }
484        _=>{
485
486        }
487    }
488
489    //println!("{:#?},{}", val, vals);
490
491    //args.split("");
492
493    return Command::Change(args, val, mth);
494}