1use std::error::Error;
9use std::fmt::{Display, Formatter};
10
11use crate::cell_stream::{end_span, ends_with_cell_semicolon, frame_recovering};
12use crate::lexer::canonical_word_spelling;
13use crate::nodes::*;
14use crate::parse::{Lookahead, SignificantToken};
15use crate::{
16 CellStream, CellStreamError, CellTokenStream, CommentTrivia, Delimited, DelimiterKind,
17 DelimiterToken, DelimiterValue, LeadingTrivia, LexError, LexErrorKind, LiteralKind, Parse,
18 ParseStream, Parser, Punctuated, Recovered, Span, Spanned, Terminal, Token, TokenParseError,
19 TokenStream, TokenTree, Tokenize, TrailingTrivia, Trivia, lex_str, lex_str_recovering,
20};
21
22macro_rules! is_token {
24 ($token:expr, $($pattern:tt)*) => {
25 <Token![$($pattern)*] as Token>::matches_token_tree($token)
26 };
27}
28
29macro_rules! unexpected {
31 ($token:expr, $expected:expr) => {{
32 let token = $token;
33 NativeParseError::Unexpected {
34 span: token.expect_span(),
35 found: token.description(),
36 expected: $expected,
37 }
38 }};
39}
40
41const PREC_CLOSER: u8 = 6;
43const PREC_COMMA: u8 = 10;
45const PREC_CONTROL: u8 = 12;
47const PREC_LOOP_CLAUSE: u8 = 16;
49const PREC_COLLECTION: u8 = 56;
51const PREC_APPLICATION_RIGHT: u8 = 61;
53const PREC_APPLICATION: u8 = 62;
55
56#[derive(Debug)]
58pub struct NativeParser;
59
60impl Parser for NativeParser {
61 type Error = NativeParseError;
62
63 fn parse_cells(&mut self, cells: CellStream) -> Result<SourceFile, Self::Error> {
64 parse_cell_stream(cells)
65 }
66}
67
68pub fn parse_native(source: &str) -> Result<SourceFile, NativeParseError> {
75 let tokens = lex_str(source).map_err(NativeParseError::Lex)?;
76 let cells = tokenize_for_native_parser(tokens)?;
77 NativeParser.parse_cells(cells)
78}
79
80pub fn parse_native_recovering(
91 source: &str,
92) -> Result<Recovered<SourceFile, LexError>, NativeParseError> {
93 let recovered = lex_str_recovering(source).map_err(NativeParseError::Lex)?;
94 let (tokens, diagnostics) = recovered.into_parts();
95 let source = tokens.source();
96 let framed = frame_recovering(tokens);
97 let cells = CellStream::from_cells_with_source(
98 framed.cells.into_iter().chain(framed.incomplete),
99 source,
100 );
101 let syntax = NativeParser.parse_cells(cells)?;
102 Ok(Recovered::new(syntax, diagnostics))
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
107pub enum NativeCellState {
108 Empty,
110 Complete,
112 Incomplete,
114 Invalid,
116}
117
118#[derive(Debug)]
120pub struct CompletedNativeCell {
121 source: Span,
123 syntax: crate::nodes::Cell,
125}
126
127impl CompletedNativeCell {
128 pub fn source(&self) -> &str {
134 self.source
135 .text()
136 .expect("completed cell source spans must resolve to text")
137 }
138
139 pub fn syntax(&self) -> &crate::nodes::Cell {
141 &self.syntax
142 }
143
144 pub fn into_parts(self) -> (Span, crate::nodes::Cell) {
146 (self.source, self.syntax)
147 }
148}
149
150#[derive(Debug)]
175pub struct NativeCellParser {
176 active_source: String,
178 active_tokens: TokenStream,
180 active_syntax: Option<crate::nodes::Cell>,
182 completed: Vec<CompletedNativeCell>,
184 lexer_diagnostics: Vec<LexError>,
186 parse_error: Option<NativeParseError>,
188 state: NativeCellState,
190}
191
192impl Default for NativeCellParser {
193 fn default() -> Self {
194 Self::new()
195 }
196}
197
198impl NativeCellParser {
199 pub fn new() -> Self {
201 Self {
202 active_source: String::new(),
203 active_tokens: TokenStream::new(),
204 active_syntax: None,
205 completed: Vec::new(),
206 lexer_diagnostics: Vec::new(),
207 parse_error: None,
208 state: NativeCellState::Empty,
209 }
210 }
211
212 pub fn push_line(&mut self, line: &str) -> NativeCellState {
219 self.active_source.push_str(line);
220 if !line.ends_with('\n') {
221 self.active_source.push('\n');
222 }
223 self.refresh()
224 }
225
226 pub fn state(&self) -> NativeCellState {
228 self.state
229 }
230
231 pub fn active_source(&self) -> &str {
233 &self.active_source
234 }
235
236 pub fn active_tokens(&self) -> &TokenStream {
238 &self.active_tokens
239 }
240
241 pub fn active_syntax(&self) -> Option<&crate::nodes::Cell> {
243 self.active_syntax.as_ref()
244 }
245
246 pub fn lexer_diagnostics(&self) -> &[LexError] {
248 &self.lexer_diagnostics
249 }
250
251 pub fn parse_error(&self) -> Option<&NativeParseError> {
253 self.parse_error.as_ref()
254 }
255
256 pub fn completed(&self) -> &[CompletedNativeCell] {
258 &self.completed
259 }
260
261 pub fn take_completed(&mut self) -> Vec<CompletedNativeCell> {
263 let completed = std::mem::take(&mut self.completed);
264 if self.state == NativeCellState::Complete {
265 self.state = NativeCellState::Empty;
266 }
267 completed
268 }
269
270 pub fn reset_active(&mut self) {
272 self.active_source.clear();
273 self.active_tokens = TokenStream::new();
274 self.active_syntax = None;
275 self.lexer_diagnostics.clear();
276 self.parse_error = None;
277 self.state = if self.completed.is_empty() {
278 NativeCellState::Empty
279 } else {
280 NativeCellState::Complete
281 };
282 }
283
284 fn refresh(&mut self) -> NativeCellState {
286 self.active_tokens = TokenStream::new();
287 self.active_syntax = None;
288 self.lexer_diagnostics.clear();
289 self.parse_error = None;
290
291 loop {
292 let recovered = match lex_str_recovering(&self.active_source) {
293 Ok(recovered) => recovered,
294 Err(error) => {
295 self.state = if incomplete_lex_error(error.kind()) {
296 NativeCellState::Incomplete
297 } else {
298 NativeCellState::Invalid
299 };
300 self.lexer_diagnostics.push(error);
301 return self.state;
302 }
303 };
304 let (tokens, diagnostics) = recovered.into_parts();
305 let framed = frame_recovering(tokens.clone());
306 let has_incomplete = framed.incomplete.is_some();
307 let mut cells = framed.cells.into_iter().map(|cell| (cell, true));
308 let first = cells
309 .next()
310 .or_else(|| framed.incomplete.map(|cell| (cell, false)));
311 let Some((cell, cell_complete)) = first else {
312 self.active_tokens = tokens;
313 self.lexer_diagnostics = diagnostics;
314 self.state = if self.completed.is_empty() {
315 NativeCellState::Empty
316 } else {
317 NativeCellState::Complete
318 };
319 return self.state;
320 };
321
322 let has_following_cell = cells.next().is_some() || has_incomplete;
323 let ended_by_semicolon = ends_with_cell_semicolon(&cell);
324 let boundary = end_span(&cell);
325 let end = boundary.end().unwrap_or(self.active_source.len());
326 let source = Span::ranged(std::sync::Arc::clone(boundary.source()), 0..end);
327
328 match parse_raw_cell(cell) {
329 Ok(Some(syntax)) if cell_complete && has_following_cell => {
330 self.completed.push(CompletedNativeCell { source, syntax });
331 self.active_source.replace_range(..end, "");
332 }
333 Ok(Some(syntax)) if cell_complete && diagnostics.is_empty() => {
334 self.completed.push(CompletedNativeCell { source, syntax });
335 self.active_source.clear();
336 self.active_tokens = TokenStream::new();
337 self.state = NativeCellState::Complete;
338 return self.state;
339 }
340 Ok(Some(syntax)) => {
341 self.active_tokens = tokens;
342 self.active_syntax = Some(syntax);
343 self.lexer_diagnostics = diagnostics;
344 self.state = NativeCellState::Incomplete;
345 return self.state;
346 }
347 Ok(None) => {
348 self.active_tokens = tokens;
349 self.lexer_diagnostics = diagnostics;
350 self.state = if self.completed.is_empty() {
351 NativeCellState::Empty
352 } else {
353 NativeCellState::Complete
354 };
355 return self.state;
356 }
357 Err(error) => {
358 let can_append_to_cell =
359 !cell_complete || (!has_following_cell && !ended_by_semicolon);
360 self.state = if can_append_to_cell && incomplete_parse_error(&error) {
361 NativeCellState::Incomplete
362 } else {
363 NativeCellState::Invalid
364 };
365 self.active_tokens = tokens;
366 self.lexer_diagnostics = diagnostics;
367 self.parse_error = Some(error);
368 return self.state;
369 }
370 }
371 }
372 }
373}
374
375pub(crate) fn incomplete_lex_error(kind: LexErrorKind) -> bool {
377 matches!(
378 kind,
379 LexErrorKind::UnterminatedGroup
380 | LexErrorKind::UnterminatedString
381 | LexErrorKind::UnterminatedRawString
382 | LexErrorKind::UnterminatedBlockComment
383 )
384}
385
386pub(crate) fn incomplete_parse_error(error: &NativeParseError) -> bool {
388 match error {
389 NativeParseError::MissingOperand { .. } => true,
390 NativeParseError::Unexpected { found, .. } => found == "end of input",
391 NativeParseError::Lex(error) => incomplete_lex_error(error.kind()),
392 NativeParseError::Tokenize(_) => true,
393 NativeParseError::NewlineInApplication { .. }
394 | NativeParseError::InvalidAssignmentTarget { .. }
395 | NativeParseError::InvalidLambdaArguments { .. }
396 | NativeParseError::Unsupported { .. } => false,
397 }
398}
399
400#[derive(Debug, Spanned)]
401pub enum NativeParseError {
403 Lex(LexError),
405 Tokenize(CellStreamError),
407 Unexpected {
409 found: String,
411 expected: &'static str,
413 span: Span,
415 },
416 MissingOperand {
418 operator: String,
420 span: Span,
422 },
423 NewlineInApplication {
425 span: Span,
427 },
428 InvalidAssignmentTarget {
430 span: Span,
432 },
433 InvalidLambdaArguments {
435 span: Span,
437 },
438 Unsupported {
440 syntax: String,
442 span: Span,
444 },
445}
446
447impl NativeParseError {
448 fn unexpected_end(expected: &'static str, span: Span) -> Self {
450 Self::Unexpected {
451 found: "end of input".into(),
452 expected,
453 span,
454 }
455 }
456
457 fn missing_operand_for(self, operator: &TokenTree) -> Self {
459 if matches!(self, Self::MissingOperand { .. }) {
460 Self::MissingOperand {
461 operator: operator.description(),
462 span: operator.expect_span(),
463 }
464 } else {
465 self
466 }
467 }
468}
469
470impl Display for NativeParseError {
471 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
472 match self {
473 Self::Lex(error) => error.fmt(formatter),
474 Self::Tokenize(error) => error.fmt(formatter),
475 Self::Unexpected {
476 found, expected, ..
477 } => write!(formatter, "expected {expected}, found `{found}`"),
478 Self::MissingOperand { operator, .. } => {
479 write!(
480 formatter,
481 "expected an operand after `{operator}`, found end of input"
482 )
483 }
484 Self::NewlineInApplication { .. } => {
485 formatter.write_str("implicit application cannot cross a line break")
486 }
487 Self::InvalidAssignmentTarget { .. } => {
488 formatter.write_str("invalid assignment target")
489 }
490 Self::InvalidLambdaArguments { .. } => {
491 formatter.write_str("invalid lambda argument list")
492 }
493 Self::Unsupported { syntax, .. } => {
494 write!(
495 formatter,
496 "native parsing of `{syntax}` is not implemented yet"
497 )
498 }
499 }
500 }
501}
502
503impl Error for NativeParseError {
504 fn source(&self) -> Option<&(dyn Error + 'static)> {
505 match self {
506 Self::Lex(error) => Some(error),
507 Self::Tokenize(error) => Some(error),
508 _ => None,
509 }
510 }
511}
512
513#[derive(Debug, Clone, Copy)]
514enum UnaryAction {
520 Atom,
522 Prefix,
524 Statement,
526 Control,
528 Debug,
530 Delimiter,
532 Quote,
534 Error,
536}
537
538#[derive(Debug, Clone, Copy)]
539struct ParseInfo {
541 precedence: u8,
543 binary_strength: Option<u8>,
545 unary_strength: Option<u8>,
547 unary: UnaryAction,
549 postfix: bool,
551}
552
553impl From<TokenParseRule> for ParseInfo {
554 fn from(rule: TokenParseRule) -> Self {
555 match rule {
556 TokenParseRule::Precedence(precedence) => Self::stop(precedence),
557 TokenParseRule::Postfix(precedence) => Self::postfix(precedence),
558 TokenParseRule::Binary(precedence, strength) => Self::binary(precedence, strength),
559 TokenParseRule::Prefix(precedence, strength) => {
560 Self::unary(precedence, UnaryAction::Prefix, strength)
561 }
562 TokenParseRule::PrefixBinary(precedence, binary, unary) => {
563 Self::prefix_binary(precedence, binary, unary)
564 }
565 TokenParseRule::Unary(precedence, strength) => {
566 Self::unary(precedence, UnaryAction::Error, strength)
567 }
568 }
569 }
570}
571
572impl ParseInfo {
573 const fn atom(precedence: u8) -> Self {
575 Self {
576 precedence,
577 binary_strength: None,
578 unary_strength: None,
579 unary: UnaryAction::Atom,
580 postfix: false,
581 }
582 }
583
584 const fn binary(precedence: u8, strength: u8) -> Self {
586 Self {
587 precedence,
588 binary_strength: Some(strength),
589 unary_strength: None,
590 unary: UnaryAction::Error,
591 postfix: false,
592 }
593 }
594
595 const fn prefix_binary(precedence: u8, binary_strength: u8, unary_strength: u8) -> Self {
597 Self {
598 precedence,
599 binary_strength: Some(binary_strength),
600 unary_strength: Some(unary_strength),
601 unary: UnaryAction::Prefix,
602 postfix: false,
603 }
604 }
605
606 const fn unary(precedence: u8, unary: UnaryAction, strength: u8) -> Self {
610 Self {
611 precedence,
612 binary_strength: None,
613 unary_strength: Some(strength),
614 unary,
615 postfix: false,
616 }
617 }
618
619 const fn postfix(precedence: u8) -> Self {
621 Self {
622 precedence,
623 binary_strength: None,
624 unary_strength: None,
625 unary: UnaryAction::Error,
626 postfix: true,
627 }
628 }
629
630 const fn delimiter(precedence: u8) -> Self {
632 Self {
633 precedence,
634 binary_strength: None,
635 unary_strength: Some(PREC_CLOSER),
636 unary: UnaryAction::Delimiter,
637 postfix: false,
638 }
639 }
640
641 const fn stop(precedence: u8) -> Self {
643 Self {
644 precedence,
645 binary_strength: None,
646 unary_strength: None,
647 unary: UnaryAction::Error,
648 postfix: false,
649 }
650 }
651}
652
653struct Engine {
655 input: ParseStream,
657}
658
659struct Components<T> {
661 first: T,
663 rest: Vec<(Token![,], T)>,
665}
666
667impl<T> Components<T> {
668 fn from_punctuated(values: Punctuated<T>) -> Self {
670 let (pair, rest) = values.into_parts();
671 let (first, punctuation, second) = pair.into_parts();
672 let mut pairs = Vec::with_capacity(rest.len() + 1);
673 pairs.push((punctuation, second));
674 pairs.extend(rest);
675 Self { first, rest: pairs }
676 }
677
678 fn is_punctuated(&self) -> bool {
680 !self.rest.is_empty()
681 }
682
683 fn into_punctuated(self) -> Result<Punctuated<T>, T> {
685 let mut rest = self.rest.into_iter();
686 let Some((punctuation, second)) = rest.next() else {
687 return Err(self.first);
688 };
689 let mut values = Punctuated::new(self.first, punctuation, second);
690 for (punctuation, value) in rest {
691 values.push(punctuation, value);
692 }
693 Ok(values)
694 }
695
696 fn map<U>(self, mut map: impl FnMut(T) -> Option<U>) -> Option<Components<U>> {
698 Some(Components {
699 first: map(self.first)?,
700 rest: self
701 .rest
702 .into_iter()
703 .map(|(punctuation, value)| Some((punctuation, map(value)?)))
704 .collect::<Option<Vec<_>>>()?,
705 })
706 }
707}
708
709impl Engine {
710 fn new(tokens: TokenStream) -> Self {
712 Self {
713 input: ParseStream::new(tokens),
714 }
715 }
716
717 fn parse_cell(
719 mut self,
720 semicolon: Option<Token![;]>,
721 eoc_span: Span,
722 ) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
723 self.skip_trivia();
724 if matches!(self.peek(), Lookahead::End(_)) {
725 return match semicolon {
726 None => Ok(None),
727 Some(semicolon) => Err(NativeParseError::Unexpected {
728 found: ";".into(),
729 expected: "a statement before `;`",
730 span: semicolon.expect_span(),
731 }),
732 };
733 }
734
735 let components = self.parse_components()?;
736
737 if let Lookahead::Token(token) = self.peek() {
738 return Err(unexpected!(token.token, "the end of the cell"));
739 }
740
741 let eoc = EOC::new("", eoc_span);
742 Ok(Some(crate::nodes::Cell::new(
743 self.packed_content(components)?,
744 semicolon,
745 eoc,
746 )))
747 }
748
749 fn parse_components(&mut self) -> Result<Components<Component>, NativeParseError> {
751 let first = if self.at_punctuation(",") {
752 Component::Empty(Empty::new("", empty_span_at(&self.peek().expect_span())))
753 } else {
754 self.parse_required(PREC_COMMA)?.into()
755 };
756 let mut rest = Vec::new();
757
758 while let Some(comma) = self.take_punctuation(",") {
759 let next = if self.at_end() || self.at_punctuation(";") || self.at_punctuation(",") {
760 Component::Empty(Empty::new("", empty_span_at(&self.peek().expect_span())))
761 } else {
762 self.parse_required(PREC_COMMA)?.into()
763 };
764 rest.push((typed_token(comma), next));
765 }
766
767 Ok(Components { first, rest })
768 }
769
770 fn parse_optional_components(
772 &mut self,
773 ) -> Result<Option<Components<Component>>, NativeParseError> {
774 if self.at_end() || self.at_punctuation(";") {
775 Ok(None)
776 } else {
777 self.parse_components().map(Some)
778 }
779 }
780
781 fn parse_required(&mut self, level: u8) -> Result<Expr, NativeParseError> {
783 let token = match self.consume() {
784 Lookahead::Token(token) => token,
785 Lookahead::End(span) => {
786 return Err(NativeParseError::MissingOperand {
787 operator: "end of input".into(),
788 span,
789 });
790 }
791 };
792 self.parse_consumed(token, level)
793 }
794
795 fn parse_nullable(&mut self, level: u8) -> Result<Option<Expr>, NativeParseError> {
797 let lookahead = self.peek();
798 let Lookahead::Token(token) = lookahead else {
799 return Ok(None);
800 };
801 if parse_info(&token.token).precedence <= level {
802 return Ok(None);
803 }
804 let Lookahead::Token(token) = self.consume() else {
805 unreachable!("the token just peeked is consumable")
806 };
807 self.parse_consumed(token, level).map(Some)
808 }
809
810 fn parse_consumed(
812 &mut self,
813 token: SignificantToken,
814 level: u8,
815 ) -> Result<Expr, NativeParseError> {
816 let info = parse_info(&token.token);
817 let result = match info.unary {
818 UnaryAction::Atom => lower_atom(token)?,
819 UnaryAction::Prefix => {
820 let strength = info.unary_strength.expect("prefix operators have U");
821 let operand = self.parse_required(level.max(strength))?;
822 let span = token.token.expect_span();
823 let spelling = token.token.description();
824 let operator =
825 PrefixOperator::from_token_tree_with_trivia(token.token, token.trailing_trivia)
826 .ok_or({
827 NativeParseError::Unsupported {
828 syntax: spelling,
829 span,
830 }
831 })?;
832 Expr!(Op::Prefix {
833 operator,
834 operand: Box::new(operand),
835 })
836 }
837 UnaryAction::Statement => {
838 let strength = info
839 .unary_strength
840 .expect("prefix statements have a unary binding strength");
841 let operand = if is_token!(&token.token, break)
842 || is_token!(&token.token, continue)
843 || is_token!(&token.token, return)
844 {
845 self.parse_nullable(level.max(strength))?
846 } else {
847 self.parse_required(level.max(strength))
848 .map_err(|error| error.missing_operand_for(&token.token))?
849 .into()
850 };
851 lower_prefix_statement(token, operand)
852 }
853 UnaryAction::Control => {
854 if is_token!(&token.token, if) {
855 self.parse_if_statement(token)?
856 } else if is_token!(&token.token, for) {
857 self.parse_for_loop(token)?
858 } else if is_token!(&token.token, while) {
859 self.parse_while_loop(token)?
860 } else if is_token!(&token.token, try) {
861 self.parse_try_statement(token)?
862 } else if is_token!(&token.token, new) {
863 self.parse_new_statement(token)?
864 } else {
865 unreachable!("control actions are assigned only to control keywords")
866 }
867 }
868 UnaryAction::Debug => self.parse_debug_clause(token)?,
869 UnaryAction::Delimiter => parse_delimited(token)?,
870 UnaryAction::Quote => {
871 let operator = token.token.description();
872 let quoted = match self.consume() {
873 Lookahead::Token(quoted) => quoted,
874 Lookahead::End(span) => {
875 return Err(NativeParseError::MissingOperand { operator, span });
876 }
877 };
878 let quoted_span = quoted.token.expect_span();
879 let Some(quoted_text) = quoted.token.spelling().map(str::to_owned) else {
880 return Err(unexpected!(quoted.token, "a quoted token"));
881 };
882 let quoted = typed_terminal(
883 Symbol::new(quoted_text, quoted_span),
884 quoted.trailing_trivia,
885 );
886 if is_token!(&token.token, symbol) {
887 Expr!(Quote::Symbol {
888 specifier: typed_token(token),
889 symbol: quoted,
890 })
891 } else if is_token!(&token.token, local) {
892 Expr!(Quote::Local {
893 specifier: typed_token(token),
894 symbol: quoted,
895 })
896 } else if is_token!(&token.token, global) {
897 Expr!(Quote::Global {
898 specifier: typed_token(token),
899 symbol: quoted,
900 })
901 } else if is_token!(&token.token, threadVariable) {
902 Expr!(Quote::ThreadVariable {
903 specifier: typed_token(token),
904 symbol: quoted,
905 })
906 } else if is_token!(&token.token, threadLocal) {
907 Expr!(Quote::ThreadLocal {
908 specifier: typed_token(token),
909 symbol: quoted,
910 })
911 } else {
912 unreachable!("quote actions are assigned only to quote specifiers")
913 }
914 }
915 UnaryAction::Error => {
916 return Err(unexpected!(token.token, "an expression"));
917 }
918 };
919 self.accumulate(result, level)
920 }
921
922 fn parse_if_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
924 let condition = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
925 let then_keyword = self.consume_exact("then")?;
926 let then_value = self.required_clause_expression(PREC_CONTROL, &then_keyword.token)?;
927 let then_clause = ThenClause::new(typed_token(then_keyword), Box::new(then_value));
928 let else_clause = self
929 .take_exact("else")
930 .map(|else_keyword| {
931 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword.token)?;
932 Ok::<_, NativeParseError>(ElseClause::new(
933 typed_token(else_keyword),
934 Box::new(value),
935 ))
936 })
937 .transpose()?;
938 Ok(Expr!(If {
939 if_token: typed_token(keyword),
940 condition: Box::new(condition),
941 then_clause,
942 else_clause,
943 }))
944 }
945
946 fn parse_for_loop(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
948 let variable = self.consume_symbol("a loop variable")?;
949
950 enum Domain {
951 Bare,
953 Range(Option<RangeBoundFrom>, Option<RangeBoundTo>),
955 In(SignificantToken, Box<Expr>),
957 }
958 let domain = if let Some(token) = self.take_exact("in") {
959 let collection = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
960 Domain::In(token, Box::new(collection))
961 } else {
962 let lower_bound = self
963 .take_exact("from")
964 .map(|token| {
965 let value = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
966 Ok::<_, NativeParseError>(RangeBoundFrom::new(
967 typed_token(token),
968 Box::new(value),
969 ))
970 })
971 .transpose()?;
972 let upper_bound = self
973 .take_exact("to")
974 .map(|token| {
975 let value = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
976 Ok::<_, NativeParseError>(RangeBoundTo::new(
977 typed_token(token),
978 Box::new(value),
979 ))
980 })
981 .transpose()?;
982 if lower_bound.is_some() || upper_bound.is_some() {
983 Domain::Range(lower_bound, upper_bound)
984 } else {
985 Domain::Bare
986 }
987 };
988
989 let when_condition = if let Some(token) = self.take_exact("when") {
990 let condition = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
991 Some(WhenCondition::new(typed_token(token), Box::new(condition)))
992 } else {
993 None
994 };
995 let body = self.parse_loop_body()?;
996
997 Ok(match domain {
998 Domain::Bare => Expr!(For::Bare {
999 for_token: typed_token(keyword),
1000 variable,
1001 condition: when_condition,
1002 body,
1003 }),
1004 Domain::Range(lower_bound, upper_bound) => Expr!(For::Range {
1005 for_token: typed_token(keyword),
1006 variable,
1007 lower_bound,
1008 upper_bound,
1009 condition: when_condition,
1010 body,
1011 }),
1012 Domain::In(token, collection) => Expr!(For::In {
1013 for_token: typed_token(keyword),
1014 variable,
1015 in_token: typed_token(token),
1016 collection,
1017 condition: when_condition,
1018 body,
1019 }),
1020 })
1021 }
1022
1023 fn parse_while_loop(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1025 let condition = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
1026 let body = self.parse_loop_body()?;
1027 Ok(Expr!(While {
1028 while_token: typed_token(keyword),
1029 condition: Box::new(condition),
1030 body,
1031 }))
1032 }
1033
1034 fn parse_loop_body(&mut self) -> Result<LoopBody, NativeParseError> {
1036 let (list_step, do_step) = if let Some(token) = self.take_exact("list") {
1037 let listed_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
1038 let list_step = Some(ListStep::new(typed_token(token), Box::new(listed_value)));
1039 if let Some(token) = self.take_exact("do") {
1040 let ignored_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
1041 (
1042 list_step,
1043 Some(DoStep::new(typed_token(token), Box::new(ignored_value))),
1044 )
1045 } else {
1046 (list_step, None)
1047 }
1048 } else if let Some(token) = self.take_exact("do") {
1049 let ignored_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
1050 (
1051 None,
1052 Some(DoStep::new(typed_token(token), Box::new(ignored_value))),
1053 )
1054 } else {
1055 return Err(self.expected_at_lookahead("`list` or `do`"));
1056 };
1057
1058 Ok(LoopBody::new(list_step, do_step))
1059 }
1060
1061 fn parse_try_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1063 let value = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
1064 let then_clause = self
1065 .take_exact("then")
1066 .map(|then_keyword| {
1067 let value = self.required_clause_expression(PREC_CONTROL, &then_keyword.token)?;
1068 Ok::<_, NativeParseError>(ThenClause::new(
1069 typed_token(then_keyword),
1070 Box::new(value),
1071 ))
1072 })
1073 .transpose()?;
1074
1075 let fallback = if let Some(else_keyword) = self.take_exact("else") {
1076 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword.token)?;
1077 Some(TryFallback::Else(ElseClause::new(
1078 typed_token(else_keyword),
1079 Box::new(value),
1080 )))
1081 } else if let Some(except_keyword) = self.take_exact("except") {
1082 let exception = self.consume_symbol("an exception symbol")?;
1083 let do_keyword = self.consume_exact("do")?;
1084 let value = self.required_clause_expression(PREC_CONTROL, &do_keyword.token)?;
1085 Some(TryFallback!(Except {
1086 except_token: typed_token(except_keyword),
1087 exception,
1088 do_token: typed_token(do_keyword),
1089 value: Box::new(value),
1090 }))
1091 } else {
1092 None
1093 };
1094
1095 Ok(Expr!(Try {
1096 try_token: typed_token(keyword),
1097 value: Box::new(value),
1098 on_success: then_clause,
1099 fallback,
1100 }))
1101 }
1102
1103 fn parse_new_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1105 let class = self.required_clause_expression(PREC_LOOP_CLAUSE, &keyword.token)?;
1106 let parent_class = if let Some(token) = self.take_exact("of") {
1107 let parent = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
1108 Some(OfClass::new(typed_token(token), Box::new(parent)))
1109 } else {
1110 None
1111 };
1112 let instance = if let Some(token) = self.take_exact("from") {
1113 let instance = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
1114 Some(FromInstance::new(typed_token(token), Box::new(instance)))
1115 } else {
1116 None
1117 };
1118
1119 Ok(Expr!(New {
1120 new_token: typed_token(keyword),
1121 class: Box::new(class),
1122 parent_class,
1123 instance,
1124 }))
1125 }
1126
1127 fn parse_debug_clause(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1129 let spelling = parsing_spelling(&keyword.token).to_owned();
1130 if matches!(
1131 spelling.as_str(),
1132 "time" | "timing" | "elapsedTime" | "elapsedTiming" | "profile"
1133 ) {
1134 let value = self
1135 .parse_required(PREC_CONTROL)
1136 .map_err(|error| error.missing_operand_for(&keyword.token))?;
1137 return Ok(match spelling.as_str() {
1138 "time" => Expr!(Profile::Time {
1139 modifier: typed_token(keyword),
1140 value: Box::new(value),
1141 }),
1142 "timing" => Expr!(Profile::Timing {
1143 modifier: typed_token(keyword),
1144 value: Box::new(value),
1145 }),
1146 "elapsedTime" => Expr!(Profile::ElapsedTime {
1147 modifier: typed_token(keyword),
1148 value: Box::new(value),
1149 }),
1150 "elapsedTiming" => Expr!(Profile::ElapsedTiming {
1151 modifier: typed_token(keyword),
1152 value: Box::new(value),
1153 }),
1154 "profile" => Expr!(Profile::Profile {
1155 modifier: typed_token(keyword),
1156 value: Box::new(value),
1157 }),
1158 _ => unreachable!(),
1159 });
1160 }
1161 let value_is_optional = matches!(spelling.as_str(), "step" | "finish");
1162 let value = if value_is_optional {
1163 self.parse_nullable(PREC_CONTROL)?
1164 } else {
1165 Some(
1166 self.parse_required(PREC_CONTROL)
1167 .map_err(|error| error.missing_operand_for(&keyword.token))?,
1168 )
1169 };
1170 let value = value.map(Box::new);
1171 Ok(match spelling.as_str() {
1172 "step" => Expr!(Debug::Step {
1173 keyword: typed_token(keyword),
1174 value,
1175 }),
1176 "finish" => Expr!(Debug::Finish {
1177 keyword: typed_token(keyword),
1178 value,
1179 }),
1180 "shield" => Expr!(Debug::Shield {
1181 keyword: typed_token(keyword),
1182 value,
1183 }),
1184 "TEST" => Expr!(Debug::Test {
1185 keyword: typed_token(keyword),
1186 value,
1187 }),
1188 "breakpoint" => Expr!(Debug::Breakpoint {
1189 keyword: typed_token(keyword),
1190 value,
1191 }),
1192 _ => unreachable!("debug actions are assigned only to debug keywords"),
1193 })
1194 }
1195
1196 fn required_clause_expression(
1198 &mut self,
1199 level: u8,
1200 keyword: &TokenTree,
1201 ) -> Result<Expr, NativeParseError> {
1202 match self.parse_nullable(level)? {
1203 None => Err(NativeParseError::MissingOperand {
1204 operator: keyword.description(),
1205 span: keyword.expect_span(),
1206 }),
1207 Some(expression) => Ok(expression),
1208 }
1209 }
1210
1211 fn consume_symbol(&mut self, expected: &'static str) -> Result<Symbol, NativeParseError> {
1213 match self.consume() {
1214 Lookahead::Token(token)
1215 if matches!(token.token, TokenTree::Ident(_))
1216 && matches!(parse_info(&token.token).unary, UnaryAction::Atom) =>
1217 {
1218 let span = token.token.expect_span();
1219 let text = token.token.description();
1220 Ok(typed_terminal(
1221 Symbol::new(text, span),
1222 token.trailing_trivia,
1223 ))
1224 }
1225 Lookahead::Token(token) => Err(unexpected!(token.token, expected)),
1226 Lookahead::End(span) => Err(NativeParseError::unexpected_end(expected, span)),
1227 }
1228 }
1229
1230 fn consume_exact(
1232 &mut self,
1233 spelling: &'static str,
1234 ) -> Result<SignificantToken, NativeParseError> {
1235 match self.consume() {
1236 Lookahead::Token(token) if parsing_spelling(&token.token) == spelling => Ok(token),
1237 Lookahead::Token(token) => Err(unexpected!(token.token, spelling)),
1238 Lookahead::End(span) => Err(NativeParseError::unexpected_end(spelling, span)),
1239 }
1240 }
1241
1242 fn take_exact(&mut self, spelling: &'static str) -> Option<SignificantToken> {
1244 if matches!(
1245 self.peek(),
1246 Lookahead::Token(token)
1247 if parsing_spelling(&token.token) == spelling
1248 ) {
1249 let Lookahead::Token(token) = self.consume() else {
1250 unreachable!("the token just peeked is consumable")
1251 };
1252 Some(token)
1253 } else {
1254 None
1255 }
1256 }
1257
1258 fn expected_at_lookahead(&self, expected: &'static str) -> NativeParseError {
1260 match self.peek() {
1261 Lookahead::Token(token) => unexpected!(token.token, expected),
1262 Lookahead::End(span) => NativeParseError::unexpected_end(expected, span),
1263 }
1264 }
1265
1266 fn accumulate(&mut self, mut left: Expr, level: u8) -> Result<Expr, NativeParseError> {
1268 loop {
1269 let Lookahead::Token(next) = self.peek() else {
1270 return Ok(left);
1271 };
1272 let info = if matches!(&next.token, TokenTree::Punct(punct) if punct.text().is_empty())
1273 {
1274 self.adjacency_info()
1275 } else {
1276 parse_info(&next.token)
1277 };
1278 if info.precedence <= level {
1279 return Ok(left);
1280 }
1281 let Lookahead::Token(operator) = self.consume() else {
1282 unreachable!("the token just peeked is consumable")
1283 };
1284 left = if matches!(&operator.token, TokenTree::Punct(punct) if punct.text().is_empty())
1285 {
1286 let right = self
1287 .parse_required(PREC_APPLICATION_RIGHT)
1288 .map_err(|error| error.missing_operand_for(&operator.token))?;
1289 let adjacency = typed_terminal(
1290 Adj::new("", operator.token.expect_span()),
1291 operator.trailing_trivia,
1292 );
1293 Expr!(Op::Bin::Adj {
1294 left_operand: Box::new(left),
1295 operator: adjacency,
1296 right_operand: Box::new(right),
1297 })
1298 } else if let Some(strength) = info.binary_strength {
1299 let left = BinaryLeft::prepare(left, &operator.token)?;
1300 let right = self
1301 .parse_required(strength)
1302 .map_err(|error| error.missing_operand_for(&operator.token))?;
1303 lower_binary(left, operator, right)?
1304 } else if info.postfix {
1305 let span = operator.token.expect_span();
1306 let spelling = operator.token.description();
1307 let operator = PostfixOperator::from_token_tree_with_trivia(
1308 operator.token,
1309 operator.trailing_trivia,
1310 )
1311 .ok_or(NativeParseError::Unsupported {
1312 syntax: spelling,
1313 span,
1314 })?;
1315 Expr!(Op::Postfix {
1316 operand: Box::new(left),
1317 operator,
1318 })
1319 } else if !matches!(info.unary, UnaryAction::Error) {
1320 if operator.crossed_newline {
1321 return Err(NativeParseError::NewlineInApplication {
1322 span: operator.token.expect_span(),
1323 });
1324 }
1325 let adjacency_span = operator.token.expect_span().subspan(0, 0);
1326 let right = self.parse_consumed(operator, PREC_APPLICATION_RIGHT)?;
1327 Expr!(Op::Bin::Adj {
1328 left_operand: Box::new(left),
1329 operator: Adj::new("", adjacency_span),
1330 right_operand: Box::new(right),
1331 })
1332 } else {
1333 return Err(unexpected!(operator.token, "an operator"));
1334 };
1335 }
1336 }
1337
1338 fn adjacency_info(&self) -> ParseInfo {
1340 let mut input = self.input.fork();
1341 let _ = input.next_significant();
1342 input.next_significant().map_or_else(
1343 || ParseInfo::stop(PREC_APPLICATION),
1344 |right| ParseInfo::binary(parse_info(&right.token).precedence, PREC_APPLICATION_RIGHT),
1345 )
1346 }
1347
1348 fn only_expression(&self, components: Components<Component>) -> Result<Expr, NativeParseError> {
1350 if components.is_punctuated() {
1351 return Err(NativeParseError::Unexpected {
1352 found: "a sequence".into(),
1353 expected: "one expression",
1354 span: components.first.expect_span(),
1355 });
1356 }
1357 match components.first {
1358 Component::Expr(value) => Ok(*value),
1359 value => Err(NativeParseError::Unexpected {
1360 found: "an empty component".into(),
1361 expected: "one expression",
1362 span: value.expect_span(),
1363 }),
1364 }
1365 }
1366
1367 fn packed_content(
1369 &self,
1370 components: Components<Component>,
1371 ) -> Result<PackedContent, NativeParseError> {
1372 match components.into_punctuated() {
1373 Ok(components) => Ok(ExprPack::new(components).into()),
1374 Err(Component::Expr(expression)) => Ok((*expression).into()),
1375 Err(value) => Err(NativeParseError::Unexpected {
1376 found: "an empty component".into(),
1377 expected: "one expression",
1378 span: value.expect_span(),
1379 }),
1380 }
1381 }
1382
1383 fn peek(&self) -> Lookahead {
1385 self.input.lookahead()
1386 }
1387
1388 fn consume(&mut self) -> Lookahead {
1390 self.input.consume_lookahead()
1391 }
1392
1393 fn skip_trivia(&mut self) {
1395 self.input.skip_trivia();
1396 }
1397
1398 fn at_end(&self) -> bool {
1400 matches!(self.peek(), Lookahead::End(_))
1401 }
1402
1403 fn at_punctuation(&self, spelling: &str) -> bool {
1405 matches!(
1406 self.peek(),
1407 Lookahead::Token(token)
1408 if token.token.spelling() == Some(spelling)
1409 )
1410 }
1411
1412 fn take_punctuation(&mut self, spelling: &str) -> Option<SignificantToken> {
1414 if !self.at_punctuation(spelling) {
1415 return None;
1416 }
1417 let Lookahead::Token(token) = self.consume() else {
1418 unreachable!("the punctuation just peeked is consumable")
1419 };
1420 Some(token)
1421 }
1422}
1423
1424fn parse_delimited(token: SignificantToken) -> Result<Expr, NativeParseError> {
1426 let group_trailing = token.trailing_trivia;
1427 let group = match token.token {
1428 TokenTree::Group(group) => group,
1429 token => return Err(unexpected!(token, "a delimited group")),
1430 };
1431 let kind = group.delim_kind();
1432 let delimiter_spans = group.delimiter().spans.clone();
1433 let mut group_contents = group.into_stream();
1434 let opening_trivia = group_contents.take_leading_trivia();
1435 let mut contents = Engine::new(group_contents);
1436 let mut muted = Vec::new();
1437 let elements = loop {
1438 let elements = contents.parse_optional_components()?;
1439 let Some(separator) = contents.take_punctuation(";") else {
1440 break elements;
1441 };
1442 let Some(elements) = elements else {
1443 return Err(unexpected!(separator.token, "a statement before `;`"));
1444 };
1445 muted.push(Statement::new(
1446 contents.packed_content(elements)?,
1447 typed_token(separator),
1448 ));
1449 };
1450 if let Lookahead::Token(token) = contents.peek() {
1451 return Err(unexpected!(token.token, "the end of the group"));
1452 }
1453
1454 let expression: Expr = match kind {
1455 DelimiterKind::Bracket => {
1456 let elements = elements
1457 .map(|elements| contents.packed_content(elements))
1458 .transpose()?;
1459 let mut value = Array::new(muted, elements);
1460 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1461 value.into()
1462 }
1463 DelimiterKind::Brace => {
1464 let elements = elements
1465 .map(|elements| contents.packed_content(elements))
1466 .transpose()?;
1467 let mut value = List::new(muted, elements);
1468 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1469 value.into()
1470 }
1471 DelimiterKind::AngleBar => {
1472 let elements = elements
1473 .map(|elements| contents.packed_content(elements))
1474 .transpose()?;
1475 let mut value = AngleBarList::new(muted, elements);
1476 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1477 value.into()
1478 }
1479 DelimiterKind::Parenthesis if muted.is_empty() && elements.is_none() => {
1480 let mut value = Sequence::new(Vec::new(), None);
1481 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1482 value.into()
1483 }
1484 DelimiterKind::Parenthesis
1485 if !muted.is_empty() || elements.as_ref().is_some_and(Components::is_punctuated) =>
1486 {
1487 let mut value = if elements.as_ref().is_some_and(Components::is_punctuated) {
1488 Sequence::new(
1489 muted,
1490 elements
1491 .map(|elements| contents.packed_content(elements))
1492 .transpose()?,
1493 )
1494 } else {
1495 let value = elements
1496 .map(|elements| contents.only_expression(elements))
1497 .transpose()?;
1498 let mut value = Holder::new(muted, value.map(Box::new));
1499 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1500 return Ok(value.into());
1501 };
1502 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1503 value.into()
1504 }
1505 DelimiterKind::Parenthesis => {
1506 let value = elements
1507 .map(|elements| contents.only_expression(elements))
1508 .transpose()?;
1509 let mut value = Holder::new(Vec::new(), value.map(Box::new));
1510 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1511 value.into()
1512 }
1513 };
1514 Ok(expression)
1515}
1516
1517fn typed_delimiter<D: DelimiterToken>(
1519 spans: crate::DoubleSpan,
1520 opening_trivia: TrailingTrivia,
1521 closing_trivia: TrailingTrivia,
1522) -> D {
1523 let mut delimiter = D::new(spans);
1524 *delimiter.opening_trivia_mut() = opening_trivia;
1525 *delimiter.closing_trivia_mut() = closing_trivia;
1526 delimiter
1527}
1528
1529fn lower_prefix_statement(keyword: SignificantToken, value: Option<Expr>) -> Expr {
1531 if is_token!(&keyword.token, break) {
1532 Expr!(Control::Break {
1533 break_token: typed_token(keyword),
1534 value: value.map(Box::new),
1535 })
1536 } else if is_token!(&keyword.token, continue) {
1537 Expr!(Control::Continue {
1538 continue_token: typed_token(keyword),
1539 value: value.map(Box::new),
1540 })
1541 } else if is_token!(&keyword.token, return) {
1542 Expr!(Control::Return {
1543 return_token: typed_token(keyword),
1544 value: value.map(Box::new),
1545 })
1546 } else {
1547 let value = value.expect("catch, throw, and trap require a value");
1548 if is_token!(&keyword.token, catch) {
1549 Expr!(Catch {
1550 catch_token: typed_token(keyword),
1551 value: Box::new(value),
1552 })
1553 } else if is_token!(&keyword.token, throw) {
1554 Expr!(Throw {
1555 throw_token: typed_token(keyword),
1556 value: Box::new(value),
1557 })
1558 } else if is_token!(&keyword.token, trap) {
1559 Expr!(Trap {
1560 trap_token: typed_token(keyword),
1561 value: Box::new(value),
1562 })
1563 } else {
1564 unreachable!("statement actions are assigned only to statement keywords")
1565 }
1566 }
1567}
1568
1569fn lower_atom(token: SignificantToken) -> Result<Expr, NativeParseError> {
1571 match token.token {
1572 TokenTree::Ident(raw) => Ok(typed_terminal(
1573 Symbol::new(raw.text(), raw.expect_span()),
1574 token.trailing_trivia,
1575 )
1576 .into()),
1577 TokenTree::Literal(raw) => {
1578 let span = raw.expect_span();
1579 Ok(match raw.kind {
1580 LiteralKind::Integer => {
1581 typed_terminal(IntegerLiteral::new(raw.text(), span), token.trailing_trivia)
1582 .into()
1583 }
1584 LiteralKind::Float => {
1585 typed_terminal(FloatLiteral::new(raw.text(), span), token.trailing_trivia)
1586 .into()
1587 }
1588 LiteralKind::String => {
1589 lower_string_literal(raw.text(), span, token.trailing_trivia)
1590 }
1591 LiteralKind::RawString => {
1592 lower_raw_string_literal(raw.text(), span, token.trailing_trivia)
1593 }
1594 })
1595 }
1596 token => Err(unexpected!(token, "an expression")),
1597 }
1598}
1599
1600enum BinaryLeft {
1602 Expression(Box<Expr>),
1604 Assignment {
1606 target: AssignmentTarget,
1608 local: bool,
1610 },
1611 Lambda(LambdaArguments),
1613}
1614
1615pub(crate) enum LambdaArguments {
1617 Variadic(Symbol),
1619 List(Box<Delimited<Option<ArgumentListContent>>>),
1621}
1622
1623impl BinaryLeft {
1624 fn prepare(left: Expr, operator: &TokenTree) -> Result<Self, NativeParseError> {
1626 let span = operator.expect_span();
1627 Ok(match operator.spelling() {
1628 Some("=") => Self::Assignment {
1629 target: AssignmentTarget::parse(left, false, span)?,
1630 local: false,
1631 },
1632 Some(":=") => Self::Assignment {
1633 target: AssignmentTarget::parse(left, true, span)?,
1634 local: true,
1635 },
1636 Some("->") => Self::Lambda(
1637 lambda_arguments(left).ok_or(NativeParseError::InvalidLambdaArguments { span })?,
1638 ),
1639 _ => Self::Expression(Box::new(left)),
1640 })
1641 }
1642}
1643
1644enum AssignmentTarget {
1646 Symbol(Symbol),
1648 Operator(ExprOp),
1650 New(ExprNew),
1652 List(Box<AssignmentList>),
1654}
1655
1656impl AssignmentTarget {
1657 fn parse(expression: Expr, local: bool, span: Span) -> Result<Self, NativeParseError> {
1659 match expression {
1660 Expr::Symbol(variable) => Ok(Self::Symbol(variable)),
1661 Expr::Op(expression) => Ok(Self::Operator(expression)),
1662 Expr::New(statement) if local => Ok(Self::New(statement)),
1663 expression => assignment_list(expression)
1664 .map(Box::new)
1665 .map(Self::List)
1666 .ok_or(NativeParseError::InvalidAssignmentTarget { span }),
1667 }
1668 }
1669}
1670
1671fn lower_binary(
1673 left: BinaryLeft,
1674 operator: SignificantToken,
1675 right: Expr,
1676) -> Result<Expr, NativeParseError> {
1677 let span = operator.token.expect_span();
1678 let spelling = operator
1679 .token
1680 .spelling()
1681 .expect("binary actions are assigned only to spelled tokens");
1682 match left {
1683 BinaryLeft::Assignment { target, local } => {
1684 Ok(lower_assignment(target, operator, right, local))
1685 }
1686 BinaryLeft::Lambda(arguments) => Ok(match arguments {
1687 LambdaArguments::Variadic(argument) => Expr!(Lambda::Variadic {
1688 argument,
1689 operator: typed_token(operator),
1690 body: Box::new(right),
1691 }),
1692 LambdaArguments::List(arguments) => Expr!(Lambda::List {
1693 arguments: *arguments,
1694 operator: typed_token(operator),
1695 body: Box::new(right),
1696 }),
1697 }),
1698 BinaryLeft::Expression(left) if spelling == "<-" => Ok(Expr!(Assign::Evaluated {
1699 evaluated_domain: left,
1700 operator: typed_token(operator),
1701 value: Box::new(right),
1702 })),
1703 BinaryLeft::Expression(left) if spelling == "=>" => Ok(Expr!(Option {
1704 key: left,
1705 operator: typed_token(operator),
1706 value: Box::new(right),
1707 })),
1708 BinaryLeft::Expression(left)
1709 if GENERATED_AUGMENTED_OPERATOR_SPELLINGS.contains(&spelling) =>
1710 {
1711 let operator = AugmentedOperator::from_token_tree_with_trivia(
1712 operator.token,
1713 operator.trailing_trivia,
1714 )
1715 .expect("the augmented operator table and category have the same source");
1716 Ok(Expr!(Assign::Augmented {
1717 target: left,
1718 operator,
1719 value: Box::new(right),
1720 }))
1721 }
1722 BinaryLeft::Expression(left) if matches!(spelling, "." | ".?") => Ok(match spelling {
1723 "." => Expr!(Op::Bin::Member::Dot {
1724 receiver: left,
1725 operator: typed_token::<Token![.]>(operator),
1726 member: Box::new(right),
1727 }),
1728 ".?" => Expr!(Op::Bin::Member::Optional {
1729 receiver: left,
1730 operator: typed_token::<Token![.?]>(operator),
1731 member: Box::new(right),
1732 }),
1733 _ => unreachable!(),
1734 }),
1735 BinaryLeft::Expression(left) if spelling == "#" => Ok(Expr!(Op::Bin::Index {
1736 receiver: left,
1737 operator: typed_token(operator),
1738 index: Box::new(right),
1739 })),
1740 BinaryLeft::Expression(left) => {
1741 let spelling = spelling.to_owned();
1742 let operator = BinaryOperator::from_token_tree_with_trivia(
1743 operator.token,
1744 operator.trailing_trivia,
1745 )
1746 .ok_or(NativeParseError::Unsupported {
1747 syntax: spelling,
1748 span,
1749 })?;
1750 Ok(Expr!(Op::Bin::Regular {
1751 left_operand: left,
1752 operator,
1753 right_operand: Box::new(right),
1754 }))
1755 }
1756 }
1757}
1758
1759fn lower_assignment(
1761 target: AssignmentTarget,
1762 operator: SignificantToken,
1763 right: Expr,
1764 local: bool,
1765) -> Expr {
1766 match (local, target) {
1767 (false, AssignmentTarget::Symbol(variable)) => {
1768 Expr!(Assign::Simple::Global {
1769 variable,
1770 operator: typed_token(operator),
1771 value: Box::new(right),
1772 })
1773 }
1774 (true, AssignmentTarget::Symbol(variable)) => {
1775 Expr!(Assign::Simple::Local {
1776 variable,
1777 operator: typed_token(operator),
1778 value: Box::new(right),
1779 })
1780 }
1781 (false, AssignmentTarget::Operator(argument_expr)) => {
1782 Expr!(Assign::Op {
1783 argument_expr,
1784 operator: typed_token(operator),
1785 value_expr: Box::new(right),
1786 })
1787 }
1788 (true, AssignmentTarget::Operator(ExprOp::Bin(ExprOpBin::Adj(application)))) => {
1789 let (typical_value, function) = installation_value(right);
1790 Expr!(Assign::Install::Method {
1791 method: application.left_operand,
1792 operator: application.operator,
1793 signature: application.right_operand,
1794 assign_op: typed_token(operator),
1795 typical_value,
1796 function: Box::new(function),
1797 })
1798 }
1799 (true, AssignmentTarget::Operator(domain_expr)) => {
1800 let (typical_value, function) = installation_value(right);
1801 Expr!(Assign::Install::Op {
1802 domain_expr,
1803 assign_op: typed_token(operator),
1804 typical_value,
1805 function: Box::new(function),
1806 })
1807 }
1808 (true, AssignmentTarget::New(new_statement)) => {
1809 Expr!(Assign::Install::New {
1810 new_statement,
1811 operator: typed_token(operator),
1812 function: Box::new(right),
1813 })
1814 }
1815 (local, AssignmentTarget::List(argument_list)) => {
1816 if local {
1817 Expr!(Assign::Parallel::Local {
1818 argument_list,
1819 operator: typed_token(operator),
1820 value: Box::new(right),
1821 })
1822 } else {
1823 Expr!(Assign::Parallel::Global {
1824 argument_list,
1825 operator: typed_token(operator),
1826 value: Box::new(right),
1827 })
1828 }
1829 }
1830 (false, AssignmentTarget::New(_)) => {
1831 unreachable!("global assignment preparation rejects new statements")
1832 }
1833 }
1834}
1835
1836pub(crate) fn installation_value(value: Expr) -> (Option<TypeAnnotation>, Expr) {
1838 match value {
1839 Expr::Option(value) => (
1840 Some(TypeAnnotation::new(value.key, value.operator)),
1841 *value.value,
1842 ),
1843 value => (None, value),
1844 }
1845}
1846
1847fn parse_cell_stream(cells: CellStream) -> Result<SourceFile, NativeParseError> {
1849 let mut elements = Vec::new();
1850 let bof_span = cells.physical_bof();
1851 let eof_span = cells.physical_eof();
1852 let mut detached = Vec::new();
1855 let mut cells = cells.into_iter().peekable();
1856 while let Some(cell) = cells.next() {
1857 if cell.is_empty() {
1858 detached.extend(CommentTrivia::of(&cell.into_parser_token_stream()).into_trivia());
1859 continue;
1860 }
1861 let eoc = cells
1862 .peek()
1863 .and_then(cell_start_span)
1864 .unwrap_or_else(|| end_span(&cell));
1865 if let Some(element) = parse_raw_cell_at(cell, eoc, std::mem::take(&mut detached))? {
1866 elements.push(element);
1867 }
1868 }
1869 let mut source_file = SourceFile::new(BOF::new("", bof_span), elements, EOF::new("", eof_span));
1870 source_file.set_closing_comments(detached);
1871 Ok(source_file)
1872}
1873
1874fn tokenize_for_native_parser(tokens: TokenStream) -> Result<CellStream, NativeParseError> {
1876 match tokens.to_cell_stream() {
1877 Ok(cells) => Ok(cells),
1878 Err(tokenize_error) => {
1879 let incomplete = frame_recovering(tokens).incomplete;
1880 if let Some(cell) = incomplete
1881 && let Err(parse_error) = parse_raw_cell(cell)
1882 {
1883 return Err(parse_error);
1884 }
1885 Err(NativeParseError::Tokenize(tokenize_error))
1886 }
1887 }
1888}
1889
1890pub(crate) fn parse_raw_cell(
1892 tokens: CellTokenStream,
1893) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1894 let eoc = end_span(&tokens);
1895 parse_raw_cell_at(tokens, eoc, Vec::new())
1896}
1897
1898fn parse_raw_cell_at(
1903 tokens: CellTokenStream,
1904 eoc: Span,
1905 mut detached: Vec<Trivia>,
1906) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1907 let ends_with_semicolon = ends_with_cell_semicolon(&tokens);
1908 let mut tokens = tokens.into_parser_token_stream();
1909 detached.extend(tokens.take_prefix_trivia().into_vec());
1910 let semicolon = ends_with_semicolon
1911 .then(|| tokens.take_final_punctuation(";"))
1912 .flatten()
1913 .map(|(punctuation, trailing_trivia)| {
1914 <Token![;] as Token>::from_token_tree_with_trivia(
1915 TokenTree::Punct(punctuation),
1916 trailing_trivia,
1917 )
1918 .expect("a semicolon punctuation token lowers to Token![;]")
1919 });
1920 let mut cell = Engine::new(tokens).parse_cell(semicolon, eoc)?;
1921 if let Some(cell) = &mut cell {
1922 cell.leading_trivia = LeadingTrivia::new(detached);
1923 }
1924 Ok(cell)
1925}
1926
1927fn cell_start_span(tokens: &CellTokenStream) -> Option<Span> {
1929 let token = tokens.iter().next()?;
1930 let span = token
1931 .leading_trivia()
1932 .first()
1933 .map_or_else(|| token.span(), Spanned::span);
1934 span.start().map(|start| span.at(start))
1935}
1936
1937impl Parse for Expr {
1938 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1939 let tokens = input.by_ref().collect::<TokenStream>();
1940 let mut engine = Engine::new(tokens);
1941 engine.skip_trivia();
1942 let value = engine
1943 .parse_required(PREC_CLOSER)
1944 .map_err(token_parse_error)?;
1945 engine.skip_trivia();
1946 match engine.peek() {
1947 Lookahead::End(_) => Ok(value),
1948 Lookahead::Token(token) => Err(TokenParseError::TrailingToken {
1949 found: token.token.description(),
1950 span: token.token.expect_span(),
1951 }),
1952 }
1953 }
1954}
1955
1956impl Parse for SourceFile {
1957 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1958 let tokens = input.by_ref().collect();
1959 tokenize_for_native_parser(tokens)
1960 .and_then(parse_cell_stream)
1961 .map_err(token_parse_error)
1962 }
1963}
1964
1965fn token_parse_error(error: NativeParseError) -> TokenParseError {
1967 let span = error.expect_span();
1968 TokenParseError::Syntax {
1969 message: error.to_string(),
1970 span,
1971 }
1972}
1973
1974fn parsing_spelling(token: &TokenTree) -> &str {
1976 token.spelling().map_or("", canonical_word_spelling)
1977}
1978
1979fn typed_token<T: Token>(token: SignificantToken) -> T {
1981 let spelling = token.token.description();
1982 T::from_token_tree_with_trivia(token.token, token.trailing_trivia)
1983 .unwrap_or_else(|| panic!("`{spelling}` cannot be lowered to `{}`", T::SPELLING))
1984}
1985
1986fn typed_terminal<T: Terminal>(mut terminal: T, trailing_trivia: TrailingTrivia) -> T {
1988 *terminal.trailing_trivia_mut() = trailing_trivia;
1989 terminal
1990}
1991
1992fn empty_span_at(lookahead: &Span) -> Span {
1994 lookahead.subspan(0, 0)
1995}
1996
1997fn lower_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
1999 let body_end = if text.len() > 1 && text.ends_with('"') {
2000 text.len() - 1
2001 } else {
2002 text.len()
2003 };
2004 let body = &text[1..body_end];
2005 let mut elements = Vec::new();
2006 let mut content_start = 0;
2007 let mut cursor = 0;
2008
2009 while cursor < body.len() {
2010 if body.as_bytes()[cursor] != b'\\' {
2011 cursor += 1;
2012 continue;
2013 }
2014 if content_start < cursor {
2015 elements.push(StringElement::Content(StringContent::new(
2016 &body[content_start..cursor],
2017 span.subspan(content_start + 1, cursor + 1),
2018 )));
2019 }
2020 let escape_end = match body.as_bytes()[cursor + 1] {
2021 b'x' => cursor + 4,
2022 b'u' => cursor + 6,
2023 b'0'..=b'7' => {
2024 let mut end = cursor + 2;
2025 while end < body.len()
2026 && end < cursor + 4
2027 && body.as_bytes()[end].is_ascii_digit()
2028 && body.as_bytes()[end] < b'8'
2029 {
2030 end += 1;
2031 }
2032 end
2033 }
2034 _ => cursor + 2,
2035 };
2036 elements.push(StringElement::Escape(EscapeSequence::new(
2037 &body[cursor..escape_end],
2038 span.subspan(cursor + 1, escape_end + 1),
2039 )));
2040 cursor = escape_end;
2041 content_start = cursor;
2042 }
2043 if content_start < body.len() {
2044 elements.push(StringElement::Content(StringContent::new(
2045 &body[content_start..],
2046 span.subspan(content_start + 1, body_end),
2047 )));
2048 }
2049 typed_terminal(StringLiteral::new(elements, span), trailing_trivia).into()
2050}
2051
2052fn lower_raw_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
2054 let body_end = if text.len() >= 6 && text.ends_with("///") {
2055 text.len() - 3
2056 } else {
2057 text.len()
2058 };
2059 let body = &text[3..body_end];
2060 let mut elements = Vec::new();
2061 let mut content_start = 0;
2062 let mut cursor = 0;
2063
2064 while cursor + 1 < body.len() {
2065 if &body.as_bytes()[cursor..cursor + 2] != b"//" {
2066 cursor += 1;
2067 continue;
2068 }
2069 if content_start < cursor {
2070 elements.push(RawStringElement::Content(RawStringContent::new(
2071 &body[content_start..cursor],
2072 span.subspan(content_start + 3, cursor + 3),
2073 )));
2074 }
2075 elements.push(RawStringElement::Escape(EscapeSequence::new(
2076 "//",
2077 span.subspan(cursor + 3, cursor + 5),
2078 )));
2079 cursor += 2;
2080 content_start = cursor;
2081 }
2082 if content_start < body.len() {
2083 elements.push(RawStringElement::Content(RawStringContent::new(
2084 &body[content_start..],
2085 span.subspan(content_start + 3, body_end),
2086 )));
2087 }
2088 typed_terminal(RawStringLiteral::new(elements, span), trailing_trivia).into()
2089}
2090
2091fn collection_contents(expression: Expr) -> Option<(crate::Delimiter, Option<PackedContent>)> {
2093 match expression {
2094 Expr::Collection(ExprCollection::Sequence(value)) if value.statements.is_empty() => {
2095 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2096 }
2097 Expr::Collection(ExprCollection::List(value)) if value.statements.is_empty() => {
2098 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2099 }
2100 Expr::Collection(ExprCollection::Array(value)) if value.statements.is_empty() => {
2101 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2102 }
2103 Expr::Collection(ExprCollection::AngleBar(value)) if value.statements.is_empty() => {
2104 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2105 }
2106 Expr::Holder(value) if value.muted.is_empty() => {
2107 let elements = value.value.map(|value| (*value).into());
2108 Some((DelimiterValue::delimiter(&value.delimiter), elements))
2109 }
2110 _ => None,
2111 }
2112}
2113
2114pub(crate) fn assignment_list(expression: Expr) -> Option<AssignmentList> {
2116 let (delimiter, elements) = collection_contents(expression)?;
2117 let contents = match elements {
2118 Some(elements) => {
2119 let components = packed_components(elements).map(assignment_argument)?;
2120 Some(match components.into_punctuated() {
2121 Ok(arguments) => AssignmentListContent!(Pack { arguments }),
2122 Err(argument) => argument.into(),
2123 })
2124 }
2125 None => None,
2126 };
2127 Some(AssignmentList::new(Delimited::new(delimiter, contents)))
2128}
2129
2130fn assignment_argument(component: Component) -> Option<AssignmentArgument> {
2132 match component {
2133 Component::Empty(value) => Some(AssignmentArgument::Empty(value)),
2134 Component::Expr(value) => match *value {
2135 Expr::Symbol(value) => Some(AssignmentArgument::Symbol(value)),
2136 Expr::Op(value) => Some(AssignmentArgument::Op(value)),
2137 Expr::Assign(ExprAssign::Evaluated(value)) => {
2138 Some(AssignmentArgument::Evaluated(value))
2139 }
2140 value => assignment_list(value).map(Into::into),
2141 },
2142 }
2143}
2144
2145fn expr_pack_symbols(elements: ExprPack) -> Option<Punctuated<Symbol>> {
2147 elements
2148 .pack
2149 .try_map(
2150 |component| match component {
2151 Component::Expr(value) => match *value {
2152 Expr::Symbol(value) => Ok(value),
2153 _ => Err(()),
2154 },
2155 Component::Empty(_) => Err(()),
2156 },
2157 Ok,
2158 )
2159 .ok()
2160}
2161
2162fn packed_components(content: PackedContent) -> Components<Component> {
2164 match content {
2165 PackedContent::Expr(expression) => Components {
2166 first: Component::Expr(expression),
2167 rest: Vec::new(),
2168 },
2169 PackedContent::Pack(pack) => Components::from_punctuated(pack.pack),
2170 }
2171}
2172
2173pub(crate) fn lambda_arguments(expression: Expr) -> Option<LambdaArguments> {
2175 match expression {
2176 Expr::Symbol(value) => Some(LambdaArguments::Variadic(value)),
2177 expression => {
2178 let (delimiter, elements) = collection_contents(expression)?;
2179 let arguments = match elements {
2180 Some(PackedContent::Expr(expression)) => match *expression {
2181 Expr::Symbol(value) => Some(ArgumentListContent::Symbol(value)),
2182 _ => return None,
2183 },
2184 Some(PackedContent::Pack(pack)) => Some(ArgumentListContent!(Pack {
2185 arguments: expr_pack_symbols(pack)?,
2186 })),
2187 None => None,
2188 };
2189 Some(LambdaArguments::List(Box::new(Delimited::new(
2190 delimiter, arguments,
2191 ))))
2192 }
2193 }
2194}
2195
2196fn token_parse_rule(spelling: &str) -> Option<TokenParseRule> {
2198 TOKEN_PARSE_RULES
2199 .binary_search_by_key(&spelling, |(declared, _)| *declared)
2200 .ok()
2201 .map(|index| TOKEN_PARSE_RULES[index].1)
2202}
2203
2204fn keyword_action(spelling: &str) -> Option<UnaryAction> {
2206 Some(match spelling {
2207 "break" | "continue" | "return" | "catch" | "throw" | "trap" => UnaryAction::Statement,
2208 "if" | "while" | "try" | "for" | "new" => UnaryAction::Control,
2209 "TEST" | "time" | "timing" | "elapsedTime" | "elapsedTiming" | "breakpoint" | "profile"
2210 | "shield" | "step" | "finish" => UnaryAction::Debug,
2211 "symbol" | "global" | "local" | "threadLocal" | "threadVariable" => UnaryAction::Quote,
2212 _ => return None,
2213 })
2214}
2215
2216fn parse_info(token: &TokenTree) -> ParseInfo {
2218 if matches!(token, TokenTree::Punct(punctuation) if punctuation.text().is_empty()) {
2219 return ParseInfo::binary(PREC_APPLICATION, PREC_APPLICATION_RIGHT);
2220 }
2221 if let TokenTree::Group(group) = token {
2222 return match group.delim_kind() {
2223 DelimiterKind::Bracket | DelimiterKind::AngleBar => {
2224 ParseInfo::delimiter(PREC_COLLECTION)
2225 }
2226 DelimiterKind::Parenthesis | DelimiterKind::Brace => {
2227 ParseInfo::delimiter(PREC_APPLICATION)
2228 }
2229 };
2230 }
2231
2232 let text = parsing_spelling(token);
2233 if let Some(rule) = token_parse_rule(text) {
2234 let mut info = ParseInfo::from(rule);
2235 if let Some(action) = keyword_action(text) {
2236 info.unary = action;
2237 }
2238 return info;
2239 }
2240
2241 match token {
2242 TokenTree::Ident(_) | TokenTree::Literal(_) => ParseInfo::atom(PREC_APPLICATION),
2243 _ => ParseInfo::stop(PREC_APPLICATION),
2244 }
2245}
2246
2247#[cfg(test)]
2248mod tests {
2249 use super::{NativeCellParser, NativeCellState};
2250 use crate::cell_stream::frame_recovering;
2251 use crate::{Spanned, lex_str};
2252
2253 #[test]
2257 fn cells_use_operator_clause_and_delimiter_state() {
2258 fn cells(source: &str) -> usize {
2259 let framed = frame_recovering(lex_str(source).unwrap());
2260 framed.cells.len() + usize::from(framed.incomplete.is_some())
2261 }
2262
2263 assert_eq!(cells("1\n2"), 2);
2264 assert_eq!(cells("1 +\n2"), 1);
2265 assert_eq!(cells("not\n1"), 1);
2266 assert_eq!(cells("1!\n2"), 2);
2267 assert_eq!(cells("if condition\nthen value"), 1);
2268 assert_eq!(cells("if condition\nthen value\nnext"), 2);
2269 assert_eq!(cells("symbol if\nnext"), 2);
2270 assert_eq!(cells("symbol +\nnext"), 2);
2271 assert_eq!(cells("1 -* comment\n*- 2"), 2);
2272 assert_eq!(cells("1 + -* comment\n*- 2"), 1);
2273 assert_eq!(cells("1;2"), 2);
2274 assert_eq!(cells("(1\n2;3)"), 1);
2277 assert_eq!(cells("symbol ;"), 1);
2279 }
2280
2281 #[test]
2282 fn invalid_binary_left_side_wins_over_a_missing_right_operand() {
2283 for (source, state, diagnostic, diagnostic_text) in [
2284 (
2285 "1 + 1 =",
2286 NativeCellState::Incomplete,
2287 "expected an operand after `=`, found end of input",
2288 "=",
2289 ),
2290 (
2291 "2 =",
2292 NativeCellState::Invalid,
2293 "invalid assignment target",
2294 "=",
2295 ),
2296 (
2297 "(x, y) ->",
2298 NativeCellState::Incomplete,
2299 "expected an operand after `->`, found end of input",
2300 "->",
2301 ),
2302 (
2303 "(x + y) ->",
2304 NativeCellState::Invalid,
2305 "invalid lambda argument list",
2306 "->",
2307 ),
2308 ] {
2309 let mut parser = NativeCellParser::new();
2310 assert_eq!(parser.push_line(source), state, "source: `{source}`");
2311 let error = parser
2312 .parse_error()
2313 .unwrap_or_else(|| panic!("expected a diagnostic for `{source}`"));
2314 assert_eq!(error.to_string(), diagnostic, "source: `{source}`");
2315 assert_eq!(error.span().text(), Some(diagnostic_text));
2316 }
2317 }
2318}