datex_core/parser/parsers/
list.rs

1use crate::ast::expressions::{DatexExpression, DatexExpressionData, List};
2use crate::ast::spanned::Spanned;
3use crate::parser::lexer::Token;
4use crate::parser::{Parser, SpannedParserError};
5
6impl Parser {
7    pub fn parse_list(
8        &mut self,
9    ) -> Result<DatexExpression, SpannedParserError> {
10        let start = self.expect(Token::LeftBracket)?.span.start;
11        let mut items = Vec::new();
12
13        while self.peek()?.token != Token::RightBracket {
14            let maybe_expression = self.parse_expression(0);
15            let expression = self.recover_on_error(
16                maybe_expression,
17                &[Token::Comma, Token::RightBracket],
18            )?;
19            items.push(expression);
20
21            if self.peek()?.token == Token::Comma {
22                self.advance()?;
23            }
24        }
25
26        let end = self.expect(Token::RightBracket)?.span.end;
27        Ok(DatexExpressionData::List(List { items }).with_span(start..end))
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use crate::ast::expressions::{DatexExpressionData, List};
34    use crate::ast::spanned::Spanned;
35    use crate::parser::errors::ParserError;
36    use crate::parser::lexer::Token;
37    use crate::parser::parser_result::ParserResult;
38    use crate::parser::tests::{
39        parse, try_parse_and_collect_errors,
40        try_parse_and_return_on_first_error,
41    };
42    use core::assert_matches::assert_matches;
43
44    #[test]
45    fn parse_empty_list() {
46        let expr = parse("[]");
47        assert_eq!(
48            expr.data,
49            DatexExpressionData::List(List { items: vec![] })
50        );
51    }
52
53    #[test]
54    fn parse_simple_list() {
55        let expr = parse("[true, false, null]");
56        assert_eq!(
57            expr.data,
58            DatexExpressionData::List(List {
59                items: vec![
60                    DatexExpressionData::Boolean(true).with_default_span(),
61                    DatexExpressionData::Boolean(false).with_default_span(),
62                    DatexExpressionData::Null.with_default_span(),
63                ]
64            })
65        );
66    }
67
68    #[test]
69    fn parse_list_with_trailing_comma() {
70        let expr = parse("[true, false, null,]");
71        assert_eq!(
72            expr.data,
73            DatexExpressionData::List(List {
74                items: vec![
75                    DatexExpressionData::Boolean(true).with_default_span(),
76                    DatexExpressionData::Boolean(false).with_default_span(),
77                    DatexExpressionData::Null.with_default_span(),
78                ]
79            })
80        );
81    }
82
83    #[test]
84    fn parse_list_with_wrong_close_paren() {
85        let result = try_parse_and_return_on_first_error("[true}");
86        assert!(result.is_err());
87        assert_matches!(
88            result.err().unwrap().error,
89            ParserError::UnexpectedToken {
90                found: Token::RightCurly,
91                ..
92            }
93        );
94    }
95
96    #[test]
97    fn parse_with_span() {
98        let expr = parse("[]");
99        assert_eq!(expr.span, 0..2);
100
101        let expr = parse("[true, false]");
102        assert_eq!(expr.span, 0..13);
103
104        let expr = parse(" [  true , false ] ");
105        assert_eq!(expr.span, 1..18);
106    }
107
108    #[test]
109    fn parse_recover_from_error() {
110        let res = try_parse_and_collect_errors("[true, x + , false]");
111        if let ParserResult::Invalid(res) = res {
112            assert_matches!(
113                res.errors[0].error,
114                ParserError::UnexpectedToken {
115                    found: Token::Comma,
116                    ..
117                }
118            );
119            assert_eq!(
120                res.ast.data,
121                DatexExpressionData::List(List {
122                    items: vec![
123                        DatexExpressionData::Boolean(true).with_default_span(),
124                        DatexExpressionData::Recover.with_default_span(),
125                        DatexExpressionData::Boolean(false).with_default_span(),
126                    ]
127                })
128            );
129        } else {
130            panic!("Expected invalid parser result");
131        }
132    }
133
134    #[test]
135    fn parse_recover_from_error_end() {
136        let res = try_parse_and_collect_errors("[true, x +]");
137        if let ParserResult::Invalid(res) = res {
138            assert_matches!(
139                res.errors[0].error,
140                ParserError::UnexpectedToken {
141                    found: Token::RightBracket,
142                    ..
143                }
144            );
145            assert_eq!(
146                res.ast.data,
147                DatexExpressionData::List(List {
148                    items: vec![
149                        DatexExpressionData::Boolean(true).with_default_span(),
150                        DatexExpressionData::Recover.with_default_span(),
151                    ]
152                })
153            );
154        } else {
155            panic!("Expected invalid parser result");
156        }
157    }
158}