yoloxide/
parser.rs

1use crate::types::Token;
2
3use crate::types::ast::{
4    statement::Statement as Stat,
5    expression::Expression as Expr,
6    operators::Operator as Op,
7    value::Value,
8    line::Line,
9    program::Program
10};
11
12use crate::types::ParseErrorKind;
13use crate::types::ExprError;
14use crate::types::StatError;
15
16use crate::types::SlidingWindow;
17use crate::types::VecWindow;
18
19pub fn parse_program(window: &mut VecWindow<Token>) -> Result<Program, StatError>
20{
21    let mut line_vec: Vec<Line> = Vec::new();
22    let mut current_line: Vec<Stat> = Vec::new();
23
24    while window.remaining_length() > 0
25    {
26        if let Some(Token::Newline) = window.get_value(0)
27        {
28            window.move_view(1);
29
30            line_vec.push(Line(current_line.clone()));
31            if cfg!(debug_assertions) { println!("[Parser] Finished line:\n{:?}", current_line) }
32
33            current_line.clear();
34            continue;
35        }
36
37        match parse_statement(window)
38        {
39            Ok(stat) => {
40                if cfg!(debug_assertions) { println!("[Parser] Parsed statement: {:?}", stat) }
41                current_line.push(stat);
42            },
43
44            error => {
45                if cfg!(debug_assertions) {
46                    println!("[Parser] Erroring out, line so far:\n{:?}", line_vec);
47                    println!("[Parser] Erroring out, window state:\n{:?}", window.get_window(3));
48                }
49                error?;
50            }
51        }
52    }
53
54    if current_line.is_empty() == false
55    {
56        line_vec.push(Line(current_line.clone()));
57    }
58
59    Ok(Program(line_vec))
60}
61
62pub fn parse_line(window: &mut VecWindow<Token>) -> Result<Line, StatError>
63{
64    let mut stat_vec: Vec<Stat> = Vec::new();
65    while window.remaining_length() > 0
66    {
67        if let Some(Token::Newline) = window.get_value(0)
68        {
69            window.move_view(1);
70            if cfg!(debug_assertions) { println!("[Parser] Finished line:\n{:?}", stat_vec) }
71            break;
72        }
73
74        match parse_statement(window)
75        {
76            Ok(stat) => {
77                if cfg!(debug_assertions) { println!("[Parser] Parsed statement: {:?}", stat) }
78                stat_vec.push(stat);
79            }
80
81            error => {
82                if cfg!(debug_assertions) {
83                    println!("[Parser] Erroring out, line so far:\n{:?}", stat_vec);
84                    println!("[Parser] Erroring out, window state:\n{:?}", window.get_window(3));
85                }
86                error?;
87            }
88        }
89    }
90
91    Ok(Line(stat_vec))
92}
93
94fn parse_statement(window: &mut VecWindow<Token>) -> Result<Stat, StatError>
95{
96    let value_tuple = (window.get_value(0), window.get_value(1), window.get_value(2));
97    if cfg!(debug_assertions) { println!("[Parse Stat] Matching slice: {:?}", value_tuple) }
98
99    let statement = match value_tuple
100    {
101        (Some(Token::Comment(comment)), _, _) => {
102            let comment_string = comment.clone();
103            window.move_view(1);
104            Stat::Comment(comment_string)
105        } 
106
107        (Some(Token::Goto), _, _) => {
108            window.move_view(1);
109            Stat::Goto(parse_expression(window)?)
110        },
111
112        (Some(Token::If), _, _) => {
113            window.move_view(1);
114            extend_if(window)?
115        },
116
117        (Some(ident @ Token::Identifier(_)), Some(Token::Plus), Some(Token::Equal)) => {
118            let value = Value::from(ident.clone());
119            window.move_view(3);
120            Stat::Assignment(value, Op::AddAssign, parse_expression(window)?)
121        },
122
123        (Some(ident @ Token::Identifier(_)), Some(Token::Minus), Some(Token::Equal)) => {
124            let value = Value::from(ident.clone());
125            window.move_view(3);
126            Stat::Assignment(value, Op::SubAssign, parse_expression(window)?)
127        },
128
129        (Some(ident @ Token::Identifier(_)), Some(Token::Star), Some(Token::Equal)) => {
130            let value = Value::from(ident.clone());
131            window.move_view(3);
132            Stat::Assignment(value, Op::MulAssign, parse_expression(window)?)
133        },
134
135        (Some(ident @ Token::Identifier(_)), Some(Token::Slash), Some(Token::Equal)) => {
136            let value = Value::from(ident.clone());
137            window.move_view(3);
138            Stat::Assignment(value, Op::DivAssign, parse_expression(window)?)
139        },
140
141        (Some(ident @ Token::Identifier(_)), Some(Token::Percent), Some(Token::Equal)) => {
142            let value = Value::from(ident.clone());
143            window.move_view(3);
144            Stat::Assignment(value, Op::ModAssign, parse_expression(window)?)
145        },
146
147        (Some(ident @ Token::Identifier(_)), Some(Token::Equal), Some(tok)) if *tok != Token::Equal => {
148            let value = Value::from(ident.clone());
149            window.move_view(2);
150            Stat::Assignment(value, Op::Assign, parse_expression(window)?)
151        },
152
153        _ => Stat::Expression(parse_expression(window)?)
154    };
155
156    Ok(statement)
157}
158
159fn extend_if(window: &mut VecWindow<Token>) -> Result<Stat, StatError>
160{
161    let condition = parse_expression(window)?;
162
163    if cfg!(debug_assertions) { println!("[Parse If] Condition: {:?}", condition) }
164
165    match window.get_value(0)
166    {
167        Some(Token::Then) => {
168            window.move_view(1);
169        },
170        
171        tok => return Err(StatError::new(None,
172                        ParseErrorKind::NoExtensionAvailable,
173                        &format!("Can't find 'then' to extend if. Found: {:?}", tok)))
174    }
175
176    let mut body: Vec<Stat> = Vec::new();
177    let mut else_body: Vec<Stat> = Vec::new();
178    let mut parsing_else = false;
179    let mut hit_end = false;
180
181    while window.remaining_length() > 0
182    {
183        let value_tuple = (window.get_value(0), window.get_value(1));
184        let statement = match value_tuple
185        {
186            (Some(Token::Else), _) => {
187                if parsing_else
188                {
189                    let error_stat = Stat::If(condition, body, Some(else_body));
190                    return Err(StatError::new(Some(error_stat),
191                                ParseErrorKind::RepeatedElseTokens,
192                                "Found an else token after already finding one for this if!"))
193                }
194                window.move_view(1);
195                parsing_else = true;
196                continue
197            },
198            (Some(Token::End), _) => {
199                window.move_view(1);
200                hit_end = true;
201                break
202            },
203
204            _ => parse_statement(window)?
205        };
206
207        if parsing_else
208        {
209            else_body.push(statement)
210        }
211        else
212        {
213            body.push(statement)
214        }
215    }
216
217
218    let final_else = if else_body.is_empty() == false
219    {
220        Some(else_body)
221    }
222    else
223    {
224        None
225    };
226
227    let out_stat = Stat::If(condition, body, final_else);
228
229    if hit_end == false
230    {
231        return Err(StatError::new(Some(out_stat), ParseErrorKind::NoExtensionAvailable, "Didn't hit end while parsing if statement!"));
232    }
233
234    Ok(out_stat)
235}
236
237fn parse_expression(window: &mut VecWindow<Token>) -> Result<Box<Expr>, ExprError>
238{
239    Ok(Box::new(expr_and(window)?))
240}
241
242fn expr_and(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
243{
244    match expr_or(window)
245    {
246        // The lower rule did match, so attempt to extend
247        Ok(expr) => {
248            match window.get_value(0)
249            {
250                Some(Token::And) => {
251                    extend_and(expr, window)
252                },
253
254                _ => Ok(expr)
255            }
256        },
257        // An error occurred in a lower rule, this is bad, throw back up the error
258        error @ Err(_) => {
259            error
260        },
261    }
262}
263
264fn extend_and(left: Expr, window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
265{
266    let op = match window.get_value(0)
267    {
268        Some(Token::And) => {
269            Op::And
270        },
271
272        _ => return Ok(left)
273    };
274
275    window.move_view(1);
276    match expr_or(window)
277    {
278        Ok(right) => {
279            // Found a right hand side for our rule, so construct the object
280            let expr = Expr::BinaryOp(op, Box::new(left), Box::new(right));
281            extend_and(expr, window)
282        }
283
284        _ => Err(ExprError::new(Some(left), ParseErrorKind::NoExtensionAvailable, "Syntax error in parsing an and!"))
285    }
286}
287
288fn expr_or(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
289{
290    match expr_equality(window)
291    {
292        // The lower rule did match, so attempt to extend
293        Ok(expr) => {
294            match window.get_value(0)
295            {
296                Some(Token::Or) => {
297                    extend_or(expr, window)
298                },
299
300                _ => Ok(expr)
301            }
302        },
303        // An error occurred in a lower rule, this is bad, throw back up the error
304        error @ Err(_) => {
305            error
306        },
307    }
308}
309
310fn extend_or(left: Expr, window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
311{
312    let op = match window.get_value(0)
313    {
314        Some(Token::Or) => {
315            Op::Or
316        },
317
318        _ => return Ok(left)
319    };
320
321    window.move_view(1);
322    match expr_equality(window)
323    {
324        Ok(right) => {
325            // Found a right hand side for our rule, so construct the object
326            let expr = Expr::BinaryOp(op, Box::new(left), Box::new(right));
327            extend_or(expr, window)
328        }
329
330        _ => Err(ExprError::new(Some(left), ParseErrorKind::NoExtensionAvailable, "Syntax error in parsing an or!"))
331    }
332}
333
334fn expr_equality(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
335{
336    match expr_order(window)
337    {
338        // The lower rule did match, so attempt to extend
339        Ok(expr) => {
340            let value_tuple = (window.get_value(0), window.get_value(1));
341            match value_tuple
342            {
343                (Some(Token::Equal), Some(Token::Equal)) |
344                (Some(Token::Exclam), Some(Token::Equal)) => {
345                    extend_equality(expr, window)
346                },
347
348                _ => Ok(expr)
349            }
350        },
351        // An error occurred in a lower rule, this is bad, throw back up the error
352        error @ Err(_) => {
353            error
354        },
355    }
356}
357
358fn extend_equality(left: Expr, window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
359{
360    let op = match (window.get_value(0), window.get_value(1))
361    {
362        (Some(Token::Equal), Some(Token::Equal)) => {
363            Op::Equal
364        },
365
366        (Some(Token::Exclam), Some(Token::Equal)) => {
367            Op::NotEqual
368        },
369
370        _ => return Ok(left)
371    };
372
373    window.move_view(2);
374    match expr_order(window)
375    {
376        Ok(right) => {
377            // Found a right hand side for our rule, so construct the object
378            let expr = Expr::BinaryOp(op, Box::new(left), Box::new(right));
379            extend_equality(expr, window)
380        }
381
382        _ => Err(ExprError::new(Some(left), ParseErrorKind::NoExtensionAvailable, "Syntax error in parsing an equality!"))
383    }
384}
385
386fn expr_order(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
387{
388    match expr_additive(window)
389    {
390        // The lower rule did match, so attempt to extend
391        Ok(expr) => {
392            let value_tuple = (window.get_value(0), window.get_value(1));
393            match value_tuple
394            {
395                (Some(Token::LAngleBrak), Some(Token::Equal)) |
396                (Some(Token::LAngleBrak), _) |
397                (Some(Token::RAngleBrak), Some(Token::Equal)) |
398                (Some(Token::RAngleBrak), _) => {
399                    extend_order(expr, window)
400                },
401
402                _ => Ok(expr)
403            }
404        },
405        // An error occurred in a lower rule, this is bad, throw back up the error
406        error @ Err(_) => {
407            error
408        },
409    }
410}
411
412fn extend_order(left: Expr, window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
413{
414    let op = match (window.get_value(0), window.get_value(1))
415    {
416        (Some(Token::LAngleBrak), Some(Token::Equal)) => {
417            window.move_view(2);
418            Op::LesserEq
419        },
420        (Some(Token::LAngleBrak), _) => {
421            window.move_view(1);
422            Op::Lesser
423        },
424
425        (Some(Token::RAngleBrak), Some(Token::Equal)) => {
426            window.move_view(2);
427            Op::GreaterEq
428        },
429        (Some(Token::RAngleBrak), _) => {
430            window.move_view(1);
431            Op::Greater
432        },
433
434        _ => return Ok(left)
435    };
436
437    match expr_additive(window)
438    {
439        Ok(right) => {
440            // Found a right hand side for our rule, so construct the object
441            let expr = Expr::BinaryOp(op, Box::new(left), Box::new(right));
442            extend_order(expr, window)
443        }
444
445        _ => Err(ExprError::new(Some(left), ParseErrorKind::NoExtensionAvailable, "Syntax error in parsing an order!"))
446    }
447}
448
449fn expr_additive(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
450{
451    match expr_multiply(window)
452    {
453        // The lower rule did match, so attempt to extend
454        Ok(expr) => {
455            match window.get_value(0)
456            {
457                Some(Token::Plus) |
458                Some(Token::Minus) => {
459                    extend_additive(expr, window)
460                }
461
462                _ => Ok(expr)
463            }
464        },
465        // An error occurred in a lower rule, this is bad, throw back up the error
466        error @ Err(_) => {
467            error
468        },
469    }
470}
471
472fn extend_additive(left: Expr, window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
473{
474    let op = match window.get_value(0)
475    {
476        Some(Token::Plus) => {
477            Op::Add
478        },
479
480        Some(Token::Minus) => {
481            Op::Sub
482        },
483
484        _ => return Ok(left)
485    };
486
487    window.move_view(1);
488    match expr_multiply(window)
489    {
490        Ok(right) => {
491            // Found a right hand side for our rule, so construct the object
492            let expr = Expr::BinaryOp(op, Box::new(left), Box::new(right));
493            extend_additive(expr, window)
494        }
495
496        _ => Err(ExprError::new(Some(left), ParseErrorKind::NoExtensionAvailable, "Syntax error in parsing an additive!"))
497    }
498}
499
500fn expr_multiply(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
501{
502    match expr_exponent(window)
503    {
504        // The lower rule did match, so attempt to extend
505        Ok(expr) => {
506            match window.get_value(0)
507            {
508                Some(Token::Slash) |
509                Some(Token::Star)  |
510                Some(Token::Percent) => {
511                    extend_multiply(expr, window)
512                },
513
514                _ => Ok(expr)
515            }
516        },
517        // An error occurred in a lower rule, this is bad, throw back up the error
518        error @ Err(_) => {
519            error
520        },
521    }
522}
523
524fn extend_multiply(left: Expr, window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
525{
526    let op = match window.get_value(0)
527    {
528        Some(Token::Slash) => {
529            Op::Div
530        },
531
532        Some(Token::Star) => {
533            Op::Mul
534        },
535
536        Some(Token::Percent) => {
537            Op::Mod
538        },
539
540        _ => return Ok(left)
541    };
542
543    window.move_view(1);
544    match expr_exponent(window)
545    {
546        Ok(right) => {
547            // Found a right hand side for our rule, so construct the object
548            let expr = Expr::BinaryOp(op, Box::new(left), Box::new(right));
549            extend_multiply(expr, window)
550        }
551
552        _ => Err(ExprError::new(Some(left), ParseErrorKind::NoExtensionAvailable, "Syntax error in parsing a multiply!"))
553    }
554}
555
556// Doesn't use extension idiom due to being right associative
557fn expr_exponent(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
558{
559    match expr_postfix(window)
560    {
561        // The lower rule did match, so attempt to extend
562        Ok(expr) => {
563            match window.get_value(0)
564            {
565                Some(Token::Caret) => {
566                    window.move_view(1);
567                    let left = Box::new(expr);
568                    let right = Box::new(expr_exponent(window)?);
569
570                    Ok(Expr::BinaryOp(Op::Pow, left, right))
571                },
572                _ => Ok(expr)
573            }
574        },
575        // An error occurred in a lower rule, this is bad, throw back up the error
576        error @ Err(_) => {
577            error
578        },
579    }
580}
581
582fn expr_postfix(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
583{
584    match expr_keyword(window)
585    {
586        // The lower rule did match, so attempt to extend to form this rule
587        Ok(expr) => Ok(extend_postfix(expr, window)),
588
589        // An error occurred in a lower rule, this is bad, throw back up the error
590        error @ Err(_) => {
591            error
592        },
593    }
594}
595
596fn extend_postfix(expr: Expr, window: &mut VecWindow<Token>) -> Expr
597{
598    match (window.get_value(0), window.get_value(1))
599    {
600        (Some(Token::Exclam), Some(Token::Equal)) => expr,
601        (Some(Token::Exclam), _) => {
602            window.move_view(1);
603            extend_postfix(Expr::UnaryOp(Op::Fact, Box::new(expr)), window)
604        }
605        _ => expr
606    }
607}
608
609fn expr_keyword(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
610{
611    match expr_neg(window)
612    {
613        // The rule below simply didn't match onto the window, so now it's our turn
614        Err(ExprError { kind: ParseErrorKind::NoParseRuleMatch, .. }) => {
615            match window.get_value(0)
616            {
617                Some(Token::Abs) => {
618                    window.move_view(1);
619                    let operand = Box::new(expr_keyword(window)?);
620
621                    Ok(Expr::UnaryOp(Op::Abs, operand))
622                },
623                Some(Token::Sqrt) => {
624                    window.move_view(1);
625                    let operand = Box::new(expr_keyword(window)?);
626
627                    Ok(Expr::UnaryOp(Op::Sqrt, operand))
628                },
629                Some(Token::Sin) => {
630                    window.move_view(1);
631                    let operand = Box::new(expr_keyword(window)?);
632
633                    Ok(Expr::UnaryOp(Op::Sin, operand))
634                },
635                Some(Token::Cos) => {
636                    window.move_view(1);
637                    let operand = Box::new(expr_keyword(window)?);
638
639                    Ok(Expr::UnaryOp(Op::Cos, operand))
640                },
641                Some(Token::Tan) => {
642                    window.move_view(1);
643                    let operand = Box::new(expr_keyword(window)?);
644
645                    Ok(Expr::UnaryOp(Op::Tan, operand))
646                },
647                Some(Token::Arcsin) => {
648                    window.move_view(1);
649                    let operand = Box::new(expr_keyword(window)?);
650
651                    Ok(Expr::UnaryOp(Op::Arcsin, operand))
652                },
653                Some(Token::Arccos) => {
654                    window.move_view(1);
655                    let operand = Box::new(expr_keyword(window)?);
656
657                    Ok(Expr::UnaryOp(Op::Arccos, operand))
658                },
659                Some(Token::Arctan) => {
660                    window.move_view(1);
661                    let operand = Box::new(expr_keyword(window)?);
662
663                    Ok(Expr::UnaryOp(Op::Arctan, operand))
664                },
665                Some(Token::Not) => {
666                    window.move_view(1);
667                    let operand = Box::new(expr_keyword(window)?);
668
669                    Ok(Expr::UnaryOp(Op::Not, operand))
670                },
671
672                _ => Err(ExprError::new(None,
673                        ParseErrorKind::NoParseRuleMatch,
674                        "In expr_keyword, can't find keyword operator after lower rule failed to match!"))
675            }
676        },
677        // The lower rule did match, so just pass back up the expression it created
678        expr @ Ok(_) => {
679            expr
680        }
681        // A different error occurred in a lower rule, this is bad, throw back up the error
682        error @ Err(_) => {
683            error
684        },
685    }
686}
687
688fn expr_neg(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
689{
690    match expr_ident(window)
691    {
692        // The rule below simply didn't match onto the window, so now it's our turn
693        Err(ExprError { kind: ParseErrorKind::NoParseRuleMatch, .. }) => {
694            match window.get_value(0)
695            {
696                Some(Token::Minus) => {
697                    window.move_view(1);
698                    let operand = Box::new(expr_neg(window)?);
699
700                    Ok(Expr::UnaryOp(Op::Negate, operand))
701                }
702
703                _ => {
704                    Err(ExprError::new(None,
705                        ParseErrorKind::NoParseRuleMatch,
706                        "In expr_neg, can't find minus after lower rule failed to match!"))
707                }
708            }
709        },
710        // The lower rule did match, so just pass back up the expression it created
711        expr @ Ok(_) => {
712            expr
713        }
714        // A different error occurred in a lower rule, this is bad, throw back up the error
715        error @ Err(_) => {
716            error
717        },
718    }
719}
720
721fn expr_ident(window: &mut VecWindow<Token>) -> Result<Expr, ExprError>
722{
723    let value_tuple = (window.get_value(0), window.get_value(1), window.get_value(2));
724    let expr = match value_tuple
725    {
726        // Postfix inc/dec operator parsing
727        (Some(ident @ Token::Identifier(_)), Some(Token::Plus), Some(Token::Plus)) => {
728            let value = Value::from(ident.clone());
729            window.move_view(3);
730            
731            Expr::UnaryOp(Op::PostInc, Box::new(Expr::Value(value)))
732        },
733        (Some(ident @ Token::Identifier(_)), Some(Token::Minus), Some(Token::Minus)) => {
734            let value = Value::from(ident.clone());
735            window.move_view(3);
736
737            Expr::UnaryOp(Op::PostDec, Box::new(Expr::Value(value)))
738        },
739
740        // Prefix inc/dec operator parsing
741        (Some(Token::Plus), Some(Token::Plus), Some(ident @ Token::Identifier(_))) => {
742            let value = Value::from(ident.clone());
743            window.move_view(3);
744
745            Expr::UnaryOp(Op::PreInc, Box::new(Expr::Value(value)))
746        },
747        (Some(Token::Minus), Some(Token::Minus), Some(ident @ Token::Identifier(_))) => {
748            let value = Value::from(ident.clone());
749            window.move_view(3);
750
751            Expr::UnaryOp(Op::PreDec, Box::new(Expr::Value(value)))
752        },
753
754        // Parses into any value, which is then wrapped into an expression
755        _ => Expr::Value(parse_value(window)?)
756    };
757
758    Ok(expr)
759}
760
761
762fn parse_value(window: &mut VecWindow<Token>) -> Result<Value, ExprError>
763{
764    match window.get_value(0)
765    {
766        Some(tok @ Token::StringToken(_)) |
767        Some(tok @ Token::YololNum(_)) |
768        Some(tok @ Token::Identifier(_)) => {
769            let tok = tok.clone();
770            window.move_view(1);
771
772            Ok(Value::from(tok))
773        },
774
775        Some(Token::LParen) => {
776            window.move_view(1);
777            let output = parse_expression(window)?;
778
779            match window.get_value(0)
780            {
781                Some(Token::RParen) => {
782                    window.move_view(1);
783                    Ok(Value::Group(output))
784                },
785
786                _ => Err(ExprError::new(Some(*output), ParseErrorKind::UnbalancedParenthesis, "Saw LParen, parsed expr, found no RParen!"))
787            }
788        },
789
790        _ => Err(ExprError::new(None, ParseErrorKind::NoParseRuleMatch, "No match while parsing value!"))
791    }
792}
793
794