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