rl_lang/parser/statements/
for_statement.rs1use crate::{
22 ast::{
23 nodes::ExpressionKind,
24 statements::{Statement, StatementKind},
25 },
26 lexer::tokentypes::TokenType,
27 parser::parser_logic::Parser,
28 utils::errors::Error,
29};
30
31impl Parser {
32 pub fn parse_for(&mut self, start: crate::utils::span::Span) -> Result<Statement, Error> {
49 if matches!(self.peek(), TokenType::LeftBracket) {
50 self.advance();
52 while self.match_type(&[TokenType::Newline]) {}
53 let init_start = self.peek_span();
54 let initializer = Box::new(self.parse_variable_declartion(init_start)?);
55 while self.match_type(&[TokenType::Newline]) {}
56 self.match_type(&[TokenType::Comma]);
57 while self.match_type(&[TokenType::Newline]) {}
58 let condition = self.parse_expression()?;
59 while self.match_type(&[TokenType::Newline]) {}
60 self.match_type(&[TokenType::Comma]);
61 while self.match_type(&[TokenType::Newline]) {}
62 let increment = self.parse_expression()?;
63 while self.match_type(&[TokenType::Newline]) {}
64 self.match_type(&[TokenType::RightBracket]);
65 while self.match_type(&[TokenType::Newline]) {}
66 let body = self.parse_block()?;
67 let span = start.join(self.previous_span());
68 Ok(Statement::new(
69 StatementKind::For {
70 initializer,
71 condition,
72 increment,
73 body,
74 },
75 span,
76 ))
77 } else if matches!(self.peek(), TokenType::Identifier(_)) {
78 while self.match_type(&[TokenType::Newline]) {}
80 let ident_expr = self.parse_expression()?;
81 let ident_id = self.ast_arena.exprs.get(ident_expr).clone();
82 let variable_name = match &ident_id.kind {
83 ExpressionKind::Identifier(name) => name,
84 _ => return Err(self.err("for-range expects identifier", ident_id.span)),
85 };
86 while self.match_type(&[TokenType::Newline]) {}
87 self.match_type(&[TokenType::In]);
88
89 while self.match_type(&[TokenType::Newline]) {}
90 let range = if (matches!(self.peek(), TokenType::NumberLiteral(_))
91 || (matches!(self.peek(), TokenType::ByteLiteral(_))))
92 {
93 let start_expr = self.parse_expression()?;
95 while self.match_type(&[TokenType::Newline]) {}
96 let start_id = self.ast_arena.exprs.get(start_expr);
97 let range_start = match start_id.kind {
98 ExpressionKind::Integer(i) => i,
99 ExpressionKind::Byte(b) => b as i64,
100 _ => return Err(self.err("range should be integers only", start_id.span)),
101 };
102 self.match_type(&[TokenType::DotDot]);
103 let end_expr = self.parse_expression()?;
104 let end_id = self.ast_arena.exprs.get(end_expr);
105 let range_end = match end_id.kind {
106 ExpressionKind::Integer(i) => i,
107 ExpressionKind::Byte(b) => b as i64,
108 _ => return Err(self.err("range should be integers only", end_id.span)),
109 };
110 let range_vec: Vec<i64> = (range_start..range_end).collect();
111 let span = start.join(self.previous_span());
112 Box::new(Statement::new(StatementKind::Range(range_vec), span))
113 } else if self.match_type(&[TokenType::LeftBracket]) {
114 let mut items = Vec::new();
116 while self.match_type(&[TokenType::Newline]) {}
117 while self.peek() != TokenType::RightBracket {
118 let value = self.parse_expression()?;
119 items.push(value);
120 while self.match_type(&[TokenType::Newline]) {}
121 if self.peek() == TokenType::RightBracket {
122 break;
123 }
124 while self.match_type(&[TokenType::Newline]) {}
125 if !self.match_type(&[TokenType::Comma]) {
126 return Err(self.err("expected ',' between list items", self.peek_span()));
127 }
128 }
129 while self.match_type(&[TokenType::Newline]) {}
130 self.match_type(&[TokenType::RightBracket]);
131 let mut iterable_list = Vec::new();
132 for item in items {
133 let item_id = self.ast_arena.exprs.get(item);
134 match item_id.kind {
135 ExpressionKind::Integer(i) => iterable_list.push(i),
136 ExpressionKind::Byte(b) => iterable_list.push(b as i64),
137 _ => return Err(self.err("list items must be integers", item_id.span)),
138 }
139 }
140 let span = start.join(self.previous_span());
141 Box::new(Statement::new(StatementKind::Range(iterable_list), span))
142 } else {
143 if matches!(self.peek(), TokenType::Identifier(_)) {
144 while self.match_type(&[TokenType::Newline]) {}
146 let iterable_expression = self.parse_expression()?;
147 while self.match_type(&[TokenType::Newline]) {}
148 let body = self.parse_block()?;
149 let span = start.join(self.previous_span());
150 return Ok(Statement::new(
151 StatementKind::ForEach {
152 variable: variable_name.clone(),
153 iterable: iterable_expression,
154 body,
155 },
156 span,
157 ));
158 }
159 return Err(self.err(
160 "expected range (e.g. 1..10), array literal ([1, 2, 3], or array variable",
161 self.peek_span(),
162 ));
163 };
164
165 while self.match_type(&[TokenType::Newline]) {}
166 let body = self.parse_block()?;
167 let span = start.join(self.previous_span());
168 Ok(Statement::new(
169 StatementKind::ForRange {
170 variable: variable_name.clone(),
171 range,
172 body,
173 },
174 span,
175 ))
176 } else {
177 Err(self.err("wrong usage of for", self.peek_span()))
178 }
179 }
180}