1mod error;
5mod helpers;
6mod simplify;
7
8use crate::Span;
9use crate::ast::*;
10use crate::parser::error::{ParseErrorKind, Rich};
11use crate::parser::helpers::*;
12use crate::parser::simplify::simplify_unary_op;
13use crate::tokens::*;
14
15use chumsky::input::{Input, MappedInput};
16use chumsky::prelude::*;
17use chumsky::{Parser, extra, select_ref};
18pub use error::ParseError;
19use helpers::ParserExt;
20use std::str::FromStr;
21
22type Error<'tokens> = Rich<'tokens, Token<'tokens>, Span, ParseErrorKind>;
23type Extra<'tokens> = extra::Err<Error<'tokens>>;
24
25pub fn map_token_input<'a, 'token>(
26 spanned: &'a SpannedToken<Token<'token>>,
27) -> (&'a Token<'token>, &'a Span) {
28 (&spanned.token, &spanned.span)
29}
30
31type InputMap<'input, 'token> =
32 fn(&'input SpannedToken<Token<'token>>) -> (&'input Token<'token>, &'input Span);
33
34type ParserInput<'input, 'token> = MappedInput<
35 'input,
36 Token<'token>,
37 Span,
38 &'input [SpannedToken<Token<'token>>],
39 InputMap<'input, 'token>,
40>;
41
42fn input<'input, 'tokens>(
43 input: &'input [SpannedToken<Token<'tokens>>],
44) -> ParserInput<'input, 'tokens> {
45 let end = input.last().map(|t| t.span.end).unwrap_or_default();
46 Input::map(input, end..end, map_token_input)
47}
48
49pub fn parse<'tokens>(
51 tokens: &'tokens [SpannedToken<Token<'tokens>>],
52) -> Result<SourceFile, Vec<ParseError>> {
53 parser()
54 .parse(input(tokens))
55 .into_result()
56 .map_err(|errors| errors.into_iter().map(ParseError::new).collect())
57}
58
59const STRUCTURAL_TOKENS: &[Token] = &[
60 Token::SigilOpenCurlyBracket,
61 Token::SigilCloseCurlyBracket,
62 Token::SigilOpenBracket,
63 Token::SigilCloseBracket,
64 Token::SigilOpenSquareBracket,
65 Token::SigilCloseSquareBracket,
66 Token::SigilSemiColon,
67];
68
69fn parser<'tokens>()
70-> impl Parser<'tokens, ParserInput<'tokens, 'tokens>, SourceFile, Extra<'tokens>> {
71 let mut statement_list_parser = Recursive::declare();
72 let mut statement_parser = Recursive::declare();
73 let mut expression_parser = Recursive::declare();
74 let mut type_parser = Recursive::declare();
75 let mut attribute_parser = Recursive::declare();
76 let mut if_inner = Recursive::declare();
77
78 let semi_recovery = none_of(Token::SigilSemiColon).repeated().ignored();
79
80 let reserved_keyword = select_ref! {
81 token @ (
82 Token::KeywordPlugin |
83 Token::KeywordAssembly |
84 Token::KeywordMaterial |
85 Token::KeywordUnit |
86 Token::KeywordEnum |
87 Token::KeywordStruct |
88 Token::KeywordMatch |
89 Token::KeywordType
90 ) => token.kind(),
91 }
92 .boxed();
93 let keyword = select_ref! {
94 token @ (
95 Token::KeywordMod |
96 Token::KeywordPart |
97 Token::KeywordSketch |
98 Token::KeywordOp |
99 Token::KeywordFn |
100 Token::KeywordIf |
101 Token::KeywordElse |
102 Token::KeywordUse |
103 Token::KeywordAs |
104 Token::KeywordReturn |
105 Token::KeywordPub |
106 Token::KeywordConst |
107 Token::KeywordProp |
108 Token::KeywordInit
109 ) => token.kind(),
110 }
111 .boxed();
112
113 let block_recovery =
114 ignore_till_matched_curly().map_with(|_, e| StatementList::dummy(e.span()));
115
116 let block = whitespace_parser()
117 .or_not()
118 .ignore_then(statement_list_parser.clone())
119 .then_maybe_whitespace()
120 .delimited_with_spanned_error(
121 just(Token::SigilOpenCurlyBracket),
122 just(Token::SigilCloseCurlyBracket),
123 |err: Error, open, end| {
124 Rich::custom(
125 err.span().clone(),
126 ParseErrorKind::UnclosedBracket {
127 open,
128 end,
129 kind: "code block",
130 close_token: Token::SigilCloseCurlyBracket,
131 },
132 )
133 },
134 )
135 .recover_with(via_parser(block_recovery))
136 .boxed();
137
138 let identifier_parser = select_ref! { Token::Identifier(ident) = e => Identifier {
139 span: e.span(),
140 name: ident.as_ref().into(),
141 } }
142 .or(reserved_keyword
143 .clone()
144 .validate(|kind, e, emitter| {
145 emitter.emit(Rich::custom(
146 e.span(),
147 ParseErrorKind::ReservedKeywordAsIdentifier(kind),
148 ));
149 kind
150 })
151 .map_with(|kind, e| Identifier {
152 span: e.span(),
153 name: kind.into(),
154 }))
155 .or(keyword
156 .validate(|kind, e, emitter| {
157 emitter.emit(Rich::custom(
158 e.span(),
159 ParseErrorKind::KeywordAsIdentifier(kind),
160 ));
161 kind
162 })
163 .map_with(|kind, e| Identifier {
164 span: e.span(),
165 name: kind.into(),
166 }))
167 .labelled("identifier")
168 .boxed();
169
170 let qualified_name = identifier_parser
171 .clone()
172 .separated_by(just(Token::SigilDoubleColon))
173 .at_least(1)
174 .collect::<Vec<_>>()
175 .with_extras()
176 .map_with(|(parts, extras), e| QualifiedName {
177 span: e.span(),
178 parts,
179 extras,
180 })
181 .labelled("qualified name")
182 .boxed();
183
184 let single_type = select_ref! {
185 Token::Identifier(ident) = e => SingleType {
186 span: e.span(),
187 name: ident.as_ref().into()
188 },
189 Token::Unit(unit) = e => SingleType {
190 span: e.span(),
191 name: unit.as_ref().into()
192 },
193 Token::SigilQuote = e => SingleType {
194 span: e.span(),
195 name: r#"""#.into()
196 },
197 }
198 .labelled("quantity type")
199 .boxed();
200
201 type_parser.define({
202 let single = single_type.clone().map(Type::Single);
203 let array = whitespace_parser()
204 .or_not()
205 .ignore_then(type_parser.clone())
206 .then_maybe_whitespace()
207 .delimited_by(
208 just(Token::SigilOpenSquareBracket),
209 just(Token::SigilCloseSquareBracket),
210 )
211 .map_with(|inner, e| {
212 Type::Array(ArrayType {
213 span: e.span(),
214 inner: Box::new(inner),
215 })
216 })
217 .labelled("array type")
218 .boxed();
219
220 let tuple = whitespace_parser()
221 .or_not()
222 .ignore_then(identifier_parser.clone())
223 .then_ignore(just(Token::SigilColon))
224 .or_not()
225 .then_maybe_whitespace()
226 .then(type_parser.clone())
227 .then_maybe_whitespace()
228 .separated_by(just(Token::SigilComma))
229 .allow_trailing()
230 .collect::<Vec<_>>()
231 .then_maybe_whitespace()
232 .delimited_with_spanned_error(
233 just(Token::SigilOpenBracket),
234 just(Token::SigilCloseBracket),
235 |err: Error, open, end| {
236 Rich::custom(
237 err.span().clone(),
238 ParseErrorKind::UnclosedBracket {
239 open,
240 end,
241 kind: "tuple type",
242 close_token: Token::SigilCloseBracket,
243 },
244 )
245 },
246 )
247 .map_with(|inner, e| {
248 Type::Tuple(TupleType {
249 span: e.span(),
250 inner,
251 })
252 })
253 .labelled("tuple type")
254 .boxed();
255
256 single.or(array).or(tuple).labelled("type").boxed()
257 });
258
259 let literal_parser = {
260 let single_value = select_ref! {
261 Token::LiteralFloat(x) = e => {
262 match f64::from_str(x) {
263 Ok(value) => LiteralKind::Float(FloatLiteral {
264 value,
265 span: e.span(),
266 }),
267 Err(err) => LiteralKind::Error(LiteralError {
268 span: e.span(),
269 kind: err.into(),
270 })
271 }
272 },
273 Token::LiteralInt(x) = e => {
274 match i64::from_str(x) {
275 Ok(value) => LiteralKind::Integer(IntegerLiteral {
276 value,
277 span: e.span(),
278 }),
279 Err(err) => LiteralKind::Error(LiteralError {
280 span: e.span(),
281 kind: err.into(),
282 })
283 }
284 },
285 Token::LiteralString(content) = e => {
286 LiteralKind::String(StringLiteral {
287 span: e.span(),
288 content: content.as_ref().into(),
289 })
290 },
291 Token::LiteralBool(value) = e => {
292 LiteralKind::Bool(BoolLiteral {
293 span: e.span(),
294 value: *value,
295 })
296 },
297 }
298 .boxed();
299
300 single_value
301 .then(single_type.clone().or_not())
302 .with_extras()
303 .try_map_with(|((literal, ty), extras), e| {
304 let literal = match (literal, ty) {
305 (LiteralKind::Float(float), Some(ty)) => {
306 LiteralKind::Quantity(QuantityLiteral {
307 span: e.span(),
308 value: float.value,
309 ty,
310 })
311 }
312 (LiteralKind::Integer(int), Some(ty)) => {
313 LiteralKind::Quantity(QuantityLiteral {
314 span: e.span(),
315 value: int.value as f64,
316 ty,
317 })
318 }
319 (_, Some(_)) => LiteralKind::Error(LiteralError {
320 span: e.span(),
321 kind: LiteralErrorKind::Untypable,
322 }),
323 (literal, None) => literal,
324 };
325 Ok(Literal {
326 span: e.span(),
327 literal,
328 extras,
329 })
330 })
331 .labelled("literal")
332 .boxed()
333 };
334
335 let unary_operator_parser = select_ref! {
336 Token::OperatorSubtract = e => UnaryOperator { span: e.span(), operation: UnaryOperatorType::Minus },
337 Token::OperatorAdd = e => UnaryOperator { span: e.span(), operation: UnaryOperatorType::Plus },
338 Token::OperatorNot = e => UnaryOperator { span: e.span(), operation: UnaryOperatorType::Not },
339 }
340 .labelled("unary operator")
341 .boxed();
342
343 let doc_comment = select_ref! {
344 Token::DocComment(comment) => comment,
345 }
346 .then_whitespace()
347 .repeated()
348 .at_least(1)
349 .collect::<Vec<_>>()
350 .map_with(|lines, e| Comment {
351 span: e.span(),
352 lines: lines.into_iter().map(|s| s.as_ref().into()).collect(),
353 })
354 .labelled("doc-comment")
355 .or_not()
356 .boxed();
357
358 let tuple_recovery = nested_delimiters(
359 Token::SigilOpenBracket,
360 Token::SigilCloseBracket,
361 [
362 (
363 Token::SigilOpenSquareBracket,
364 Token::SigilCloseSquareBracket,
365 ),
366 (Token::SigilOpenCurlyBracket, Token::SigilCloseCurlyBracket),
367 ],
368 |_| (),
369 )
370 .map_with(|_, e| (vec![TupleItem::dummy(e.span())], ItemExtras::default()));
371
372 let tuple_body = identifier_parser
373 .clone()
374 .then_maybe_whitespace()
375 .then_ignore(just(Token::OperatorAssignment).then_maybe_whitespace())
376 .or_not()
377 .then(expression_parser.clone())
378 .with_extras()
379 .map_with(|((name, value), extras), e| TupleItem {
380 span: e.span(),
381 extras,
382 name,
383 value,
384 })
385 .then_maybe_whitespace()
386 .separated_by(just(Token::SigilComma).then_maybe_whitespace())
387 .allow_trailing()
388 .collect::<Vec<_>>()
389 .boxed();
390
391 let call_inner = qualified_name
392 .clone()
393 .then_maybe_whitespace()
394 .then(
395 whitespace_parser()
396 .or_not()
397 .ignore_then(tuple_body.clone())
398 .with_extras()
399 .then_maybe_whitespace()
400 .map_with(|(arguments, extras), e| ArgumentList {
401 span: e.span(),
402 extras,
403 arguments: arguments
404 .into_iter()
405 .map(|item| match item.name {
406 Some(name) => Argument::Named(NamedArgument {
407 span: item.span,
408 extras: item.extras,
409 name,
410 value: item.value,
411 }),
412 None => Argument::Unnamed(UnnamedArgument {
413 span: item.span,
414 extras: item.extras,
415 value: item.value,
416 }),
417 })
418 .collect::<Vec<_>>(),
419 })
420 .labelled("function arguments")
421 .delimited_with_spanned_error(
422 just(Token::SigilOpenBracket),
423 just(Token::SigilCloseBracket),
424 |err: Error, open, end| {
425 Rich::custom(
426 err.span().clone(),
427 ParseErrorKind::UnclosedBracket {
428 open,
429 end,
430 kind: "function arguments",
431 close_token: Token::SigilCloseBracket,
432 },
433 )
434 },
435 )
436 .recover_with(via_parser(
437 tuple_recovery
438 .clone()
439 .map_with(|_, e| ArgumentList::dummy(e.span())),
440 )),
441 )
442 .with_extras()
443 .map_with(|((name, arguments), extras), e| Call {
444 span: e.span(),
445 extras,
446 name,
447 arguments,
448 })
449 .boxed();
450
451 statement_parser.define({
452 let visibility = select_ref! {
453 Token::KeywordPub => Visibility::Public,
454 }
455 .labelled("visibility");
456
457 let expression = attribute_parser
458 .clone()
459 .then(expression_parser.clone())
460 .with_extras()
461 .map_with(
462 |((attributes, expression), extras), e| ExpressionStatement {
463 span: e.span(),
464 extras,
465 attributes,
466 expression,
467 },
468 )
469 .map(Statement::Expression)
470 .boxed();
471
472 let local_assignment_inner = attribute_parser
473 .clone()
474 .then(identifier_parser.clone())
475 .then_maybe_whitespace()
476 .then(
477 just(Token::SigilColon)
478 .then_maybe_whitespace()
479 .ignore_then(type_parser.clone())
480 .then_maybe_whitespace()
481 .or_not(),
482 )
483 .then_ignore(just(Token::OperatorAssignment))
484 .then_maybe_whitespace()
485 .then(
486 expression_parser.clone().recover_with(via_parser(
487 semi_recovery
488 .clone()
489 .map_with(|_, e| Expression::Error(e.span())),
490 )),
491 )
492 .with_extras()
493 .map_with(
494 |((((attributes, name), ty), value), extras), e| LocalAssignment {
495 span: e.span(),
496 extras,
497 attributes,
498 name,
499 value: Box::new(value),
500 ty,
501 },
502 )
503 .boxed();
504
505 let local_assignment = local_assignment_inner
506 .clone()
507 .map(Statement::LocalAssignment)
508 .labelled("local assignment");
509
510 let const_assignment_inner = doc_comment
511 .clone()
512 .then(attribute_parser.clone())
513 .then(visibility.then_whitespace().or_not())
514 .then(just(Token::KeywordConst).map_with(|_, e| e.span()))
515 .then_maybe_whitespace()
516 .then(identifier_parser.clone())
517 .then_maybe_whitespace()
518 .then(
519 just(Token::SigilColon)
520 .then_maybe_whitespace()
521 .ignore_then(type_parser.clone())
522 .then_maybe_whitespace()
523 .or_not(),
524 )
525 .then_ignore(just(Token::OperatorAssignment))
526 .then_maybe_whitespace()
527 .then(
528 expression_parser.clone().recover_with(via_parser(
529 semi_recovery
530 .clone()
531 .map_with(|_, e| Expression::Error(e.span())),
532 )),
533 )
534 .with_extras()
535 .map_with(
536 |(
537 ((((((doc, attributes), visibility), keyword_span), name), ty), value),
538 extras,
539 ),
540 e| {
541 ConstAssignment {
542 span: e.span(),
543 keyword_span,
544 extras,
545 doc,
546 attributes,
547 visibility,
548 name,
549 value: Box::new(value),
550 ty,
551 }
552 },
553 )
554 .boxed();
555
556 let const_assignment = const_assignment_inner
557 .clone()
558 .map(Statement::Const)
559 .labelled("const assignment");
560
561 let pub_assignment_inner = doc_comment
563 .clone()
564 .then(attribute_parser.clone())
565 .then(just(Token::KeywordPub).map_with(|_, e| e.span()))
566 .then_maybe_whitespace()
567 .then(identifier_parser.clone())
568 .then_maybe_whitespace()
569 .then(
570 just(Token::SigilColon)
571 .then_maybe_whitespace()
572 .ignore_then(type_parser.clone())
573 .then_maybe_whitespace()
574 .or_not(),
575 )
576 .then_ignore(just(Token::OperatorAssignment))
577 .then_maybe_whitespace()
578 .then(
579 expression_parser.clone().recover_with(via_parser(
580 semi_recovery
581 .clone()
582 .map_with(|_, e| Expression::Error(e.span())),
583 )),
584 )
585 .with_extras()
586 .map_with(
587 |((((((doc, attributes), keyword_span), name), ty), value), extras), e| {
588 ConstAssignment {
589 span: e.span(),
590 keyword_span,
591 extras,
592 doc,
593 attributes,
594 visibility: Some(Visibility::Public),
595 name,
596 value: Box::new(value),
597 ty,
598 }
599 },
600 )
601 .boxed();
602
603 let pub_assignment = pub_assignment_inner
604 .clone()
605 .map(Statement::Const)
606 .labelled("pub const assignment");
607
608 let property_assignment_inner = doc_comment
609 .clone()
610 .then(attribute_parser.clone())
611 .then(just(Token::KeywordProp).map_with(|_, e| e.span()))
612 .then_maybe_whitespace()
613 .then(identifier_parser.clone())
614 .then_maybe_whitespace()
615 .then(
616 just(Token::SigilColon)
617 .then_maybe_whitespace()
618 .ignore_then(type_parser.clone())
619 .then_maybe_whitespace()
620 .or_not(),
621 )
622 .then_ignore(just(Token::OperatorAssignment))
623 .then_maybe_whitespace()
624 .then(
625 expression_parser.clone().recover_with(via_parser(
626 semi_recovery
627 .clone()
628 .map_with(|_, e| Expression::Error(e.span())),
629 )),
630 )
631 .with_extras()
632 .map_with(
633 |((((((doc, attributes), keyword_span), name), ty), value), extras), e| {
634 PropertyAssignment {
635 span: e.span(),
636 keyword_span,
637 extras,
638 doc,
639 attributes,
640 name,
641 value: Box::new(value),
642 ty,
643 }
644 },
645 )
646 .boxed();
647
648 let property_assignment = property_assignment_inner
649 .clone()
650 .map(Statement::Property)
651 .labelled("property assignment");
652
653 attribute_parser.define({
654 let attribute_command = local_assignment_inner
655 .clone()
656 .map(AttributeCommand::Assignment)
657 .or(call_inner.clone().map(AttributeCommand::Call))
658 .or(identifier_parser.clone().map(AttributeCommand::Ident));
659
660 just(Token::SigilHash)
661 .ignore_then(just(Token::OperatorNot).or_not().map(|opt| opt.is_some()))
662 .then(
663 attribute_command
664 .separated_by(just(Token::SigilComma).then_maybe_whitespace())
665 .at_least(1)
666 .collect::<Vec<_>>()
667 .then_maybe_whitespace()
668 .delimited_by(
669 just(Token::SigilOpenSquareBracket),
670 just(Token::SigilCloseSquareBracket),
671 ),
672 )
673 .then_whitespace()
674 .with_extras()
675 .map_with(|((is_inner, commands), extras), e| Attribute {
676 span: e.span(),
677 is_inner,
678 extras,
679 commands,
680 })
681 .labelled("attribute")
682 .repeated()
683 .collect::<Vec<Attribute>>()
684 .boxed()
685 });
686
687 let comment = comment_parser()
688 .map(Statement::Comment)
689 .then_maybe_whitespace()
690 .labelled("comment")
691 .boxed();
692
693 let parameter_list_inner = whitespace_parser()
694 .or_not()
695 .ignore_then(identifier_parser.clone())
696 .then_maybe_whitespace()
697 .then(
698 just(Token::SigilColon)
699 .then_maybe_whitespace()
700 .ignore_then(
701 type_parser.clone().recover_with(via_parser(
702 recovery_expect_any_except(&[
703 Token::SigilComma,
704 Token::OperatorAssignment,
705 Token::SigilCloseBracket,
706 ])
707 .map_with(|_, e| Type::dummy(e.span())),
708 )),
709 )
710 .then_maybe_whitespace()
711 .or_not(),
712 )
713 .then(
714 just(Token::OperatorAssignment)
715 .then_maybe_whitespace()
716 .ignore_then(
717 expression_parser.clone().recover_with(via_parser(
718 recovery_expect_any_except(&[
719 Token::SigilComma,
720 Token::SigilCloseBracket,
721 ])
722 .map_with(|_, e| Expression::Error(e.span())),
723 )),
724 )
725 .then_maybe_whitespace()
726 .or_not(),
727 )
728 .with_extras()
729 .map_with(|(((name, ty), default), extras), e| Parameter {
730 span: e.span(),
731 extras,
732 name,
733 ty,
734 default,
735 })
736 .then_maybe_whitespace()
737 .separated_by(just(Token::SigilComma))
738 .allow_trailing()
739 .collect::<Vec<_>>()
740 .boxed();
741
742 let parameter_list = parameter_list_inner
743 .then_maybe_whitespace()
744 .with_extras()
745 .map_with(|(parameters, extras), e| ParameterList {
746 span: e.span(),
747 extras,
748 parameters,
749 })
750 .delimited_with_spanned_error(
751 just(Token::SigilOpenBracket),
752 just(Token::SigilCloseBracket),
753 |err: Error, open, end| {
754 Rich::custom(
755 err.span().clone(),
756 ParseErrorKind::UnclosedBracket {
757 open,
758 end,
759 kind: "function parameters",
760 close_token: Token::SigilCloseBracket,
761 },
762 )
763 },
764 )
765 .recover_with(via_parser(
766 ignore_till_matched_brackets()
767 .or(none_of(STRUCTURAL_TOKENS).repeated())
768 .map_with(|_, e| ParameterList::dummy(e.span())),
769 ))
770 .boxed();
771
772 let module = doc_comment
773 .clone()
774 .then(attribute_parser.clone())
775 .then(visibility.then_whitespace().or_not())
776 .then(just(Token::KeywordMod).map_with(|_, e| e.span()))
777 .then_whitespace()
778 .then(
779 identifier_parser.clone().recover_with(via_parser(
780 recovery_expect_any_except(&[Token::SigilOpenCurlyBracket])
781 .map_with(|_, e| Identifier::dummy(e.span())),
782 )),
783 )
784 .then_maybe_whitespace()
785 .then(
786 block
787 .clone()
788 .map(Some)
789 .or(just(Token::SigilSemiColon).map(|_| None)),
790 )
791 .with_extras()
792 .map_with(
793 |((((((doc, attributes), visibility), keyword_span), name), body), extras), e| {
794 Statement::Module(ModuleDefinition {
795 span: e.span(),
796 keyword_span,
797 extras,
798 doc,
799 attributes,
800 visibility,
801 name,
802 body,
803 })
804 },
805 )
806 .boxed();
807
808 let use_part = identifier_parser
809 .clone()
810 .map(UseStatementPart::Identifier)
811 .or(just(Token::OperatorMultiply).map_with(|_, e| UseStatementPart::Glob(e.span())))
812 .recover_with(via_parser(
813 recovery_expect_any_except(&[Token::SigilDoubleColon])
814 .map_with(|_, e| UseStatementPart::Error(e.span())),
815 ))
816 .boxed();
817
818 let use_parts = use_part
819 .separated_by(just(Token::SigilDoubleColon))
820 .at_least(1)
821 .collect::<Vec<_>>()
822 .with_extras()
823 .map_with(|(parts, extras), e| UseName {
824 span: e.span(),
825 extras,
826 parts,
827 })
828 .boxed();
829
830 let use_statement = attribute_parser
831 .clone()
832 .then(visibility.then_whitespace().or_not())
833 .then(just(Token::KeywordUse).map_with(|_, e| e.span()))
834 .then_whitespace()
835 .then(use_parts)
836 .then(
837 whitespace_parser()
838 .then(just(Token::KeywordAs))
839 .then_whitespace()
840 .ignore_then(identifier_parser.clone().recover_with(via_parser(
841 recovery_expect_any().map_with(|_, e| Identifier::dummy(e.span())),
842 )))
843 .or_not(),
844 )
845 .with_extras()
846 .map_with(
847 |(((((attributes, visibility), keyword_span), name), use_as), extras), e| {
848 Statement::Use(UseStatement {
849 span: e.span(),
850 attributes,
851 visibility,
852 keyword_span,
853 extras,
854 name,
855 use_as,
856 })
857 },
858 )
859 .boxed();
860
861 let workbench_kind = select_ref! {
862 Token::KeywordSketch => WorkbenchKind::Sketch,
863 Token::KeywordPart => WorkbenchKind::Part,
864 Token::KeywordOp => WorkbenchKind::Op,
865 }
866 .boxed();
867
868 let init = doc_comment
869 .clone()
870 .then(attribute_parser.clone())
871 .then(just(Token::KeywordInit).map_with(|_, e| e.span()))
872 .then_maybe_whitespace()
873 .then(parameter_list.clone())
874 .then_maybe_whitespace()
875 .then(block.clone())
876 .with_extras()
877 .map_with(
878 |(((((doc, attributes), keyword_span), arguments), body), extras), e| {
879 Statement::Init(InitDefinition {
880 span: e.span(),
881 keyword_span,
882 extras,
883 doc,
884 attributes,
885 parameters: arguments,
886 body,
887 })
888 },
889 )
890 .boxed();
891 let workbench = doc_comment
892 .clone()
893 .then(attribute_parser.clone())
894 .then(visibility.then_whitespace().or_not())
895 .then(workbench_kind.map_with(|kind, e| (kind, e.span())))
896 .then_whitespace()
897 .then(
898 identifier_parser.clone().recover_with(via_parser(
899 recovery_expect_any_except(&[
900 Token::SigilOpenCurlyBracket,
901 Token::SigilOpenBracket,
902 ])
903 .map_with(|_, e| Identifier::dummy(e.span())),
904 )),
905 )
906 .then_maybe_whitespace()
907 .then(parameter_list.clone())
908 .then_maybe_whitespace()
909 .then(block.clone())
910 .with_extras()
911 .map_with(
912 |(
913 (
914 (
915 ((((doc, attributes), visibility), (kind, keyword_span)), name),
916 arguments,
917 ),
918 body,
919 ),
920 extras,
921 ),
922 e| {
923 Statement::Workbench(WorkbenchDefinition {
924 span: e.span(),
925 keyword_span,
926 extras,
927 kind,
928 doc,
929 attributes,
930 visibility,
931 name,
932 plan: arguments,
933 body,
934 })
935 },
936 )
937 .boxed();
938
939 let return_statement = just(Token::KeywordReturn)
940 .map_with(|_, e| e.span())
941 .then_maybe_whitespace()
942 .then(expression_parser.clone().or_not())
943 .with_extras()
944 .map_with(|((keyword_span, value), extras), e| {
945 Statement::Return(Return {
946 span: e.span(),
947 keyword_span,
948 extras,
949 value,
950 })
951 })
952 .boxed();
953
954 let function = doc_comment
955 .clone()
956 .then(visibility.then_whitespace().or_not())
957 .then(just(Token::KeywordFn).map_with(|_, e| e.span()))
958 .then_whitespace()
959 .then(
960 identifier_parser.clone().recover_with(via_parser(
961 recovery_expect_any_except(&[
962 Token::SigilOpenCurlyBracket,
963 Token::SigilOpenBracket,
964 ])
965 .map_with(|_, e| Identifier::dummy(e.span())),
966 )),
967 )
968 .then_maybe_whitespace()
969 .then(parameter_list.clone())
970 .then_maybe_whitespace()
971 .then(
972 just(Token::SigilSingleArrow)
973 .then_maybe_whitespace()
974 .ignore_then(type_parser.clone())
975 .then_maybe_whitespace()
976 .or_not(),
977 )
978 .then(block.clone())
979 .with_extras()
980 .map_with(
981 |(
982 ((((((doc, visibility), keyword_span), name), arguments), return_type), body),
983 extras,
984 ),
985 e| {
986 Statement::Function(FunctionDefinition {
987 span: e.span(),
988 keyword_span,
989 extras,
990 doc,
991 visibility,
992 name,
993 arguments,
994 return_type,
995 body,
996 })
997 },
998 )
999 .boxed();
1000
1001 let if_expression = attribute_parser
1002 .clone()
1003 .then(if_inner.clone().map(Expression::If))
1004 .with_extras()
1005 .map_with(|((attributes, expression), extras), e| {
1006 Statement::Expression(ExpressionStatement {
1007 span: e.span(),
1008 extras,
1009 attributes,
1010 expression,
1011 })
1012 })
1013 .labelled("if statement")
1014 .boxed();
1015
1016 let inner_doc_statement = select_ref! {
1017 Token::InnerDocComment(comment) => String::from(comment.as_ref()),
1018 }
1019 .then_maybe_whitespace()
1020 .repeated()
1021 .at_least(1)
1022 .collect::<Vec<_>>()
1023 .map_with(|lines, e| Comment {
1024 span: e.span(),
1025 lines,
1026 })
1027 .labelled("inner doc-comment")
1028 .map(Statement::InnerDocComment)
1029 .boxed();
1030
1031 let not_assigment = whitespace_parser()
1032 .or_not()
1033 .then(none_of([
1034 Token::OperatorAssignment,
1035 Token::SigilDoubleColon,
1036 ]))
1037 .ignored()
1038 .or(just(Token::SigilSemiColon).ignored())
1039 .rewind()
1040 .boxed();
1041
1042 let reserved_keyword_statement = reserved_keyword
1043 .clone()
1044 .then_ignore(not_assigment.clone())
1045 .try_map_with(|kind, e| {
1046 Err::<(), _>(Rich::custom(
1047 e.span(),
1048 ParseErrorKind::ReservedKeyword(kind),
1049 ))
1050 })
1051 .ignored()
1052 .recover_with(via_parser(
1053 reserved_keyword
1054 .then_ignore(not_assigment)
1055 .clone()
1056 .ignore_then(
1057 none_of(STRUCTURAL_TOKENS)
1058 .repeated()
1059 .then_ignore(ignore_till_matched_curly())
1060 .or(ignore_till_semi().then_ignore(just(Token::SigilSemiColon))),
1061 ),
1062 ))
1063 .map_with(|_, e| Statement::Error(e.span()))
1064 .boxed();
1065
1066 let with_semi = return_statement
1067 .or(use_statement)
1068 .or(const_assignment)
1069 .or(pub_assignment)
1070 .or(property_assignment)
1071 .or(local_assignment)
1072 .or(expression)
1073 .then_maybe_whitespace()
1074 .boxed();
1075
1076 let without_semi = function
1077 .or(inner_doc_statement)
1078 .or(init)
1079 .or(workbench)
1080 .or(module)
1081 .or(comment)
1082 .or(if_expression)
1083 .boxed();
1084
1085 without_semi
1086 .or(reserved_keyword_statement)
1087 .or(with_semi.then_ignore(
1088 just(Token::SigilSemiColon)
1089 .labelled("semicolon")
1090 .ignored()
1091 .recover_with(via_parser(
1092 none_of(STRUCTURAL_TOKENS)
1093 .repeated()
1094 .then_ignore(just(Token::SigilSemiColon)),
1095 )),
1096 ))
1097 .boxed()
1098 .labelled("statement")
1099 });
1100
1101 statement_list_parser.define({
1102 let trailing_expr = attribute_parser
1103 .clone()
1104 .then(expression_parser.clone())
1105 .with_extras()
1106 .map_with(
1107 |((attributes, expression), extras), e| ExpressionStatement {
1108 span: e.span(),
1109 extras,
1110 attributes,
1111 expression,
1112 },
1113 )
1114 .map(Statement::Expression)
1115 .map(Box::new)
1116 .or_not()
1117 .then_maybe_whitespace()
1118 .boxed();
1119
1120 whitespace_parser()
1121 .or_not()
1122 .ignore_then(statement_parser)
1123 .then_maybe_whitespace()
1124 .repeated()
1125 .collect::<Vec<_>>()
1126 .then(trailing_expr)
1127 .with_extras()
1128 .map_with(|((statements, tail), extras), e| StatementList {
1129 span: e.span(),
1130 extras,
1131 statements,
1132 tail,
1133 })
1134 .then_maybe_whitespace()
1135 .boxed()
1136 });
1137
1138 expression_parser.define({
1139 let unclosed_string = select_ref! {
1140 Token::Error(LexerError::UnclosedString(_)) => (),
1141 }
1142 .ignore_then(
1143 semi_recovery
1144 .clone()
1145 .try_map_with(|_, e| {
1146 let span: Span = e.span();
1147 Err::<Expression, _>(Rich::custom(
1148 (span.start - 1)..span.end,
1149 ParseErrorKind::UnterminatedString,
1150 ))
1151 })
1152 .recover_with(via_parser(
1153 semi_recovery
1154 .clone()
1155 .map_with(|_, e| Expression::Error(e.span())),
1156 )),
1157 )
1158 .labelled("unclosed string")
1159 .boxed();
1160
1161 let literal = literal_parser
1162 .map(Expression::Literal)
1163 .labelled("literal")
1164 .boxed()
1165 .or(unclosed_string);
1166
1167 let marker = just(Token::SigilAt)
1168 .ignore_then(identifier_parser.clone())
1169 .map(Expression::Marker)
1170 .labelled("marker")
1171 .boxed();
1172
1173 let string_content_part = select_ref! {
1174 Token::StringContent(content) = e => StringPart::Content(StringLiteral {
1175 span: e.span(),
1176 content: content.as_ref().into(),
1177 }),
1178 Token::Character(char) = e => StringPart::Char(StringCharacter {
1179 span: e.span(),
1180 character: *char,
1181 }),
1182 }
1183 .labelled("string content")
1184 .boxed();
1185
1186 let format_precision = select_ref!(
1187 Token::StringFormatPrecision(precision) = e => {
1188 u32::from_str(&precision[1..]).map_err(|err| (err, e.span()))
1189 }
1190 );
1191 let format_width = select_ref!(
1192 Token::StringFormatWidth(width) = e => {
1193 u32::from_str(&width[1..]).map_err(|err| (err, e.span()))
1194 }
1195 );
1196 let format_spec = format_width
1197 .or_not()
1198 .then(format_precision.or_not())
1199 .map_with(|(width, precision), e| StringFormatSpecification {
1200 span: e.span(),
1201 width,
1202 precision,
1203 })
1204 .labelled("string format specification")
1205 .boxed();
1206
1207 let string_format_part = expression_parser
1208 .clone()
1209 .then(format_spec)
1210 .with_extras()
1211 .delimited_by(
1212 just(Token::StringFormatOpen),
1213 just(Token::StringFormatClose),
1214 )
1215 .map_with(
1216 |((expression, specification), extras), e| StringExpression {
1217 span: e.span(),
1218 extras,
1219 expression: Box::new(expression),
1220 specification: Box::new(specification),
1221 },
1222 )
1223 .map(StringPart::Expression)
1224 .labelled("string format expression")
1225 .boxed();
1226 let string_part = string_content_part
1227 .or(string_format_part)
1228 .labelled("format string content");
1229
1230 let string_format = string_part
1231 .repeated()
1232 .collect::<Vec<_>>()
1233 .delimited_by(just(Token::FormatStringStart), just(Token::FormatStringEnd))
1234 .with_extras()
1235 .map_with(|(parts, extras), e| FormatString {
1236 span: e.span(),
1237 extras,
1238 parts,
1239 })
1240 .map(Expression::String)
1241 .boxed();
1242
1243 let tuple = whitespace_parser()
1244 .or_not()
1245 .ignore_then(tuple_body.clone())
1246 .then_maybe_whitespace()
1247 .with_extras()
1248 .delimited_with_spanned_error(
1249 just(Token::SigilOpenBracket),
1250 just(Token::SigilCloseBracket),
1251 |err: Error, open, end| {
1252 Rich::custom(
1253 err.span().clone(),
1254 ParseErrorKind::UnclosedBracket {
1255 open,
1256 end,
1257 kind: "tuple",
1258 close_token: Token::SigilCloseBracket,
1259 },
1260 )
1261 },
1262 )
1263 .map_with(|(values, extras), e| {
1264 Expression::Tuple(TupleExpression {
1265 span: e.span(),
1266 extras,
1267 values,
1268 })
1269 })
1270 .labelled("tuple");
1271
1272 let bracketed = expression_parser
1273 .clone()
1274 .then_maybe_whitespace()
1275 .delimited_with_spanned_error(
1276 just(Token::SigilOpenBracket).then_maybe_whitespace(),
1277 just(Token::SigilCloseBracket),
1278 |err: Error, open, end| {
1279 Rich::custom(
1280 err.span().clone(),
1281 ParseErrorKind::UnclosedBracket {
1282 open,
1283 end,
1284 kind: "bracketed expression",
1285 close_token: Token::SigilCloseBracket,
1286 },
1287 )
1288 },
1289 )
1290 .boxed();
1291
1292 let array_item = expression_parser
1293 .clone()
1294 .with_extras()
1295 .map_with(|(expression, extras), e| ArrayItem {
1296 span: e.span(),
1297 extras,
1298 expression,
1299 })
1300 .boxed();
1301
1302 let array_range = array_item
1303 .clone()
1304 .then_maybe_whitespace()
1305 .then_ignore(just(Token::SigilDoubleDot))
1306 .then_maybe_whitespace()
1307 .then(array_item.clone())
1308 .then_maybe_whitespace()
1309 .with_extras()
1310 .delimited_by(
1311 just(Token::SigilOpenSquareBracket).then_maybe_whitespace(),
1312 just(Token::SigilCloseSquareBracket),
1313 )
1314 .then(single_type.clone().or_not())
1315 .map_with(|(((start, end), extras), ty), e| {
1316 Expression::ArrayRange(ArrayRangeExpression {
1317 span: e.span(),
1318 extras,
1319 start: Box::new(start),
1320 end: Box::new(end),
1321 ty,
1322 })
1323 })
1324 .labelled("array range")
1325 .boxed();
1326
1327 let array_list = array_item
1328 .clone()
1329 .then_maybe_whitespace()
1330 .separated_by(just(Token::SigilComma).then_maybe_whitespace())
1331 .allow_trailing()
1332 .collect::<Vec<_>>()
1333 .with_extras()
1334 .delimited_by(
1335 just(Token::SigilOpenSquareBracket).then_maybe_whitespace(),
1336 just(Token::SigilCloseSquareBracket),
1337 )
1338 .then(single_type.clone().or_not())
1339 .map_with(|((items, extras), ty), e| {
1340 Expression::ArrayList(ArrayListExpression {
1341 span: e.span(),
1342 extras,
1343 items,
1344 ty,
1345 })
1346 })
1347 .labelled("array")
1348 .boxed();
1349
1350 let block_expression = block
1351 .clone()
1352 .map(Expression::Block)
1353 .labelled("block expression")
1354 .boxed();
1355
1356 if_inner.define(
1357 just(Token::KeywordIf)
1358 .map_with(|_, e| e.span())
1359 .then_whitespace()
1360 .then(expression_parser.clone())
1361 .then_maybe_whitespace()
1362 .then(block.clone())
1363 .then_maybe_whitespace()
1364 .then(
1365 just(Token::KeywordElse)
1366 .map_with(|_, e| e.span())
1367 .then_maybe_whitespace()
1368 .then(if_inner.clone())
1369 .map(|(span, inner)| (span, Box::new(inner)))
1370 .or_not(),
1371 )
1372 .then(
1373 just(Token::KeywordElse)
1374 .map_with(|_, e| e.span())
1375 .then_maybe_whitespace()
1376 .then(block.clone())
1377 .or_not(),
1378 )
1379 .with_extras()
1380 .map_with(
1381 |(((((if_span, condition), body), next_if), else_body), extras), e| {
1382 let (next_if_span, next_if) = next_if
1383 .map(|(span, if_expr)| (Some(span), Some(if_expr)))
1384 .unwrap_or((None, None));
1385 let (else_span, else_body) = else_body
1386 .map(|(span, body)| (Some(span), Some(body)))
1387 .unwrap_or((None, None));
1388 If {
1389 span: e.span(),
1390 if_span,
1391 extras,
1392 condition: Box::new(condition),
1393 body,
1394 next_if_span,
1395 next_if,
1396 else_span,
1397 else_body,
1398 }
1399 },
1400 )
1401 .boxed(),
1402 );
1403 let if_expression = if_inner
1404 .map(Expression::If)
1405 .labelled("if expression")
1406 .boxed();
1407
1408 let qualified_name_expr = identifier_parser
1409 .clone()
1410 .map_with(|ident, e| QualifiedName {
1411 span: e.span(),
1412 parts: vec![ident],
1413 extras: ItemExtras::default(),
1414 })
1415 .foldl_with(
1416 just(Token::SigilDoubleColon)
1417 .ignore_then(identifier_parser.clone())
1418 .repeated(),
1419 |mut acc, part, _| {
1420 acc.span.end = part.span.end;
1421 acc.parts.push(part);
1422 acc
1423 },
1424 )
1425 .with_extras()
1426 .map(|(mut name, extras)| {
1427 name.extras = extras;
1428 name
1429 })
1430 .map(Expression::QualifiedName)
1431 .boxed();
1432
1433 let call = call_inner
1434 .clone()
1435 .map(Expression::Call)
1436 .labelled("method call");
1437
1438 let bracket_based = bracketed.or(tuple).recover_with(via_parser(
1439 tuple_recovery
1440 .clone()
1441 .map_with(|_, e| Expression::Error(e.span())),
1442 ));
1443
1444 let base = literal
1445 .or(string_format)
1446 .or(call)
1447 .or(marker)
1448 .or(bracket_based)
1449 .or(array_range)
1450 .or(array_list)
1451 .or(block_expression)
1452 .or(if_expression)
1453 .or(qualified_name_expr)
1454 .boxed();
1455
1456 let access_attribute = just(Token::SigilHash)
1457 .ignore_then(identifier_parser.clone())
1458 .map(Element::Attribute)
1459 .labelled("attribute access")
1460 .boxed();
1461
1462 let access_tuple = just(Token::SigilDot)
1463 .ignore_then(identifier_parser.clone())
1464 .map(Element::Tuple)
1465 .labelled("tuple access")
1466 .boxed();
1467
1468 let access_method = just(Token::SigilDot)
1469 .ignore_then(call_inner)
1470 .map(Element::Method)
1471 .labelled("method call")
1472 .boxed();
1473
1474 let access_array = expression_parser
1475 .clone()
1476 .delimited_by(
1477 just(Token::SigilOpenSquareBracket),
1478 just(Token::SigilCloseSquareBracket),
1479 )
1480 .map(Box::new)
1481 .map(Element::ArrayElement)
1482 .labelled("array access")
1483 .boxed();
1484
1485 let access_item = access_attribute
1486 .or(access_method)
1487 .or(access_tuple)
1488 .or(access_array)
1489 .boxed();
1490
1491 let element_access = base
1492 .clone()
1493 .foldl_with(
1494 whitespace_parser()
1495 .or_not()
1496 .ignore_then(access_item)
1497 .repeated(),
1498 |value, element, e| {
1499 Expression::ElementAccess(ElementAccess {
1500 span: e.span(),
1501 value: value.into(),
1502 element,
1503 })
1504 },
1505 )
1506 .labelled("element access")
1507 .boxed();
1508
1509 let unary_expression = unary_operator_parser
1510 .then_maybe_whitespace()
1511 .then(element_access.clone())
1512 .with_extras()
1513 .map_with(|((op, rhs), extras), e| UnaryOperation {
1514 span: e.span(),
1515 extras,
1516 operation: op,
1517 rhs: rhs.into(),
1518 })
1519 .map(simplify_unary_op)
1520 .boxed();
1521
1522 let binary_param = element_access.or(unary_expression.clone());
1523
1524 let near = binop(binary_param, &[Token::OperatorNear]);
1525 let xor = binop(near, &[Token::OperatorPowerXor, Token::OperatorXor]);
1526 let union_intersect = binop(xor, &[Token::OperatorUnion, Token::OperatorIntersect]);
1527 let mul_div = binop(
1528 union_intersect,
1529 &[Token::OperatorMultiply, Token::OperatorDivide],
1530 );
1531 let add_sub = binop(mul_div, &[Token::OperatorAdd, Token::OperatorSubtract]);
1532 let less_greater_eq = binop(
1533 add_sub,
1534 &[Token::OperatorLessEqual, Token::OperatorGreaterEqual],
1535 );
1536 let less_greater = binop(
1537 less_greater_eq,
1538 &[Token::OperatorLessThan, Token::OperatorGreaterThan],
1539 );
1540 let eq_neq = binop(
1541 less_greater,
1542 &[Token::OperatorEqual, Token::OperatorNotEqual],
1543 );
1544 let or_and = binop(eq_neq, &[Token::OperatorOr, Token::OperatorAnd]);
1545
1546 or_and.labelled("expression").boxed()
1547 });
1548
1549 statement_list_parser
1550 .then_ignore(end())
1551 .map_with(move |statements, ex| SourceFile {
1552 span: ex.span(),
1553 statements,
1554 })
1555}