1use super::*;
2
3impl Parser {
4 fn is_upper_camel_segment(name: &str) -> bool {
5 name.chars().next().is_some_and(|c| c.is_uppercase())
6 }
7
8 fn is_constructor_path(path: &str) -> bool {
9 path.rsplit('.')
10 .next()
11 .is_some_and(Self::is_upper_camel_segment)
12 }
13
14 fn reject_zero_arg_constructor_call(&self, path: &str) -> Result<(), ParseError> {
15 if Self::is_constructor_path(path) && self.peek(1).kind == TokenKind::RParen {
16 return Err(self.error(format!(
17 "Zero-argument constructor call '{}()' is not allowed. Use '{}' (no parentheses).",
18 path, path
19 )));
20 }
21 Ok(())
22 }
23
24 pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
25 self.parse_comparison()
26 }
27
28 pub(super) fn parse_comparison(&mut self) -> Result<Expr, ParseError> {
29 let mut left = self.parse_additive()?;
30
31 loop {
32 let op = match &self.current().kind {
33 TokenKind::Eq => BinOp::Eq,
34 TokenKind::Neq => BinOp::Neq,
35 TokenKind::Lt => BinOp::Lt,
36 TokenKind::Gt => BinOp::Gt,
37 TokenKind::Lte => BinOp::Lte,
38 TokenKind::Gte => BinOp::Gte,
39 _ => break,
40 };
41 self.advance();
42 let right = self.parse_additive()?;
43 left = Expr::BinOp(op, Box::new(left), Box::new(right));
44 }
45
46 Ok(left)
47 }
48
49 pub(super) fn parse_additive(&mut self) -> Result<Expr, ParseError> {
50 let mut left = self.parse_multiplicative()?;
51
52 loop {
53 let op = match &self.current().kind {
54 TokenKind::Plus => BinOp::Add,
55 TokenKind::Minus => BinOp::Sub,
56 _ => break,
57 };
58 self.advance();
59 let right = self.parse_multiplicative()?;
60 left = Expr::BinOp(op, Box::new(left), Box::new(right));
61 }
62
63 Ok(left)
64 }
65
66 pub(super) fn parse_multiplicative(&mut self) -> Result<Expr, ParseError> {
67 let mut left = self.parse_unary()?;
68
69 loop {
70 let op = match &self.current().kind {
71 TokenKind::Star => BinOp::Mul,
72 TokenKind::Slash => BinOp::Div,
73 _ => break,
74 };
75 self.advance();
76 let right = self.parse_unary()?;
77 left = Expr::BinOp(op, Box::new(left), Box::new(right));
78 }
79
80 Ok(left)
81 }
82
83 pub(super) fn parse_unary(&mut self) -> Result<Expr, ParseError> {
84 if self.check_exact(&TokenKind::Minus) {
85 self.advance();
86 let operand = self.parse_postfix()?;
87 return Ok(Expr::BinOp(
88 BinOp::Sub,
89 Box::new(Expr::Literal(Literal::Int(0))),
90 Box::new(operand),
91 ));
92 }
93 self.parse_postfix()
94 }
95
96 pub(super) fn parse_postfix(&mut self) -> Result<Expr, ParseError> {
97 let mut expr = self.parse_call_or_atom()?;
98
99 loop {
100 if self.check_exact(&TokenKind::Question) {
101 self.advance();
102 expr = Expr::ErrorProp(Box::new(expr));
103 } else if self.check_exact(&TokenKind::Dot) {
104 self.advance();
105 let field_tok = self.expect_kind(
106 &TokenKind::Ident(String::new()),
107 "Expected field name after '.'",
108 )?;
109 let field = match field_tok.kind {
110 TokenKind::Ident(s) => s,
111 _ => unreachable!(),
112 };
113 expr = Expr::Attr(Box::new(expr), field);
114 if self.check_exact(&TokenKind::LParen) {
115 if let Some(path) = Self::dotted_name(&expr)
117 && path.ends_with(".update")
118 {
119 let prefix = &path[..path.len() - ".update".len()];
120 if !prefix.is_empty()
121 && prefix.chars().next().is_some_and(|c| c.is_uppercase())
122 {
123 self.advance(); let base = self.parse_expr()?;
125 let updates = if self.check_exact(&TokenKind::Comma) {
126 self.advance();
127 self.skip_formatting();
128 self.parse_record_create_fields()?
129 } else {
130 Vec::new()
131 };
132 self.expect_exact(&TokenKind::RParen)?;
133 expr = Expr::RecordUpdate {
134 type_name: prefix.to_string(),
135 base: Box::new(base),
136 updates,
137 };
138 continue;
139 }
140 }
141 if let Some(path) = Self::dotted_name(&expr) {
142 self.reject_zero_arg_constructor_call(&path)?;
143 }
144 let named_arg_start = matches!(&self.peek(1).kind, TokenKind::Ident(_))
145 && self.peek(2).kind == TokenKind::Assign;
146 if named_arg_start && let Some(path) = Self::dotted_name(&expr) {
147 self.advance();
149 let fields = self.parse_record_create_fields()?;
150 self.expect_exact(&TokenKind::RParen)?;
151 expr = Expr::RecordCreate {
152 type_name: path,
153 fields,
154 };
155 } else {
156 self.advance();
157 let args = self.parse_args()?;
158 self.expect_exact(&TokenKind::RParen)?;
159 expr = Expr::FnCall(Box::new(expr), args);
160 }
161 }
162 } else {
163 break;
164 }
165 }
166
167 Ok(expr)
168 }
169
170 pub(super) fn dotted_name(expr: &Expr) -> Option<String> {
171 match expr {
172 Expr::Ident(name) => Some(name.clone()),
173 Expr::Attr(inner, field) => {
174 let mut base = Self::dotted_name(inner)?;
175 base.push('.');
176 base.push_str(field);
177 Some(base)
178 }
179 _ => None,
180 }
181 }
182
183 pub(super) fn parse_call_or_atom(&mut self) -> Result<Expr, ParseError> {
184 let atom = self.parse_atom()?;
185
186 if self.check_exact(&TokenKind::LParen) {
187 if let Some(path) = Self::dotted_name(&atom) {
188 self.reject_zero_arg_constructor_call(&path)?;
189 }
190
191 let is_record_create = if let Expr::Ident(ref name) = atom {
195 name.chars().next().is_some_and(|c| c.is_uppercase())
196 && matches!(&self.peek_skip_formatting(1).kind, TokenKind::Ident(_))
197 && self.peek_skip_formatting(2).kind == TokenKind::Assign
198 } else {
199 false
200 };
201 let named_arg_start = matches!(&self.peek_skip_formatting(1).kind, TokenKind::Ident(_))
202 && self.peek_skip_formatting(2).kind == TokenKind::Assign;
203
204 if is_record_create && let Expr::Ident(type_name) = atom {
205 self.advance(); let fields = self.parse_record_create_fields()?;
207 self.expect_exact(&TokenKind::RParen)?;
208 return Ok(Expr::RecordCreate { type_name, fields });
209 }
210
211 if named_arg_start && let Some(path) = Self::dotted_name(&atom) {
213 self.advance();
214 let fields = self.parse_record_create_fields()?;
215 self.expect_exact(&TokenKind::RParen)?;
216 return Ok(Expr::RecordCreate {
217 type_name: path,
218 fields,
219 });
220 }
221
222 self.advance();
223 let args = self.parse_args()?;
224 self.expect_exact(&TokenKind::RParen)?;
225 return Ok(Expr::FnCall(Box::new(atom), args));
226 }
227
228 Ok(atom)
229 }
230
231 pub(super) fn parse_record_create_fields(&mut self) -> Result<Vec<(String, Expr)>, ParseError> {
233 let mut fields = Vec::new();
234 self.skip_formatting();
235
236 while !self.check_exact(&TokenKind::RParen) && !self.is_eof() {
237 if self.check_exact(&TokenKind::Comma) {
238 self.advance();
239 self.skip_formatting();
240 continue;
241 }
242 let name_tok =
243 self.expect_kind(&TokenKind::Ident(String::new()), "Expected field name")?;
244 let field_name = match name_tok.kind {
245 TokenKind::Ident(s) => s,
246 _ => unreachable!(),
247 };
248 self.expect_exact(&TokenKind::Assign)?;
249 let value = self.parse_expr()?;
250 fields.push((field_name, value));
251 self.skip_formatting();
252 }
253
254 Ok(fields)
255 }
256
257 pub(super) fn parse_args(&mut self) -> Result<Vec<Expr>, ParseError> {
258 let mut args = Vec::new();
259 self.skip_formatting();
260
261 while !self.check_exact(&TokenKind::RParen) && !self.is_eof() {
262 if self.check_exact(&TokenKind::Comma) {
263 self.advance();
264 self.skip_formatting();
265 continue;
266 }
267 args.push(self.parse_expr()?);
268 self.skip_formatting();
269 }
270
271 Ok(args)
272 }
273
274 pub(super) fn parse_map_literal(&mut self) -> Result<Expr, ParseError> {
275 self.expect_exact(&TokenKind::LBrace)?;
276 let mut entries = Vec::new();
277 self.skip_formatting();
278
279 while !self.check_exact(&TokenKind::RBrace) && !self.is_eof() {
280 if self.check_exact(&TokenKind::Comma) {
281 self.advance();
282 self.skip_formatting();
283 continue;
284 }
285
286 let key = self.parse_expr()?;
287 self.skip_formatting();
288 if !self.check_exact(&TokenKind::FatArrow) {
289 return Err(
290 self.error("Expected '=>' between key and value in map literal".to_string())
291 );
292 }
293 self.advance(); self.skip_formatting();
295 let value = self.parse_expr()?;
296 entries.push((key, value));
297 self.skip_formatting();
298
299 if self.check_exact(&TokenKind::Comma) {
300 self.advance();
301 self.skip_formatting();
302 }
303 }
304
305 self.expect_exact(&TokenKind::RBrace)?;
306 Ok(Expr::MapLiteral(entries))
307 }
308
309 pub(super) fn parse_atom(&mut self) -> Result<Expr, ParseError> {
310 match self.current().kind.clone() {
311 TokenKind::Int(i) => {
312 self.advance();
313 Ok(Expr::Literal(Literal::Int(i)))
314 }
315 TokenKind::Float(f) => {
316 self.advance();
317 Ok(Expr::Literal(Literal::Float(f)))
318 }
319 TokenKind::Str(s) => {
320 self.advance();
321 Ok(Expr::Literal(Literal::Str(s)))
322 }
323 TokenKind::InterpStr(parts) => {
324 self.advance();
325 let mut str_parts = Vec::new();
326 for (is_expr, s) in parts {
327 if is_expr {
328 if s.trim().is_empty() {
330 str_parts.push(StrPart::Literal(String::new()));
331 } else {
332 let mut lexer = crate::lexer::Lexer::new(&s);
333 let tokens = lexer.tokenize().map_err(|e| ParseError::Error {
334 msg: format!("Error in interpolation: {}", e),
335 line: self.current().line,
336 col: self.current().col,
337 })?;
338 let mut sub_parser = Parser::new(tokens);
339 let expr = sub_parser.parse_expr().map_err(|e| ParseError::Error {
340 msg: format!("Error in interpolation: {}", e),
341 line: self.current().line,
342 col: self.current().col,
343 })?;
344 str_parts.push(StrPart::Parsed(Box::new(expr)));
345 }
346 } else {
347 str_parts.push(StrPart::Literal(s));
348 }
349 }
350 Ok(Expr::InterpolatedStr(str_parts))
351 }
352 TokenKind::Bool(b) => {
353 self.advance();
354 Ok(Expr::Literal(Literal::Bool(b)))
355 }
356 TokenKind::Match => self.parse_match(),
357 TokenKind::LParen => {
358 self.advance();
359 let first = self.parse_expr()?;
360 if self.check_exact(&TokenKind::Comma) {
361 let mut items = vec![first];
362 while self.check_exact(&TokenKind::Comma) {
363 self.advance();
364 items.push(self.parse_expr()?);
365 }
366 self.expect_exact(&TokenKind::RParen)?;
367 Ok(Expr::Tuple(items))
368 } else {
369 self.expect_exact(&TokenKind::RParen)?;
370 Ok(first)
371 }
372 }
373 TokenKind::Ident(s) => {
374 self.advance();
375 if s == "Unit" {
376 Ok(Expr::Literal(Literal::Unit))
377 } else {
378 Ok(Expr::Ident(s))
379 }
380 }
381 TokenKind::LBracket => {
382 self.advance(); let mut elements = Vec::new();
384 self.skip_formatting();
385 while !self.check_exact(&TokenKind::RBracket) && !self.is_eof() {
386 if self.check_exact(&TokenKind::Comma) {
387 self.advance();
388 self.skip_formatting();
389 continue;
390 }
391 elements.push(self.parse_expr()?);
392 self.skip_formatting();
393 }
394 self.expect_exact(&TokenKind::RBracket)?;
395 Ok(Expr::List(elements))
396 }
397 TokenKind::LBrace => self.parse_map_literal(),
398 TokenKind::Fn => Err(self.error(
399 "Anonymous functions are not supported in Aver. Define a top-level function and pass its name."
400 .to_string(),
401 )),
402 _ => Err(self.error(format!(
403 "Expected expression (identifier, literal, '[', or '{{'), found {}",
404 self.current().kind
405 ))),
406 }
407 }
408}