Actually just three programming languages in a trenchcoat
1use super::*;
2use crate::{Parser, Spanned, token_pattern::TokenPattern};
3use become_expression::BecomeExpression;
4use trilogy_scanner::TokenType::{self, *};
5
6/// The many kinds of expressions in a Trilogy program.
7#[derive(Clone, Debug, Spanned, PrettyPrintSExpr)]
8pub enum Expression {
9 Number(Box<NumberLiteral>),
10 Character(Box<CharacterLiteral>),
11 String(Box<StringLiteral>),
12 Bits(Box<BitsLiteral>),
13 Boolean(Box<BooleanLiteral>),
14 Unit(Box<UnitLiteral>),
15 Atom(Box<AtomLiteral>),
16 Struct(Box<StructLiteral>),
17 Array(Box<ArrayLiteral>),
18 Set(Box<SetLiteral>),
19 Record(Box<RecordLiteral>),
20 ArrayComprehension(Box<ArrayComprehension>),
21 SetComprehension(Box<SetComprehension>),
22 RecordComprehension(Box<RecordComprehension>),
23 Reference(Box<super::Identifier>),
24 Keyword(Box<KeywordReference>),
25 Application(Box<Application>),
26 Call(Box<CallExpression>),
27 Binary(Box<BinaryOperation>),
28 Unary(Box<UnaryOperation>),
29 Let(Box<LetExpression>),
30 IfElse(Box<IfElseExpression>),
31 Match(Box<MatchExpression>),
32 Is(Box<IsExpression>),
33 End(Box<EndExpression>),
34 Exit(Box<ExitExpression>),
35 Resume(Box<ResumeExpression>),
36 Become(Box<BecomeExpression>),
37 Cancel(Box<CancelExpression>),
38 Return(Box<ReturnExpression>),
39 Break(Box<BreakExpression>),
40 Continue(Box<ContinueExpression>),
41 Fn(Box<FnExpression>),
42 Do(Box<DoExpression>),
43 Qy(Box<QyExpression>),
44 Template(Box<Template>),
45 Handled(Box<HandledExpression>),
46 Parenthesized(Box<ParenthesizedExpression>),
47 ModuleAccess(Box<ModuleAccess>),
48}
49
50#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
51pub(crate) enum Precedence {
52 None,
53 Sequence,
54 Continuation,
55 Or,
56 And,
57 Equality,
58 Comparison,
59 Pipe,
60 RPipe,
61 Cons,
62 Glue,
63 BitwiseOr,
64 BitwiseXor,
65 BitwiseShift,
66 BitwiseAnd,
67 Term,
68 Factor,
69 Exponent,
70 RCompose,
71 Compose,
72 Path,
73 Application,
74 Unary,
75 Call,
76 Access,
77}
78
79enum ExpressionResult {
80 Continue(Expression),
81 Done(Expression),
82 Pattern(Pattern),
83}
84
85impl Expression {
86 pub(crate) const PREFIX: [TokenType; 33] = [
87 Numeric,
88 String,
89 Bits,
90 KwTrue,
91 KwFalse,
92 Atom,
93 Character,
94 KwUnit,
95 OBrack,
96 OBrackPipe,
97 OBracePipe,
98 OpBang,
99 OpTilde,
100 KwYield,
101 KwIf,
102 KwIs,
103 KwMatch,
104 KwEnd,
105 KwExit,
106 KwReturn,
107 KwResume,
108 KwBreak,
109 KwContinue,
110 KwCancel,
111 KwLet,
112 Identifier,
113 KwWith,
114 KwFn,
115 KwDo,
116 KwQy,
117 DollarString,
118 TemplateStart,
119 OParen,
120 ];
121
122 fn binary(parser: &mut Parser, lhs: Expression) -> SyntaxResult<ExpressionResult> {
123 let binary = BinaryOperation::parse(parser, lhs)?;
124 match binary {
125 Ok(binary) => Ok(ExpressionResult::Continue(Self::Binary(Box::new(binary)))),
126 Err(pattern) => Ok(ExpressionResult::Pattern(pattern)),
127 }
128 }
129
130 fn parse_follow(
131 parser: &mut Parser,
132 precedence: Precedence,
133 lhs: Expression,
134 no_seq: bool,
135 ) -> SyntaxResult<ExpressionResult> {
136 // A bit of strangeness here because `peek()` takes a mutable reference,
137 // so we can't use the fields afterwards... but we need their value after
138 // and I'd really rather not clone every token of every expression, so
139 // instead we peek first, then do a force peek after (to skip an extra chomp).
140 parser.peek();
141 let is_spaced = parser.is_spaced;
142 let is_line_start = parser.is_line_start;
143 let token = parser.force_peek();
144
145 use ExpressionResult::{Continue, Done};
146
147 match token.token_type {
148 OpDot if precedence < Precedence::Access => Self::binary(parser, lhs),
149 OpAmpAmp if precedence < Precedence::And => Self::binary(parser, lhs),
150 OpPipePipe if precedence < Precedence::Or => Self::binary(parser, lhs),
151 OpPlus | OpMinus if precedence < Precedence::Term => Self::binary(parser, lhs),
152 OpStar | OpSlash | OpPercent | OpSlashSlash if precedence < Precedence::Factor => {
153 Self::binary(parser, lhs)
154 }
155 OpStarStar if precedence <= Precedence::Exponent => Self::binary(parser, lhs),
156 OpLt | OpGt | OpLtEq | OpGtEq if precedence == Precedence::Comparison => {
157 let expr = Self::binary(parser, lhs);
158 if let Ok(Continue(expr)) = &expr {
159 parser.error(SyntaxError::new(
160 expr.span(),
161 "comparison operators cannot be chained, use parentheses to disambiguate",
162 ));
163 }
164 expr
165 }
166 OpLt | OpGt | OpLtEq | OpGtEq if precedence < Precedence::Comparison => {
167 Self::binary(parser, lhs)
168 }
169 OpEqEq | OpEqEqEq if precedence == Precedence::Equality => {
170 let expr = Self::binary(parser, lhs);
171 if let Ok(Continue(expr)) = &expr {
172 parser.error(SyntaxError::new(
173 expr.span(),
174 "equality operators cannot be chained, use parentheses to disambiguate",
175 ));
176 }
177 expr
178 }
179 OpBangEq | OpBangEqEq | OpEqEq | OpEqEqEq if precedence < Precedence::Equality => {
180 Self::binary(parser, lhs)
181 }
182 OpAmp if precedence < Precedence::BitwiseAnd => Self::binary(parser, lhs),
183 OpPipe if precedence < Precedence::BitwiseOr => Self::binary(parser, lhs),
184 OpCaret if precedence < Precedence::BitwiseXor => Self::binary(parser, lhs),
185 OpShr | OpShl | OpShrEx | OpShlEx | OpShrCon | OpShlCon
186 if precedence < Precedence::BitwiseShift =>
187 {
188 Self::binary(parser, lhs)
189 }
190 OpColonColon if precedence < Precedence::Path => Ok(Continue(Self::ModuleAccess(
191 Box::new(ModuleAccess::parse(parser, lhs)?),
192 ))),
193 OpColon if precedence <= Precedence::Cons => Self::binary(parser, lhs),
194 OpLtLt if precedence < Precedence::Compose => Self::binary(parser, lhs),
195 OpGtGt if precedence < Precedence::RCompose => Self::binary(parser, lhs),
196 OpPipeGt if precedence < Precedence::Pipe => Self::binary(parser, lhs),
197 OpLtPipe if precedence < Precedence::RPipe => Self::binary(parser, lhs),
198 OpGlue if precedence < Precedence::Glue => Self::binary(parser, lhs),
199 OpBang if precedence < Precedence::Call && !is_spaced => Ok(Continue(Self::Call(
200 Box::new(CallExpression::parse(parser, lhs)?),
201 ))),
202 OpSemi if precedence <= Precedence::Sequence && !no_seq => Self::binary(parser, lhs),
203
204 // NOTE: despite and/or being allowed in patterns, we can't accept them here because
205 // they are also allowed in queries, in which case an expression was never an option,
206 // unless that expression was the start of a lookup, in which case the and/or is not
207 // permitted, so... if we're parsing as maybe expression or pattern, we aren't
208 // expecting and/or...
209 KwAnd | KwOr => Ok(Done(lhs)),
210 // Unary operators and keywords are not permitted here. They must be parenthesized
211 // to be considered an argument to an application. It messes with handler parsing
212 // otherwise, while also being confusing in terms of precedence rules.
213 KwYield | KwResume | KwCancel | KwReturn | KwContinue | KwBreak | KwBecome => {
214 Ok(Done(lhs))
215 }
216
217 // A function application never spans across two lines. Furthermore,
218 // the application requires a space, even when the parse would be
219 // otherwise unambiguous.
220 //
221 // Sadly, the list of things that can follow, for an application, is
222 // anything prefix (except unary operators) so this becomes a very long list.
223 _ if Expression::PREFIX.matches(token)
224 && precedence < Precedence::Application
225 && !is_line_start
226 && is_spaced =>
227 {
228 Ok(Continue(Self::Application(Box::new(Application::parse(
229 parser, lhs,
230 )?))))
231 }
232 // If nothing matched, it must be the end of the expression
233 _ => Ok(Done(lhs)),
234 }
235 }
236
237 fn parse_prefix(parser: &mut Parser) -> SyntaxResult<Result<Self, Pattern>> {
238 let token = parser.peek();
239 match token.token_type {
240 Numeric => Ok(Ok(Self::Number(Box::new(NumberLiteral::parse(parser)?)))),
241 String => Ok(Ok(Self::String(Box::new(StringLiteral::parse(parser)?)))),
242 Bits => Ok(Ok(Self::Bits(Box::new(BitsLiteral::parse(parser)?)))),
243 KwTrue | KwFalse => Ok(Ok(Self::Boolean(Box::new(BooleanLiteral::parse(parser)?)))),
244 Atom => {
245 let atom = AtomLiteral::parse(parser)?;
246 if parser.check(OParen).is_ok() {
247 let result = StructLiteral::parse(parser, atom)?;
248 match result {
249 Ok(expr) => Ok(Ok(Self::Struct(Box::new(expr)))),
250 Err(patt) => Ok(Err(Pattern::Struct(Box::new(patt)))),
251 }
252 } else {
253 Ok(Ok(Self::Atom(Box::new(atom))))
254 }
255 }
256 Character => Ok(Ok(Self::Character(Box::new(CharacterLiteral::parse(
257 parser,
258 )?)))),
259 KwUnit => Ok(Ok(Self::Unit(Box::new(UnitLiteral::parse(parser)?)))),
260 OBrack => {
261 let start = parser.expect(OBrack).unwrap();
262 if let Ok(end) = parser.expect(CBrack) {
263 return Ok(Ok(Self::Array(Box::new(ArrayLiteral::new_empty(
264 start, end,
265 )))));
266 }
267 match ArrayElement::parse(parser)? {
268 Ok(ArrayElement::Element(expression)) if parser.check(KwFor).is_ok() => {
269 Ok(Ok(Self::ArrayComprehension(Box::new(
270 ArrayComprehension::parse_rest(parser, start, expression)?,
271 ))))
272 }
273 Ok(element) => match ArrayLiteral::parse_rest(parser, start, element)? {
274 Ok(expr) => Ok(Ok(Self::Array(Box::new(expr)))),
275 Err(patt) => Ok(Err(Pattern::Array(Box::new(patt)))),
276 },
277 Err(next) => Ok(Err(Pattern::Array(Box::new(
278 ArrayPattern::parse_from_expression(
279 parser,
280 start,
281 Punctuated::new(),
282 next,
283 )?,
284 )))),
285 }
286 }
287 OBrackPipe => {
288 let start = parser.expect(OBrackPipe).unwrap();
289 if let Ok(end) = parser.expect(CBrackPipe) {
290 return Ok(Ok(Self::Set(Box::new(SetLiteral::new_empty(start, end)))));
291 }
292 match SetElement::parse(parser)? {
293 Ok(SetElement::Element(expression)) if parser.expect(KwFor).is_ok() => {
294 Ok(Ok(Self::SetComprehension(Box::new(
295 SetComprehension::parse_rest(parser, start, expression)?,
296 ))))
297 }
298 Ok(element) => {
299 let result = SetLiteral::parse_rest(parser, start, element)?;
300 match result {
301 Ok(expr) => Ok(Ok(Self::Set(Box::new(expr)))),
302 Err(patt) => Ok(Err(Pattern::Set(Box::new(patt)))),
303 }
304 }
305 Err(next) => Ok(Err(Pattern::Set(Box::new(
306 SetPattern::parse_from_expression(parser, start, vec![], next)?,
307 )))),
308 }
309 }
310 OBracePipe => {
311 let start = parser.expect(OBracePipe).unwrap();
312 if let Ok(end) = parser.expect(CBracePipe) {
313 return Ok(Ok(Self::Record(Box::new(RecordLiteral::new_empty(
314 start, end,
315 )))));
316 }
317 match RecordElement::parse(parser)? {
318 Ok(RecordElement::Element(key, value)) if parser.expect(KwFor).is_ok() => {
319 Ok(Ok(Self::RecordComprehension(Box::new(
320 RecordComprehension::parse_rest(parser, start, key, value)?,
321 ))))
322 }
323 Ok(element) => {
324 let result = RecordLiteral::parse_rest(parser, start, element)?;
325 match result {
326 Ok(literal) => Ok(Ok(Self::Record(Box::new(literal)))),
327 Err(pattern) => Ok(Err(Pattern::Record(Box::new(pattern)))),
328 }
329 }
330 Err(next) => Ok(Err(Pattern::Record(Box::new(
331 RecordPattern::parse_from_expression(parser, start, vec![], next)?,
332 )))),
333 }
334 }
335 OpBang | OpMinus | OpTilde | KwYield | KwTypeof => match UnaryOperation::parse(parser)?
336 {
337 Ok(expr) => Ok(Ok(Self::Unary(Box::new(expr)))),
338 Err(patt) => Ok(Err(patt)),
339 },
340 KwIf => {
341 let expr = IfElseExpression::parse(parser)?;
342 if !expr.is_strict_expression() {
343 parser.error(ErrorKind::IfExpressionRestriction.at(expr.span()));
344 }
345 Ok(Ok(Self::IfElse(Box::new(expr))))
346 }
347 KwMatch => Ok(Ok(Self::Match(Box::new(
348 MatchExpression::parse(parser)?.strict_expression()?,
349 )))),
350 KwEnd => Ok(Ok(Self::End(Box::new(EndExpression::parse(parser)?)))),
351 KwExit => Ok(Ok(Self::Exit(Box::new(ExitExpression::parse(parser)?)))),
352 KwReturn => Ok(Ok(Self::Return(Box::new(ReturnExpression::parse(parser)?)))),
353 KwResume => Ok(Ok(Self::Resume(Box::new(ResumeExpression::parse(parser)?)))),
354 KwBecome => Ok(Ok(Self::Become(Box::new(BecomeExpression::parse(parser)?)))),
355 KwBreak => Ok(Ok(Self::Break(Box::new(BreakExpression::parse(parser)?)))),
356 KwContinue => Ok(Ok(Self::Continue(Box::new(ContinueExpression::parse(
357 parser,
358 )?)))),
359 KwCancel => Ok(Ok(Self::Cancel(Box::new(CancelExpression::parse(parser)?)))),
360 KwLet => Ok(Ok(Self::Let(Box::new(LetExpression::parse(parser)?)))),
361 Identifier => Ok(Ok(Self::Reference(Box::new(super::Identifier::parse(
362 parser,
363 )?)))),
364 KwWith => Ok(Ok(Self::Handled(Box::new(HandledExpression::parse(
365 parser,
366 )?)))),
367 KwFn => Ok(Ok(Self::Fn(Box::new(FnExpression::parse(parser)?)))),
368 KwDo => Ok(Ok(Self::Do(Box::new(DoExpression::parse(parser)?)))),
369 KwQy => Ok(Ok(Self::Qy(Box::new(QyExpression::parse(parser)?)))),
370 DollarString | TemplateStart => {
371 Ok(Ok(Self::Template(Box::new(Template::parse(parser)?))))
372 }
373 OParen => match KeywordReference::try_parse(parser) {
374 Some(keyword) => Ok(Ok(Self::Keyword(Box::new(keyword)))),
375 None => match ParenthesizedExpression::parse(parser)? {
376 Ok(expression) => Ok(Ok(Self::Parenthesized(Box::new(expression)))),
377 Err(pattern) => Ok(Err(Pattern::Parenthesized(Box::new(pattern)))),
378 },
379 },
380 KwIs => Ok(Ok(Self::Is(Box::new(IsExpression::parse(parser)?)))),
381 KwMut | Discard | OpCaret => Ok(Err(Pattern::parse(parser)?)),
382
383 // Invalid stuff, but we can do better error messages by handling some specifically
384 KwNot => {
385 let error = ErrorKind::KwNotInExpression.at(token.span);
386 parser.error(error.clone());
387 Err(error)
388 }
389 _ => {
390 let error = SyntaxError::new(
391 token.span,
392 format!("unexpected token {:?} in expression", token.token_type),
393 );
394 parser.error(error.clone());
395 Err(error)
396 }
397 }
398 }
399
400 fn parse_suffix(
401 parser: &mut Parser,
402 precedence: Precedence,
403 no_seq: bool,
404 mut expr: Expression,
405 ) -> SyntaxResult<Result<Self, Pattern>> {
406 loop {
407 match Self::parse_follow(parser, precedence, expr, no_seq)? {
408 ExpressionResult::Continue(updated) => expr = updated,
409 ExpressionResult::Done(expr) => return Ok(Ok(expr)),
410 ExpressionResult::Pattern(patt) => return Ok(Err(patt)),
411 }
412 }
413 }
414
415 fn parse_precedence_inner(
416 parser: &mut Parser,
417 precedence: Precedence,
418 no_seq: bool,
419 ) -> SyntaxResult<Result<Self, Pattern>> {
420 match Self::parse_prefix(parser)? {
421 Ok(expr) => Self::parse_suffix(parser, precedence, no_seq, expr),
422 Err(patt) => Ok(Err(Pattern::parse_suffix(
423 parser,
424 pattern::Precedence::None,
425 patt,
426 )?)),
427 }
428 }
429
430 pub(crate) fn parse_or_pattern_precedence(
431 parser: &mut Parser,
432 precedence: Precedence,
433 ) -> SyntaxResult<Result<Self, Pattern>> {
434 Self::parse_precedence_inner(parser, precedence, false)
435 }
436
437 pub(crate) fn parse_precedence(
438 parser: &mut Parser,
439 precedence: Precedence,
440 ) -> SyntaxResult<Self> {
441 Self::parse_or_pattern_precedence(parser, precedence)?.map_err(|patt| {
442 SyntaxError::new(
443 patt.span(),
444 "expected an expression in parameter list, but found a pattern",
445 )
446 })
447 }
448
449 pub(crate) fn parse_parameter_list(parser: &mut Parser) -> SyntaxResult<Result<Self, Pattern>> {
450 Self::parse_precedence_inner(parser, Precedence::None, true)
451 }
452
453 pub(crate) fn parse_or_pattern(parser: &mut Parser) -> SyntaxResult<Result<Self, Pattern>> {
454 Self::parse_or_pattern_precedence(parser, Precedence::None)
455 }
456
457 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> {
458 Self::parse_precedence(parser, Precedence::None)
459 }
460
461 pub(crate) fn parse_no_seq(parser: &mut Parser) -> SyntaxResult<Self> {
462 Self::parse_precedence_inner(parser, Precedence::None, true)?.map_err(|patt| {
463 SyntaxError::new(patt.span(), "expected an expression but found a pattern")
464 })
465 }
466
467 pub(crate) fn is_lvalue(&self) -> bool {
468 match self {
469 Self::Binary(op) if matches!(op.operator, BinaryOperator::Access(..)) => true,
470 _ => self.is_pattern(),
471 }
472 }
473
474 pub(crate) fn is_pattern(&self) -> bool {
475 match self {
476 Self::Reference(..) => true,
477 Self::Atom(..) => true,
478 Self::Number(..) => true,
479 Self::Boolean(..) => true,
480 Self::Unit(..) => true,
481 Self::Bits(..) => true,
482 Self::String(..) => true,
483 Self::Character(..) => true,
484 Self::Unary(op) if matches!(op.operator, UnaryOperator::Negate(..)) => {
485 op.operand.is_pattern()
486 }
487 Self::Binary(op)
488 if matches!(
489 op.operator,
490 BinaryOperator::Glue(..) | BinaryOperator::Cons(..)
491 ) =>
492 {
493 op.lhs.is_pattern() && op.rhs.is_pattern()
494 }
495 Self::Struct(inner) => inner.value.is_pattern(),
496 Self::Array(array) => {
497 array.elements.iter().all(|element| match element {
498 ArrayElement::Element(element) => element.is_pattern(),
499 ArrayElement::Spread(_, element) => element.is_pattern(),
500 }) && array
501 .elements
502 .iter()
503 .filter(|element| matches!(element, ArrayElement::Spread(..)))
504 .count()
505 <= 1
506 }
507 Self::Set(set) => set.elements.iter().all(|element| match element {
508 SetElement::Element(element) => element.is_pattern(),
509 SetElement::Spread(_, spread)
510 if std::ptr::eq(element, set.elements.last().unwrap()) =>
511 {
512 spread.is_pattern()
513 }
514 _ => false,
515 }),
516 Self::Record(record) => record.elements.iter().all(|element| match element {
517 RecordElement::Element(key, value) => key.is_pattern() && value.is_pattern(),
518 RecordElement::Spread(_, spread)
519 if std::ptr::eq(element, record.elements.last().unwrap()) =>
520 {
521 spread.is_pattern()
522 }
523 _ => false,
524 }),
525 Self::Parenthesized(paren) => paren.expression.is_pattern(),
526 _ => false,
527 }
528 }
529}
530
531#[cfg(test)]
532mod test {
533 use super::*;
534
535 test_parse!(expr_prec_boolean: "!true && false || true && !false" => Expression::parse => "
536 (Expression::Binary
537 (BinaryOperation
538 (Expression::Binary (BinaryOperation (Expression::Unary _) (BinaryOperator::And _) _))
539 (BinaryOperator::Or _)
540 (Expression::Binary (BinaryOperation _ (BinaryOperator::And _) (Expression::Unary _)))))");
541 test_parse!(expr_prec_arithmetic: "- 1 / 2 + 3 ** e - 4 * 5" => Expression::parse => "
542 (Expression::Binary
543 (BinaryOperation
544 (Expression::Binary
545 (BinaryOperation
546 (Expression::Binary (BinaryOperation (Expression::Unary _) (BinaryOperator::Divide _) _))
547 (BinaryOperator::Add _)
548 (Expression::Binary (BinaryOperation _ (BinaryOperator::Power _) _))))
549 (BinaryOperator::Subtract _)
550 (Expression::Binary
551 (BinaryOperation
552 _
553 (BinaryOperator::Multiply _)
554 _))))");
555 test_parse!(expr_prec_factor: "1 / 2 % 3 // 4 * 5" => Expression::parse => "
556 (Expression::Binary
557 (BinaryOperation
558 (Expression::Binary
559 (BinaryOperation
560 (Expression::Binary
561 (BinaryOperation
562 (Expression::Binary
563 (BinaryOperation
564 _
565 (BinaryOperator::Divide _)
566 _))
567 (BinaryOperator::Remainder _)
568 _))
569 (BinaryOperator::IntDivide _)
570 _))
571 (BinaryOperator::Multiply _)
572 _))");
573 test_parse!(expr_prec_bitwise: "~x & y <~ 4 | x ^ y ~> 3" => Expression::parse => "
574 (Expression::Binary
575 (BinaryOperation
576 (Expression::Binary
577 (BinaryOperation
578 (Expression::Binary (BinaryOperation (Expression::Unary _) (BinaryOperator::BitwiseAnd _) _))
579 (BinaryOperator::LeftShift _)
580 _))
581 (BinaryOperator::BitwiseOr _)
582 (Expression::Binary
583 (BinaryOperation
584 _
585 (BinaryOperator::BitwiseXor _)
586 (Expression::Binary
587 (BinaryOperation
588 _
589 (BinaryOperator::RightShift _)
590 _))))))");
591 test_parse!(expr_prec_app_pipe: "f x |> map (fn y. 2 * y) |> print" => Expression::parse => "
592 (Expression::Binary
593 (BinaryOperation
594 (Expression::Binary
595 (BinaryOperation
596 (Expression::Application _)
597 (BinaryOperator::Pipe _)
598 (Expression::Application _)))
599 (BinaryOperator::Pipe _)
600 (Expression::Reference _)))");
601 test_parse!(expr_prec_pipe_rpipe: "x |> f <| g <| y |> h" => Expression::parse => "
602 (Expression::Binary
603 (BinaryOperation
604 (Expression::Binary
605 (BinaryOperation
606 (Expression::Reference _)
607 (BinaryOperator::Pipe _)
608 (Expression::Binary
609 (BinaryOperation
610 (Expression::Binary
611 (BinaryOperation
612 (Expression::Reference _)
613 (BinaryOperator::RPipe _)
614 (Expression::Reference _)))
615 (BinaryOperator::RPipe _)
616 (Expression::Reference _)))))
617 (BinaryOperator::Pipe _)
618 (Expression::Reference _)))");
619 test_parse!(expr_prec_compose_rcompose: "x >> f << g << y >> h" => Expression::parse => "
620 (Expression::Binary
621 (BinaryOperation
622 (Expression::Binary
623 (BinaryOperation
624 (Expression::Reference _)
625 (BinaryOperator::RCompose _)
626 (Expression::Binary
627 (BinaryOperation
628 (Expression::Binary
629 (BinaryOperation
630 (Expression::Reference _)
631 (BinaryOperator::Compose _)
632 (Expression::Reference _)))
633 (BinaryOperator::Compose _)
634 (Expression::Reference _)))))
635 (BinaryOperator::RCompose _)
636 (Expression::Reference _)))");
637 test_parse!(expr_prec_application: "x - f y + f y <| -z" => Expression::parse => "
638 (Expression::Binary
639 (BinaryOperation
640 (Expression::Binary
641 (BinaryOperation
642 (Expression::Binary
643 (BinaryOperation
644 (Expression::Reference _)
645 (BinaryOperator::Subtract _)
646 (Expression::Application _)))
647 (BinaryOperator::Add _)
648 (Expression::Application _)))
649 (BinaryOperator::RPipe _)
650 (Expression::Unary _)))");
651 test_parse!(expr_prec_if_else: "if true then 5 + 6 else 7 + 8" => Expression::parse => "
652 (Expression::IfElse
653 (IfElseExpression
654 _
655 (Expression::Boolean _)
656 (IfBody::Then _ _)
657 (ElseClause _ _)))");
658
659 test_parse_error!(expr_eq_without_parens: "x == y == z" => Expression::parse => "equality operators cannot be chained, use parentheses to disambiguate");
660 test_parse_error!(expr_cmp_without_parens: "x <= y <= z" => Expression::parse => "comparison operators cannot be chained, use parentheses to disambiguate");
661 test_parse!(expr_prec_cmp_eq: "x < y == y > z" => Expression::parse => "
662 (Expression::Binary
663 (BinaryOperation
664 (Expression::Binary _)
665 (BinaryOperator::StructuralEquality _)
666 (Expression::Binary _)))");
667
668 test_parse_error!(expr_multiline_application: "f\nx" => Expression::parse);
669 test_parse_error!(expr_application_no_space: "f(x)" => Expression::parse);
670 test_parse!(expr_multiline_operators: "f\n<| x" => Expression::parse => "
671 (Expression::Binary
672 (BinaryOperation
673 (Expression::Reference _)
674 (BinaryOperator::RPipe _)
675 (Expression::Reference _)))");
676
677 test_parse!(expr_is: "true && is check(y) and also(z) && false" => Expression::parse => "
678 (Expression::Binary
679 (BinaryOperation
680 (Expression::Binary
681 (BinaryOperation
682 (Expression::Boolean _)
683 (BinaryOperator::And _)
684 (Expression::Is _)))
685 (BinaryOperator::And _)
686 (Expression::Boolean _)))");
687 test_parse!(expr_is_prec: "false || is x = y && z" => Expression::parse => "
688 (Expression::Binary
689 (BinaryOperation
690 (Expression::Boolean _)
691 (BinaryOperator::Or _)
692 (Expression::Is _)))");
693
694 test_parse!(expr_prec_glue_cons: "\"hello\" : \"hello\" <> \"world\" : 3 + 3 : \"world\"" => Expression::parse => "
695 (Expression::Binary
696 (BinaryOperation
697 (Expression::String _)
698 (BinaryOperator::Cons _)
699 (Expression::Binary
700 (BinaryOperation
701 (Expression::Binary
702 (BinaryOperation
703 (Expression::String _)
704 (BinaryOperator::Glue _)
705 (Expression::String _)))
706 (BinaryOperator::Cons _)
707 (Expression::Binary
708 (BinaryOperation
709 (Expression::Binary
710 (BinaryOperation
711 (Expression::Number _)
712 (BinaryOperator::Add _)
713 (Expression::Number _)))
714 (BinaryOperator::Cons _)
715 (Expression::String _)))))))");
716
717 test_parse!(expr_prec_call: "a + b!() + c!()" => Expression::parse => "
718 (Expression::Binary
719 (BinaryOperation
720 (Expression::Binary
721 (BinaryOperation
722 (Expression::Reference _)
723 (BinaryOperator::Add _)
724 (Expression::Call _)))
725 (BinaryOperator::Add _)
726 (Expression::Call _)))");
727
728 test_parse!(expr_prec_access: "a.1!() + b.'hello 3" => Expression::parse => "
729 (Expression::Binary
730 (BinaryOperation
731 (Expression::Call
732 (CallExpression
733 (Expression::Binary
734 (BinaryOperation
735 (Expression::Reference _)
736 (BinaryOperator::Access _)
737 (Expression::Number _)))
738 _ _
739 []
740 _))
741 (BinaryOperator::Add _)
742 (Expression::Application
743 (Application
744 (Expression::Binary
745 (BinaryOperation
746 (Expression::Reference _)
747 (BinaryOperator::Access _)
748 (Expression::Atom _)))
749 (Expression::Number _)))))");
750 test_parse!(expr_let_seq: "b; let a = b, a; b" => Expression::parse => "
751 (Expression::Binary
752 (BinaryOperation
753 _
754 (BinaryOperator::Sequence _)
755 (Expression::Binary
756 (BinaryOperation
757 (Expression::Let _)
758 (BinaryOperator::Sequence _)
759 _))))");
760 test_parse!(expr_mod_access: "mod1::mod2::member" => Expression::parse => "
761 (Expression::ModuleAccess
762 (ModuleAccess
763 (Expression::ModuleAccess
764 (ModuleAccess
765 (Expression::Reference _)
766 _
767 (Identifier)))
768 _
769 (Identifier)))");
770 test_parse!(expr_prec_paths: "a b::c d::e f" => Expression::parse => "
771 (Expression::Application
772 (Application
773 (Expression::ModuleAccess
774 (ModuleAccess
775 (Expression::Application
776 (Application
777 (Expression::ModuleAccess _)
778 (Expression::Reference _)))
779 _
780 (Identifier)))
781 (Expression::Reference _)))
782 ");
783}