datex_core/parser/parsers/
list.rs1use 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}