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, LexError, LexErrorKind, LiteralKind, Parse, ParseStream,
18 Parser, Punctuated, Recovered, Span, Spanned, Terminal, Token, TokenParseError, TokenStream,
19 TokenTree, Tokenize, TrailingTrivia, 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
1480 if !muted.is_empty() || elements.as_ref().is_some_and(Components::is_punctuated) =>
1481 {
1482 let mut value = if elements.as_ref().is_some_and(Components::is_punctuated) {
1483 Sequence::new(
1484 muted,
1485 elements
1486 .map(|elements| contents.packed_content(elements))
1487 .transpose()?,
1488 )
1489 } else {
1490 let value = elements
1491 .map(|elements| contents.only_expression(elements))
1492 .transpose()?;
1493 let mut value = Holder::new(muted, value.map(Box::new));
1494 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1495 return Ok(value.into());
1496 };
1497 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1498 value.into()
1499 }
1500 DelimiterKind::Parenthesis => {
1501 let value = elements
1502 .map(|elements| contents.only_expression(elements))
1503 .transpose()?;
1504 let mut value = Holder::new(Vec::new(), value.map(Box::new));
1505 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1506 value.into()
1507 }
1508 };
1509 Ok(expression)
1510}
1511
1512fn typed_delimiter<D: DelimiterToken>(
1514 spans: crate::DoubleSpan,
1515 opening_trivia: TrailingTrivia,
1516 closing_trivia: TrailingTrivia,
1517) -> D {
1518 let mut delimiter = D::new(spans);
1519 *delimiter.opening_trivia_mut() = opening_trivia;
1520 *delimiter.closing_trivia_mut() = closing_trivia;
1521 delimiter
1522}
1523
1524fn lower_prefix_statement(keyword: SignificantToken, value: Option<Expr>) -> Expr {
1526 if is_token!(&keyword.token, break) {
1527 Expr!(Control::Break {
1528 break_token: typed_token(keyword),
1529 value: value.map(Box::new),
1530 })
1531 } else if is_token!(&keyword.token, continue) {
1532 Expr!(Control::Continue {
1533 continue_token: typed_token(keyword),
1534 value: value.map(Box::new),
1535 })
1536 } else if is_token!(&keyword.token, return) {
1537 Expr!(Control::Return {
1538 return_token: typed_token(keyword),
1539 value: value.map(Box::new),
1540 })
1541 } else {
1542 let value = value.expect("catch, throw, and trap require a value");
1543 if is_token!(&keyword.token, catch) {
1544 Expr!(Catch {
1545 catch_token: typed_token(keyword),
1546 value: Box::new(value),
1547 })
1548 } else if is_token!(&keyword.token, throw) {
1549 Expr!(Throw {
1550 throw_token: typed_token(keyword),
1551 value: Box::new(value),
1552 })
1553 } else if is_token!(&keyword.token, trap) {
1554 Expr!(Trap {
1555 trap_token: typed_token(keyword),
1556 value: Box::new(value),
1557 })
1558 } else {
1559 unreachable!("statement actions are assigned only to statement keywords")
1560 }
1561 }
1562}
1563
1564fn lower_atom(token: SignificantToken) -> Result<Expr, NativeParseError> {
1566 match token.token {
1567 TokenTree::Ident(raw) => Ok(typed_terminal(
1568 Symbol::new(raw.text(), raw.expect_span()),
1569 token.trailing_trivia,
1570 )
1571 .into()),
1572 TokenTree::Literal(raw) => {
1573 let span = raw.expect_span();
1574 Ok(match raw.kind {
1575 LiteralKind::Integer => {
1576 typed_terminal(IntegerLiteral::new(raw.text(), span), token.trailing_trivia)
1577 .into()
1578 }
1579 LiteralKind::Float => {
1580 typed_terminal(FloatLiteral::new(raw.text(), span), token.trailing_trivia)
1581 .into()
1582 }
1583 LiteralKind::String => {
1584 lower_string_literal(raw.text(), span, token.trailing_trivia)
1585 }
1586 LiteralKind::RawString => {
1587 lower_raw_string_literal(raw.text(), span, token.trailing_trivia)
1588 }
1589 })
1590 }
1591 token => Err(unexpected!(token, "an expression")),
1592 }
1593}
1594
1595enum BinaryLeft {
1597 Expression(Box<Expr>),
1599 Assignment {
1601 target: AssignmentTarget,
1603 local: bool,
1605 },
1606 Lambda(LambdaArguments),
1608}
1609
1610pub(crate) enum LambdaArguments {
1612 Variadic(Symbol),
1614 List(Box<Delimited<Option<ArgumentListContent>>>),
1616}
1617
1618impl BinaryLeft {
1619 fn prepare(left: Expr, operator: &TokenTree) -> Result<Self, NativeParseError> {
1621 let span = operator.expect_span();
1622 Ok(match operator.spelling() {
1623 Some("=") => Self::Assignment {
1624 target: AssignmentTarget::parse(left, false, span)?,
1625 local: false,
1626 },
1627 Some(":=") => Self::Assignment {
1628 target: AssignmentTarget::parse(left, true, span)?,
1629 local: true,
1630 },
1631 Some("->") => Self::Lambda(
1632 lambda_arguments(left).ok_or(NativeParseError::InvalidLambdaArguments { span })?,
1633 ),
1634 _ => Self::Expression(Box::new(left)),
1635 })
1636 }
1637}
1638
1639enum AssignmentTarget {
1641 Symbol(Symbol),
1643 Operator(ExprOp),
1645 New(ExprNew),
1647 List(Box<AssignmentList>),
1649}
1650
1651impl AssignmentTarget {
1652 fn parse(expression: Expr, local: bool, span: Span) -> Result<Self, NativeParseError> {
1654 match expression {
1655 Expr::Symbol(variable) => Ok(Self::Symbol(variable)),
1656 Expr::Op(expression) => Ok(Self::Operator(expression)),
1657 Expr::New(statement) if local => Ok(Self::New(statement)),
1658 expression => assignment_list(expression)
1659 .map(Box::new)
1660 .map(Self::List)
1661 .ok_or(NativeParseError::InvalidAssignmentTarget { span }),
1662 }
1663 }
1664}
1665
1666fn lower_binary(
1668 left: BinaryLeft,
1669 operator: SignificantToken,
1670 right: Expr,
1671) -> Result<Expr, NativeParseError> {
1672 let span = operator.token.expect_span();
1673 let spelling = operator
1674 .token
1675 .spelling()
1676 .expect("binary actions are assigned only to spelled tokens");
1677 match left {
1678 BinaryLeft::Assignment { target, local } => {
1679 Ok(lower_assignment(target, operator, right, local))
1680 }
1681 BinaryLeft::Lambda(arguments) => Ok(match arguments {
1682 LambdaArguments::Variadic(argument) => Expr!(Lambda::Variadic {
1683 argument,
1684 operator: typed_token(operator),
1685 body: Box::new(right),
1686 }),
1687 LambdaArguments::List(arguments) => Expr!(Lambda::List {
1688 arguments: *arguments,
1689 operator: typed_token(operator),
1690 body: Box::new(right),
1691 }),
1692 }),
1693 BinaryLeft::Expression(left) if spelling == "<-" => Ok(Expr!(Assign::Evaluated {
1694 evaluated_domain: left,
1695 operator: typed_token(operator),
1696 value: Box::new(right),
1697 })),
1698 BinaryLeft::Expression(left) if spelling == "=>" => Ok(Expr!(Option {
1699 key: left,
1700 operator: typed_token(operator),
1701 value: Box::new(right),
1702 })),
1703 BinaryLeft::Expression(left)
1704 if GENERATED_AUGMENTED_OPERATOR_SPELLINGS.contains(&spelling) =>
1705 {
1706 let operator = AugmentedOperator::from_token_tree_with_trivia(
1707 operator.token,
1708 operator.trailing_trivia,
1709 )
1710 .expect("the augmented operator table and category have the same source");
1711 Ok(Expr!(Assign::Augmented {
1712 target: left,
1713 operator,
1714 value: Box::new(right),
1715 }))
1716 }
1717 BinaryLeft::Expression(left) if matches!(spelling, "." | ".?") => Ok(match spelling {
1718 "." => Expr!(Op::Bin::Member::Dot {
1719 receiver: left,
1720 operator: typed_token::<Token![.]>(operator),
1721 member: Box::new(right),
1722 }),
1723 ".?" => Expr!(Op::Bin::Member::Optional {
1724 receiver: left,
1725 operator: typed_token::<Token![.?]>(operator),
1726 member: Box::new(right),
1727 }),
1728 _ => unreachable!(),
1729 }),
1730 BinaryLeft::Expression(left) if spelling == "#" => Ok(Expr!(Op::Bin::Index {
1731 receiver: left,
1732 operator: typed_token(operator),
1733 index: Box::new(right),
1734 })),
1735 BinaryLeft::Expression(left) => {
1736 let spelling = spelling.to_owned();
1737 let operator = BinaryOperator::from_token_tree_with_trivia(
1738 operator.token,
1739 operator.trailing_trivia,
1740 )
1741 .ok_or(NativeParseError::Unsupported {
1742 syntax: spelling,
1743 span,
1744 })?;
1745 Ok(Expr!(Op::Bin::Regular {
1746 left_operand: left,
1747 operator,
1748 right_operand: Box::new(right),
1749 }))
1750 }
1751 }
1752}
1753
1754fn lower_assignment(
1756 target: AssignmentTarget,
1757 operator: SignificantToken,
1758 right: Expr,
1759 local: bool,
1760) -> Expr {
1761 match (local, target) {
1762 (false, AssignmentTarget::Symbol(variable)) => {
1763 Expr!(Assign::Simple::Global {
1764 variable,
1765 operator: typed_token(operator),
1766 value: Box::new(right),
1767 })
1768 }
1769 (true, AssignmentTarget::Symbol(variable)) => {
1770 Expr!(Assign::Simple::Local {
1771 variable,
1772 operator: typed_token(operator),
1773 value: Box::new(right),
1774 })
1775 }
1776 (false, AssignmentTarget::Operator(argument_expr)) => {
1777 Expr!(Assign::Op {
1778 argument_expr,
1779 operator: typed_token(operator),
1780 value_expr: Box::new(right),
1781 })
1782 }
1783 (true, AssignmentTarget::Operator(ExprOp::Bin(ExprOpBin::Adj(application)))) => {
1784 let (typical_value, function) = installation_value(right);
1785 Expr!(Assign::Install::Method {
1786 method: application.left_operand,
1787 operator: application.operator,
1788 signature: application.right_operand,
1789 assign_op: typed_token(operator),
1790 typical_value,
1791 function: Box::new(function),
1792 })
1793 }
1794 (true, AssignmentTarget::Operator(domain_expr)) => {
1795 let (typical_value, function) = installation_value(right);
1796 Expr!(Assign::Install::Op {
1797 domain_expr,
1798 assign_op: typed_token(operator),
1799 typical_value,
1800 function: Box::new(function),
1801 })
1802 }
1803 (true, AssignmentTarget::New(new_statement)) => {
1804 Expr!(Assign::Install::New {
1805 new_statement,
1806 operator: typed_token(operator),
1807 function: Box::new(right),
1808 })
1809 }
1810 (local, AssignmentTarget::List(argument_list)) => {
1811 if local {
1812 Expr!(Assign::Parallel::Local {
1813 argument_list,
1814 operator: typed_token(operator),
1815 value: Box::new(right),
1816 })
1817 } else {
1818 Expr!(Assign::Parallel::Global {
1819 argument_list,
1820 operator: typed_token(operator),
1821 value: Box::new(right),
1822 })
1823 }
1824 }
1825 (false, AssignmentTarget::New(_)) => {
1826 unreachable!("global assignment preparation rejects new statements")
1827 }
1828 }
1829}
1830
1831pub(crate) fn installation_value(value: Expr) -> (Option<TypeAnnotation>, Expr) {
1833 match value {
1834 Expr::Option(value) => (
1835 Some(TypeAnnotation::new(value.key, value.operator)),
1836 *value.value,
1837 ),
1838 value => (None, value),
1839 }
1840}
1841
1842fn parse_cell_stream(cells: CellStream) -> Result<SourceFile, NativeParseError> {
1844 let mut elements = Vec::new();
1845 let eof_span = cells.physical_eof();
1846 let mut comments = CommentTrivia::default();
1847 let mut cells = cells.into_iter().peekable();
1848 while let Some(cell) = cells.next() {
1849 if cell.is_empty() {
1850 comments.append(CommentTrivia::take_inner(
1851 &mut cell.into_parser_token_stream(),
1852 ));
1853 continue;
1854 }
1855 let eoc = cells
1856 .peek()
1857 .and_then(cell_start_span)
1858 .unwrap_or_else(|| end_span(&cell));
1859 if let Some(element) = parse_raw_cell_at(cell, eoc)? {
1860 elements.push(element);
1861 }
1862 }
1863 let mut source_file = SourceFile::new(elements, EOF::new("", eof_span));
1864 source_file.comments = comments;
1865 Ok(source_file)
1866}
1867
1868fn tokenize_for_native_parser(tokens: TokenStream) -> Result<CellStream, NativeParseError> {
1870 match tokens.to_cell_stream() {
1871 Ok(cells) => Ok(cells),
1872 Err(tokenize_error) => {
1873 let incomplete = frame_recovering(tokens).incomplete;
1874 if let Some(cell) = incomplete
1875 && let Err(parse_error) = parse_raw_cell(cell)
1876 {
1877 return Err(parse_error);
1878 }
1879 Err(NativeParseError::Tokenize(tokenize_error))
1880 }
1881 }
1882}
1883
1884pub(crate) fn parse_raw_cell(
1886 tokens: CellTokenStream,
1887) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1888 let eoc = end_span(&tokens);
1889 parse_raw_cell_at(tokens, eoc)
1890}
1891
1892fn parse_raw_cell_at(
1894 tokens: CellTokenStream,
1895 eoc: Span,
1896) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1897 let ends_with_semicolon = ends_with_cell_semicolon(&tokens);
1898 let mut tokens = tokens.into_parser_token_stream();
1899 let comments = CommentTrivia::take_from_cell(&mut tokens);
1900 let semicolon = ends_with_semicolon
1901 .then(|| tokens.take_final_punctuation(";"))
1902 .flatten()
1903 .map(|(punctuation, trailing_trivia)| {
1904 <Token![;] as Token>::from_token_tree_with_trivia(
1905 TokenTree::Punct(punctuation),
1906 trailing_trivia,
1907 )
1908 .expect("a semicolon punctuation token lowers to Token![;]")
1909 });
1910 let mut cell = Engine::new(tokens).parse_cell(semicolon, eoc)?;
1911 if let Some(cell) = &mut cell {
1912 cell.comments = comments;
1913 }
1914 Ok(cell)
1915}
1916
1917fn cell_start_span(tokens: &CellTokenStream) -> Option<Span> {
1919 let token = tokens.iter().next()?;
1920 let span = token
1921 .leading_trivia()
1922 .first()
1923 .map_or_else(|| token.span(), Spanned::span);
1924 span.start().map(|start| span.at(start))
1925}
1926
1927impl Parse for Expr {
1928 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1929 let tokens = input.by_ref().collect::<TokenStream>();
1930 let mut engine = Engine::new(tokens);
1931 engine.skip_trivia();
1932 let value = engine
1933 .parse_required(PREC_CLOSER)
1934 .map_err(token_parse_error)?;
1935 engine.skip_trivia();
1936 match engine.peek() {
1937 Lookahead::End(_) => Ok(value),
1938 Lookahead::Token(token) => Err(TokenParseError::TrailingToken {
1939 found: token.token.description(),
1940 span: token.token.expect_span(),
1941 }),
1942 }
1943 }
1944}
1945
1946impl Parse for SourceFile {
1947 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1948 let tokens = input.by_ref().collect();
1949 tokenize_for_native_parser(tokens)
1950 .and_then(parse_cell_stream)
1951 .map_err(token_parse_error)
1952 }
1953}
1954
1955fn token_parse_error(error: NativeParseError) -> TokenParseError {
1957 let span = error.expect_span();
1958 TokenParseError::Syntax {
1959 message: error.to_string(),
1960 span,
1961 }
1962}
1963
1964fn parsing_spelling(token: &TokenTree) -> &str {
1966 token.spelling().map_or("", canonical_word_spelling)
1967}
1968
1969fn typed_token<T: Token>(token: SignificantToken) -> T {
1971 let spelling = token.token.description();
1972 T::from_token_tree_with_trivia(token.token, token.trailing_trivia)
1973 .unwrap_or_else(|| panic!("`{spelling}` cannot be lowered to `{}`", T::SPELLING))
1974}
1975
1976fn typed_terminal<T: Terminal>(mut terminal: T, trailing_trivia: TrailingTrivia) -> T {
1978 *terminal.trailing_trivia_mut() = trailing_trivia;
1979 terminal
1980}
1981
1982fn empty_span_at(lookahead: &Span) -> Span {
1984 lookahead.subspan(0, 0)
1985}
1986
1987fn lower_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
1989 let body = &text[1..text.len() - 1];
1990 let mut elements = Vec::new();
1991 let mut content_start = 0;
1992 let mut cursor = 0;
1993
1994 while cursor < body.len() {
1995 if body.as_bytes()[cursor] != b'\\' {
1996 cursor += 1;
1997 continue;
1998 }
1999 if content_start < cursor {
2000 elements.push(StringElement::Content(StringContent::new(
2001 &body[content_start..cursor],
2002 span.subspan(content_start + 1, cursor + 1),
2003 )));
2004 }
2005 let escape_end = match body.as_bytes()[cursor + 1] {
2006 b'x' => cursor + 4,
2007 b'u' => cursor + 6,
2008 b'0'..=b'7' => {
2009 let mut end = cursor + 2;
2010 while end < body.len()
2011 && end < cursor + 4
2012 && body.as_bytes()[end].is_ascii_digit()
2013 && body.as_bytes()[end] < b'8'
2014 {
2015 end += 1;
2016 }
2017 end
2018 }
2019 _ => cursor + 2,
2020 };
2021 elements.push(StringElement::Escape(EscapeSequence::new(
2022 &body[cursor..escape_end],
2023 span.subspan(cursor + 1, escape_end + 1),
2024 )));
2025 cursor = escape_end;
2026 content_start = cursor;
2027 }
2028 if content_start < body.len() {
2029 elements.push(StringElement::Content(StringContent::new(
2030 &body[content_start..],
2031 span.subspan(content_start + 1, text.len() - 1),
2032 )));
2033 }
2034 typed_terminal(StringLiteral::new(elements, span), trailing_trivia).into()
2035}
2036
2037fn lower_raw_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
2039 let body = &text[3..text.len() - 3];
2040 let mut elements = Vec::new();
2041 let mut content_start = 0;
2042 let mut cursor = 0;
2043
2044 while cursor + 1 < body.len() {
2045 if &body.as_bytes()[cursor..cursor + 2] != b"//" {
2046 cursor += 1;
2047 continue;
2048 }
2049 if content_start < cursor {
2050 elements.push(RawStringElement::Content(RawStringContent::new(
2051 &body[content_start..cursor],
2052 span.subspan(content_start + 3, cursor + 3),
2053 )));
2054 }
2055 elements.push(RawStringElement::Escape(EscapeSequence::new(
2056 "//",
2057 span.subspan(cursor + 3, cursor + 5),
2058 )));
2059 cursor += 2;
2060 content_start = cursor;
2061 }
2062 if content_start < body.len() {
2063 elements.push(RawStringElement::Content(RawStringContent::new(
2064 &body[content_start..],
2065 span.subspan(content_start + 3, text.len() - 3),
2066 )));
2067 }
2068 typed_terminal(RawStringLiteral::new(elements, span), trailing_trivia).into()
2069}
2070
2071fn collection_contents(expression: Expr) -> Option<(crate::Delimiter, Option<PackedContent>)> {
2073 match expression {
2074 Expr::Collection(ExprCollection::Sequence(value)) if value.statements.is_empty() => {
2075 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2076 }
2077 Expr::Collection(ExprCollection::List(value)) if value.statements.is_empty() => {
2078 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2079 }
2080 Expr::Collection(ExprCollection::Array(value)) if value.statements.is_empty() => {
2081 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2082 }
2083 Expr::Collection(ExprCollection::AngleBar(value)) if value.statements.is_empty() => {
2084 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2085 }
2086 Expr::Holder(value) if value.muted.is_empty() => {
2087 let elements = value.value.map(|value| (*value).into());
2088 Some((DelimiterValue::delimiter(&value.delimiter), elements))
2089 }
2090 _ => None,
2091 }
2092}
2093
2094pub(crate) fn assignment_list(expression: Expr) -> Option<AssignmentList> {
2096 let (delimiter, elements) = collection_contents(expression)?;
2097 let contents = match elements {
2098 Some(elements) => {
2099 let components = packed_components(elements).map(assignment_argument)?;
2100 Some(match components.into_punctuated() {
2101 Ok(arguments) => AssignmentListContent!(Pack { arguments }),
2102 Err(argument) => argument.into(),
2103 })
2104 }
2105 None => None,
2106 };
2107 Some(AssignmentList::new(Delimited::new(delimiter, contents)))
2108}
2109
2110fn assignment_argument(component: Component) -> Option<AssignmentArgument> {
2112 match component {
2113 Component::Empty(value) => Some(AssignmentArgument::Empty(value)),
2114 Component::Expr(value) => match *value {
2115 Expr::Symbol(value) => Some(AssignmentArgument::Symbol(value)),
2116 Expr::Op(value) => Some(AssignmentArgument::Op(value)),
2117 value => assignment_list(value).map(Into::into),
2118 },
2119 }
2120}
2121
2122fn expr_pack_symbols(elements: ExprPack) -> Option<Punctuated<Symbol>> {
2124 elements
2125 .pack
2126 .try_map(
2127 |component| match component {
2128 Component::Expr(value) => match *value {
2129 Expr::Symbol(value) => Ok(value),
2130 _ => Err(()),
2131 },
2132 Component::Empty(_) => Err(()),
2133 },
2134 Ok,
2135 )
2136 .ok()
2137}
2138
2139fn packed_components(content: PackedContent) -> Components<Component> {
2141 match content {
2142 PackedContent::Expr(expression) => Components {
2143 first: Component::Expr(expression),
2144 rest: Vec::new(),
2145 },
2146 PackedContent::Pack(pack) => Components::from_punctuated(pack.pack),
2147 }
2148}
2149
2150pub(crate) fn lambda_arguments(expression: Expr) -> Option<LambdaArguments> {
2152 match expression {
2153 Expr::Symbol(value) => Some(LambdaArguments::Variadic(value)),
2154 expression => {
2155 let (delimiter, elements) = collection_contents(expression)?;
2156 let arguments = match elements {
2157 Some(PackedContent::Expr(expression)) => match *expression {
2158 Expr::Symbol(value) => Some(ArgumentListContent::Symbol(value)),
2159 _ => return None,
2160 },
2161 Some(PackedContent::Pack(pack)) => Some(ArgumentListContent!(Pack {
2162 arguments: expr_pack_symbols(pack)?,
2163 })),
2164 None => None,
2165 };
2166 Some(LambdaArguments::List(Box::new(Delimited::new(
2167 delimiter, arguments,
2168 ))))
2169 }
2170 }
2171}
2172
2173fn token_parse_rule(spelling: &str) -> Option<TokenParseRule> {
2175 TOKEN_PARSE_RULES
2176 .binary_search_by_key(&spelling, |(declared, _)| *declared)
2177 .ok()
2178 .map(|index| TOKEN_PARSE_RULES[index].1)
2179}
2180
2181fn keyword_action(spelling: &str) -> Option<UnaryAction> {
2183 Some(match spelling {
2184 "break" | "continue" | "return" | "catch" | "throw" | "trap" => UnaryAction::Statement,
2185 "if" | "while" | "try" | "for" | "new" => UnaryAction::Control,
2186 "TEST" | "time" | "timing" | "elapsedTime" | "elapsedTiming" | "breakpoint" | "profile"
2187 | "shield" | "step" | "finish" => UnaryAction::Debug,
2188 "symbol" | "global" | "local" | "threadLocal" | "threadVariable" => UnaryAction::Quote,
2189 _ => return None,
2190 })
2191}
2192
2193fn parse_info(token: &TokenTree) -> ParseInfo {
2195 if matches!(token, TokenTree::Punct(punctuation) if punctuation.text().is_empty()) {
2196 return ParseInfo::binary(PREC_APPLICATION, PREC_APPLICATION_RIGHT);
2197 }
2198 if let TokenTree::Group(group) = token {
2199 return match group.delim_kind() {
2200 DelimiterKind::Bracket | DelimiterKind::AngleBar => {
2201 ParseInfo::delimiter(PREC_COLLECTION)
2202 }
2203 DelimiterKind::Parenthesis | DelimiterKind::Brace => {
2204 ParseInfo::delimiter(PREC_APPLICATION)
2205 }
2206 };
2207 }
2208
2209 let text = parsing_spelling(token);
2210 if let Some(rule) = token_parse_rule(text) {
2211 let mut info = ParseInfo::from(rule);
2212 if let Some(action) = keyword_action(text) {
2213 info.unary = action;
2214 }
2215 return info;
2216 }
2217
2218 match token {
2219 TokenTree::Ident(_) | TokenTree::Literal(_) => ParseInfo::atom(PREC_APPLICATION),
2220 _ => ParseInfo::stop(PREC_APPLICATION),
2221 }
2222}
2223
2224#[cfg(test)]
2225mod tests {
2226 use super::{NativeCellParser, NativeCellState};
2227 use crate::cell_stream::frame_recovering;
2228 use crate::{Spanned, lex_str};
2229
2230 #[test]
2234 fn cells_use_operator_clause_and_delimiter_state() {
2235 fn cells(source: &str) -> usize {
2236 let framed = frame_recovering(lex_str(source).unwrap());
2237 framed.cells.len() + usize::from(framed.incomplete.is_some())
2238 }
2239
2240 assert_eq!(cells("1\n2"), 2);
2241 assert_eq!(cells("1 +\n2"), 1);
2242 assert_eq!(cells("not\n1"), 1);
2243 assert_eq!(cells("1!\n2"), 2);
2244 assert_eq!(cells("if condition\nthen value"), 1);
2245 assert_eq!(cells("if condition\nthen value\nnext"), 2);
2246 assert_eq!(cells("symbol if\nnext"), 2);
2247 assert_eq!(cells("symbol +\nnext"), 2);
2248 assert_eq!(cells("1 -* comment\n*- 2"), 2);
2249 assert_eq!(cells("1 + -* comment\n*- 2"), 1);
2250 assert_eq!(cells("1;2"), 2);
2251 assert_eq!(cells("(1\n2;3)"), 1);
2254 assert_eq!(cells("symbol ;"), 1);
2256 }
2257
2258 #[test]
2259 fn invalid_binary_left_side_wins_over_a_missing_right_operand() {
2260 for (source, state, diagnostic, diagnostic_text) in [
2261 (
2262 "1 + 1 =",
2263 NativeCellState::Incomplete,
2264 "expected an operand after `=`, found end of input",
2265 "=",
2266 ),
2267 (
2268 "2 =",
2269 NativeCellState::Invalid,
2270 "invalid assignment target",
2271 "=",
2272 ),
2273 (
2274 "(x, y) ->",
2275 NativeCellState::Incomplete,
2276 "expected an operand after `->`, found end of input",
2277 "->",
2278 ),
2279 (
2280 "(x + y) ->",
2281 NativeCellState::Invalid,
2282 "invalid lambda argument list",
2283 "->",
2284 ),
2285 ] {
2286 let mut parser = NativeCellParser::new();
2287 assert_eq!(parser.push_line(source), state, "source: `{source}`");
2288 let error = parser
2289 .parse_error()
2290 .unwrap_or_else(|| panic!("expected a diagnostic for `{source}`"));
2291 assert_eq!(error.to_string(), diagnostic, "source: `{source}`");
2292 assert_eq!(error.span().text(), Some(diagnostic_text));
2293 }
2294 }
2295}