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 fn spanned(&self, expr: Expr, line: usize) -> Spanned<Expr> {
26 Spanned::new(expr, line)
27 }
28
29 pub fn parse_expr(&mut self) -> Result<Spanned<Expr>, ParseError> {
30 self.parse_comparison()
31 }
32
33 pub(super) fn parse_comparison(&mut self) -> Result<Spanned<Expr>, ParseError> {
34 let mut left = self.parse_additive()?;
35
36 loop {
37 let line = self.current().line;
38 let op = match &self.current().kind {
39 TokenKind::Eq => BinOp::Eq,
40 TokenKind::Neq => BinOp::Neq,
41 TokenKind::Lt => BinOp::Lt,
42 TokenKind::Gt => BinOp::Gt,
43 TokenKind::Lte => BinOp::Lte,
44 TokenKind::Gte => BinOp::Gte,
45 _ => break,
46 };
47 self.advance();
48 let right = self.parse_additive()?;
49 left = self.spanned(Expr::BinOp(op, Box::new(left), Box::new(right)), line);
50 }
51
52 Ok(left)
53 }
54
55 pub(super) fn parse_additive(&mut self) -> Result<Spanned<Expr>, ParseError> {
56 let mut left = self.parse_multiplicative()?;
57
58 loop {
59 let line = self.current().line;
60 let op = match &self.current().kind {
61 TokenKind::Plus => BinOp::Add,
62 TokenKind::Minus => BinOp::Sub,
63 _ => break,
64 };
65 self.advance();
66 let right = self.parse_multiplicative()?;
67 left = self.spanned(Expr::BinOp(op, Box::new(left), Box::new(right)), line);
68 }
69
70 Ok(left)
71 }
72
73 pub(super) fn parse_multiplicative(&mut self) -> Result<Spanned<Expr>, ParseError> {
74 let mut left = self.parse_unary()?;
75
76 loop {
77 let line = self.current().line;
78 let op = match &self.current().kind {
79 TokenKind::Star => BinOp::Mul,
80 TokenKind::Slash => BinOp::Div,
81 _ => break,
82 };
83 self.advance();
84 let right = self.parse_unary()?;
85 left = self.spanned(Expr::BinOp(op, Box::new(left), Box::new(right)), line);
86 }
87
88 Ok(left)
89 }
90
91 pub(super) fn parse_unary(&mut self) -> Result<Spanned<Expr>, ParseError> {
92 if self.check_exact(&TokenKind::Minus) {
93 let line = self.current().line;
94 self.advance();
95 let operand = self.parse_postfix()?;
96 return Ok(self.spanned(
97 Expr::BinOp(
98 BinOp::Sub,
99 Box::new(Spanned::bare(Expr::Literal(Literal::Int(0)))),
100 Box::new(operand),
101 ),
102 line,
103 ));
104 }
105 self.parse_postfix()
106 }
107
108 pub(super) fn parse_postfix(&mut self) -> Result<Spanned<Expr>, ParseError> {
109 let mut expr = self.parse_call_or_atom()?;
110
111 loop {
112 if self.check_exact(&TokenKind::Question) && self.peek(1).kind == TokenKind::Bang {
113 let line = self.current().line;
115 if let Expr::Tuple(elements) = expr.node {
116 self.advance(); self.advance(); expr = self.spanned(Expr::IndependentProduct(elements, true), line);
119 } else {
120 return Err(self.error(
121 "Operator '?!' can only be applied to a tuple expression, e.g. (a, b)?!"
122 .to_string(),
123 ));
124 }
125 } else if self.check_exact(&TokenKind::Bang)
126 && !matches!(self.peek(1).kind, TokenKind::LBracket)
127 {
128 let line = self.current().line;
131 if let Expr::Tuple(elements) = expr.node {
132 self.advance(); expr = self.spanned(Expr::IndependentProduct(elements, false), line);
134 } else {
135 break; }
137 } else if self.check_exact(&TokenKind::Question) {
138 let line = self.current().line;
139 self.advance();
140 expr = self.spanned(Expr::ErrorProp(Box::new(expr)), line);
141 } else if self.check_exact(&TokenKind::Dot) {
142 let dot_line = self.current().line;
143 self.advance();
144 let field_tok = self.expect_kind(
145 &TokenKind::Ident(String::new()),
146 "Expected field name after '.'",
147 )?;
148 let field = match field_tok.kind {
149 TokenKind::Ident(s) => s,
150 _ => unreachable!(),
151 };
152 expr = self.spanned(Expr::Attr(Box::new(expr), field), dot_line);
153 if self.check_exact(&TokenKind::LParen) {
154 if let Some(path) = Self::dotted_name(&expr)
156 && path.ends_with(".update")
157 {
158 let prefix = &path[..path.len() - ".update".len()];
159 if !prefix.is_empty()
160 && prefix.chars().next().is_some_and(|c| c.is_uppercase())
161 {
162 let update_line = self.current().line;
163 self.advance(); let base = self.parse_expr()?;
165 let updates = if self.check_exact(&TokenKind::Comma) {
166 self.advance();
167 self.skip_formatting();
168 self.parse_record_create_fields()?
169 } else {
170 Vec::new()
171 };
172 self.expect_exact(&TokenKind::RParen)?;
173 expr = self.spanned(
174 Expr::RecordUpdate {
175 type_name: prefix.to_string(),
176 base: Box::new(base),
177 updates,
178 },
179 update_line,
180 );
181 continue;
182 }
183 }
184 if let Some(path) = Self::dotted_name(&expr) {
185 self.reject_zero_arg_constructor_call(&path)?;
186 }
187 let named_arg_start = matches!(&self.peek(1).kind, TokenKind::Ident(_))
188 && self.peek(2).kind == TokenKind::Assign;
189 if named_arg_start && let Some(path) = Self::dotted_name(&expr) {
190 let ctor_line = self.current().line;
192 self.advance();
193 let fields = self.parse_record_create_fields()?;
194 self.expect_exact(&TokenKind::RParen)?;
195 expr = self.spanned(
196 Expr::RecordCreate {
197 type_name: path,
198 fields,
199 },
200 ctor_line,
201 );
202 } else {
203 let call_line = self.current().line;
204 self.advance();
205 let args = self.parse_args()?;
206 self.expect_exact(&TokenKind::RParen)?;
207 expr = self.spanned(Expr::FnCall(Box::new(expr), args), call_line);
208 }
209 }
210 } else {
211 break;
212 }
213 }
214
215 Ok(expr)
216 }
217
218 pub(super) fn dotted_name(expr: &Spanned<Expr>) -> Option<String> {
219 match &expr.node {
220 Expr::Ident(name) => Some(name.clone()),
221 Expr::Attr(inner, field) => {
222 let mut base = Self::dotted_name(inner)?;
223 base.push('.');
224 base.push_str(field);
225 Some(base)
226 }
227 _ => None,
228 }
229 }
230
231 pub(super) fn parse_call_or_atom(&mut self) -> Result<Spanned<Expr>, ParseError> {
232 let atom = self.parse_atom()?;
233
234 if self.check_exact(&TokenKind::LParen) {
235 if let Some(path) = Self::dotted_name(&atom) {
236 self.reject_zero_arg_constructor_call(&path)?;
237 }
238
239 let is_record_create = if let Expr::Ident(ref name) = atom.node {
243 name.chars().next().is_some_and(|c| c.is_uppercase())
244 && matches!(&self.peek_skip_formatting(1).kind, TokenKind::Ident(_))
245 && self.peek_skip_formatting(2).kind == TokenKind::Assign
246 } else {
247 false
248 };
249 let named_arg_start = matches!(&self.peek_skip_formatting(1).kind, TokenKind::Ident(_))
250 && self.peek_skip_formatting(2).kind == TokenKind::Assign;
251
252 if is_record_create && let Expr::Ident(type_name) = atom.node {
253 let line = atom.line;
254 self.advance(); let fields = self.parse_record_create_fields()?;
256 self.expect_exact(&TokenKind::RParen)?;
257 return Ok(self.spanned(Expr::RecordCreate { type_name, fields }, line));
258 }
259
260 if named_arg_start && let Some(path) = Self::dotted_name(&atom) {
262 let line = atom.line;
263 self.advance();
264 let fields = self.parse_record_create_fields()?;
265 self.expect_exact(&TokenKind::RParen)?;
266 return Ok(self.spanned(
267 Expr::RecordCreate {
268 type_name: path,
269 fields,
270 },
271 line,
272 ));
273 }
274
275 let call_line = self.current().line;
276 self.advance();
277 let args = self.parse_args()?;
278 self.expect_exact(&TokenKind::RParen)?;
279 return Ok(self.spanned(Expr::FnCall(Box::new(atom), args), call_line));
280 }
281
282 Ok(atom)
283 }
284
285 pub(super) fn parse_record_create_fields(
287 &mut self,
288 ) -> Result<Vec<(String, Spanned<Expr>)>, ParseError> {
289 let mut fields = Vec::new();
290 self.skip_formatting();
291
292 while !self.check_exact(&TokenKind::RParen) && !self.is_eof() {
293 if self.check_exact(&TokenKind::Comma) {
294 self.advance();
295 self.skip_formatting();
296 continue;
297 }
298 let name_tok =
299 self.expect_kind(&TokenKind::Ident(String::new()), "Expected field name")?;
300 let field_name = match name_tok.kind {
301 TokenKind::Ident(s) => s,
302 _ => unreachable!(),
303 };
304 self.expect_exact(&TokenKind::Assign)?;
305 let value = self.parse_expr()?;
306 fields.push((field_name, value));
307 self.skip_formatting();
308 }
309
310 Ok(fields)
311 }
312
313 pub(super) fn parse_args(&mut self) -> Result<Vec<Spanned<Expr>>, ParseError> {
314 let mut args = Vec::new();
315 self.skip_formatting();
316
317 while !self.check_exact(&TokenKind::RParen) && !self.is_eof() {
318 if self.check_exact(&TokenKind::Comma) {
319 self.advance();
320 self.skip_formatting();
321 continue;
322 }
323 args.push(self.parse_expr()?);
324 self.skip_formatting();
325 }
326
327 Ok(args)
328 }
329
330 pub(super) fn parse_map_literal(&mut self) -> Result<Expr, ParseError> {
331 self.expect_exact(&TokenKind::LBrace)?;
332 let mut entries = Vec::new();
333 self.skip_formatting();
334
335 while !self.check_exact(&TokenKind::RBrace) && !self.is_eof() {
336 if self.check_exact(&TokenKind::Comma) {
337 self.advance();
338 self.skip_formatting();
339 continue;
340 }
341
342 let key = self.parse_expr()?;
343 self.skip_formatting();
344 if !self.check_exact(&TokenKind::FatArrow) {
345 return Err(
346 self.error("Expected '=>' between key and value in map literal".to_string())
347 );
348 }
349 self.advance(); self.skip_formatting();
351 let value = self.parse_expr()?;
352 entries.push((key, value));
353 self.skip_formatting();
354
355 if self.check_exact(&TokenKind::Comma) {
356 self.advance();
357 self.skip_formatting();
358 }
359 }
360
361 self.expect_exact(&TokenKind::RBrace)?;
362 Ok(Expr::MapLiteral(entries))
363 }
364
365 pub(super) fn parse_atom(&mut self) -> Result<Spanned<Expr>, ParseError> {
366 let line = self.current().line;
367 match self.current().kind.clone() {
368 TokenKind::Int(i) => {
369 self.advance();
370 Ok(self.spanned(Expr::Literal(Literal::Int(i)), line))
371 }
372 TokenKind::Float(f) => {
373 self.advance();
374 Ok(self.spanned(Expr::Literal(Literal::Float(f)), line))
375 }
376 TokenKind::Str(s) => {
377 self.advance();
378 Ok(self.spanned(Expr::Literal(Literal::Str(s)), line))
379 }
380 TokenKind::InterpStr(parts) => {
381 self.advance();
382 let mut str_parts = Vec::new();
383 for (is_expr, s) in parts {
384 if is_expr {
385 if s.trim().is_empty() {
387 str_parts.push(StrPart::Literal(String::new()));
388 } else {
389 let mut lexer = crate::lexer::Lexer::new(&s);
390 let tokens = lexer.tokenize().map_err(|e| ParseError::Error {
391 msg: format!("Error in interpolation: {}", e),
392 line: self.current().line,
393 col: self.current().col,
394 })?;
395 let mut sub_parser = Parser::new(tokens);
396 let expr = sub_parser.parse_expr().map_err(|e| ParseError::Error {
397 msg: format!("Error in interpolation: {}", e),
398 line: self.current().line,
399 col: self.current().col,
400 })?;
401 str_parts.push(StrPart::Parsed(Box::new(expr)));
402 }
403 } else {
404 str_parts.push(StrPart::Literal(s));
405 }
406 }
407 Ok(self.spanned(Expr::InterpolatedStr(str_parts), line))
408 }
409 TokenKind::Bool(b) => {
410 self.advance();
411 Ok(self.spanned(Expr::Literal(Literal::Bool(b)), line))
412 }
413 TokenKind::Match => {
414 let m = self.parse_match()?;
415 Ok(self.spanned(m, line))
416 }
417 TokenKind::LParen => {
418 self.advance();
419 let first = self.parse_expr()?;
420 if self.check_exact(&TokenKind::Comma) {
421 let mut items = vec![first];
422 while self.check_exact(&TokenKind::Comma) {
423 self.advance();
424 items.push(self.parse_expr()?);
425 }
426 self.expect_exact(&TokenKind::RParen)?;
427 Ok(self.spanned(Expr::Tuple(items), line))
428 } else {
429 self.expect_exact(&TokenKind::RParen)?;
430 Ok(first)
431 }
432 }
433 TokenKind::Ident(s) => {
434 self.advance();
435 if s == "Unit" {
436 Ok(self.spanned(Expr::Literal(Literal::Unit), line))
437 } else {
438 Ok(self.spanned(Expr::Ident(s), line))
439 }
440 }
441 TokenKind::LBracket => {
442 self.advance(); let mut elements = Vec::new();
444 self.skip_formatting();
445 while !self.check_exact(&TokenKind::RBracket) && !self.is_eof() {
446 if self.check_exact(&TokenKind::Comma) {
447 self.advance();
448 self.skip_formatting();
449 continue;
450 }
451 elements.push(self.parse_expr()?);
452 self.skip_formatting();
453 }
454 self.expect_exact(&TokenKind::RBracket)?;
455 Ok(self.spanned(Expr::List(elements), line))
456 }
457 TokenKind::LBrace => {
458 let map = self.parse_map_literal()?;
459 Ok(self.spanned(map, line))
460 }
461 TokenKind::Fn => Err(self.error(
462 "Anonymous functions are not supported in Aver. Define a top-level function and pass its name."
463 .to_string(),
464 )),
465 _ => Err(self.error(format!(
466 "Expected expression (identifier, literal, '[', or '{{'), found {}",
467 self.current().kind
468 ))),
469 }
470 }
471}