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 {
540 precedence: u8,
542 binary_strength: Option<u8>,
544 unary_strength: Option<u8>,
546 unary: UnaryAction,
548 postfix: bool,
550}
551
552impl From<TokenParseRule> for ParseInfo {
553 fn from(rule: TokenParseRule) -> Self {
554 match rule {
555 TokenParseRule::Precedence(precedence) => Self::stop(precedence),
556 TokenParseRule::Postfix(precedence) => Self::postfix(precedence),
557 TokenParseRule::Binary(precedence, strength) => Self::binary(precedence, strength),
558 TokenParseRule::Prefix(precedence, strength) => {
559 Self::unary(precedence, UnaryAction::Prefix, strength)
560 }
561 TokenParseRule::PrefixBinary(precedence, binary, unary) => {
562 Self::prefix_binary(precedence, binary, unary)
563 }
564 TokenParseRule::Unary(precedence, strength) => {
565 Self::unary(precedence, UnaryAction::Error, strength)
566 }
567 }
568 }
569}
570
571impl ParseInfo {
572 const fn atom(precedence: u8) -> Self {
574 Self {
575 precedence,
576 binary_strength: None,
577 unary_strength: None,
578 unary: UnaryAction::Atom,
579 postfix: false,
580 }
581 }
582
583 const fn binary(precedence: u8, strength: u8) -> Self {
585 Self {
586 precedence,
587 binary_strength: Some(strength),
588 unary_strength: None,
589 unary: UnaryAction::Error,
590 postfix: false,
591 }
592 }
593
594 const fn prefix_binary(precedence: u8, binary_strength: u8, unary_strength: u8) -> Self {
596 Self {
597 precedence,
598 binary_strength: Some(binary_strength),
599 unary_strength: Some(unary_strength),
600 unary: UnaryAction::Prefix,
601 postfix: false,
602 }
603 }
604
605 const fn unary(precedence: u8, unary: UnaryAction, strength: u8) -> Self {
609 Self {
610 precedence,
611 binary_strength: None,
612 unary_strength: Some(strength),
613 unary,
614 postfix: false,
615 }
616 }
617
618 const fn postfix(precedence: u8) -> Self {
620 Self {
621 precedence,
622 binary_strength: None,
623 unary_strength: None,
624 unary: UnaryAction::Error,
625 postfix: true,
626 }
627 }
628
629 const fn delimiter(precedence: u8) -> Self {
631 Self {
632 precedence,
633 binary_strength: None,
634 unary_strength: Some(PREC_CLOSER),
635 unary: UnaryAction::Delimiter,
636 postfix: false,
637 }
638 }
639
640 const fn stop(precedence: u8) -> Self {
642 Self {
643 precedence,
644 binary_strength: None,
645 unary_strength: None,
646 unary: UnaryAction::Error,
647 postfix: false,
648 }
649 }
650}
651
652struct Engine {
654 input: ParseStream,
656}
657
658struct Components<T> {
660 first: T,
662 rest: Vec<(Token![,], T)>,
664}
665
666impl<T> Components<T> {
667 fn from_punctuated(values: Punctuated<T>) -> Self {
669 let (pair, rest) = values.into_parts();
670 let (first, punctuation, second) = pair.into_parts();
671 let mut pairs = Vec::with_capacity(rest.len() + 1);
672 pairs.push((punctuation, second));
673 pairs.extend(rest);
674 Self { first, rest: pairs }
675 }
676
677 fn is_punctuated(&self) -> bool {
679 !self.rest.is_empty()
680 }
681
682 fn into_punctuated(self) -> Result<Punctuated<T>, T> {
684 let mut rest = self.rest.into_iter();
685 let Some((punctuation, second)) = rest.next() else {
686 return Err(self.first);
687 };
688 let mut values = Punctuated::new(self.first, punctuation, second);
689 for (punctuation, value) in rest {
690 values.push(punctuation, value);
691 }
692 Ok(values)
693 }
694
695 fn map<U>(self, mut map: impl FnMut(T) -> Option<U>) -> Option<Components<U>> {
697 Some(Components {
698 first: map(self.first)?,
699 rest: self
700 .rest
701 .into_iter()
702 .map(|(punctuation, value)| Some((punctuation, map(value)?)))
703 .collect::<Option<Vec<_>>>()?,
704 })
705 }
706}
707
708impl Engine {
709 fn new(tokens: TokenStream) -> Self {
711 Self {
712 input: ParseStream::new(tokens),
713 }
714 }
715
716 fn parse_cell(
718 mut self,
719 semicolon: Option<Token![;]>,
720 eoc_span: Span,
721 ) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
722 self.skip_trivia();
723 if matches!(self.peek(), Lookahead::End(_)) {
724 return match semicolon {
725 None => Ok(None),
726 Some(semicolon) => Err(NativeParseError::Unexpected {
727 found: ";".into(),
728 expected: "a statement before `;`",
729 span: semicolon.expect_span(),
730 }),
731 };
732 }
733
734 let components = self.parse_components()?;
735
736 if let Lookahead::Token(token) = self.peek() {
737 return Err(unexpected!(token.token, "the end of the cell"));
738 }
739
740 let eoc = EOC::new("", eoc_span);
741 Ok(Some(crate::nodes::Cell::new(
742 self.packed_content(components)?,
743 semicolon,
744 eoc,
745 )))
746 }
747
748 fn parse_components(&mut self) -> Result<Components<Component>, NativeParseError> {
750 let first = if self.at_punctuation(",") {
751 Component::Empty(Empty::new("", empty_span_at(&self.peek().expect_span())))
752 } else {
753 self.parse_required(PREC_COMMA)?.into()
754 };
755 let mut rest = Vec::new();
756
757 while let Some(comma) = self.take_punctuation(",") {
758 let next = if self.at_end() || self.at_punctuation(";") || self.at_punctuation(",") {
759 Component::Empty(Empty::new("", empty_span_at(&self.peek().expect_span())))
760 } else {
761 self.parse_required(PREC_COMMA)?.into()
762 };
763 rest.push((typed_token(comma), next));
764 }
765
766 Ok(Components { first, rest })
767 }
768
769 fn parse_optional_components(
771 &mut self,
772 ) -> Result<Option<Components<Component>>, NativeParseError> {
773 if self.at_end() || self.at_punctuation(";") {
774 Ok(None)
775 } else {
776 self.parse_components().map(Some)
777 }
778 }
779
780 fn parse_required(&mut self, level: u8) -> Result<Expr, NativeParseError> {
782 let token = match self.consume() {
783 Lookahead::Token(token) => token,
784 Lookahead::End(span) => {
785 return Err(NativeParseError::MissingOperand {
786 operator: "end of input".into(),
787 span,
788 });
789 }
790 };
791 self.parse_consumed(token, level)
792 }
793
794 fn parse_nullable(&mut self, level: u8) -> Result<Option<Expr>, NativeParseError> {
796 let lookahead = self.peek();
797 let Lookahead::Token(token) = lookahead else {
798 return Ok(None);
799 };
800 if parse_info(&token.token).precedence <= level {
801 return Ok(None);
802 }
803 let Lookahead::Token(token) = self.consume() else {
804 unreachable!("the token just peeked is consumable")
805 };
806 self.parse_consumed(token, level).map(Some)
807 }
808
809 fn parse_consumed(
811 &mut self,
812 token: SignificantToken,
813 level: u8,
814 ) -> Result<Expr, NativeParseError> {
815 let info = parse_info(&token.token);
816 let result = match info.unary {
817 UnaryAction::Atom => lower_atom(token)?,
818 UnaryAction::Prefix => {
819 let strength = info.unary_strength.expect("prefix operators have U");
820 let operand = self.parse_required(level.max(strength))?;
821 let span = token.token.expect_span();
822 let spelling = token.token.description();
823 let operator =
824 PrefixOperator::from_token_tree_with_trivia(token.token, token.trailing_trivia)
825 .ok_or({
826 NativeParseError::Unsupported {
827 syntax: spelling,
828 span,
829 }
830 })?;
831 Expr!(Op::Prefix {
832 operator,
833 operand: Box::new(operand),
834 })
835 }
836 UnaryAction::Statement => {
837 let strength = info
838 .unary_strength
839 .expect("prefix statements have a unary binding strength");
840 let operand = if is_token!(&token.token, break)
841 || is_token!(&token.token, continue)
842 || is_token!(&token.token, return)
843 {
844 self.parse_nullable(level.max(strength))?
845 } else {
846 self.parse_required(level.max(strength))
847 .map_err(|error| error.missing_operand_for(&token.token))?
848 .into()
849 };
850 lower_prefix_statement(token, operand)
851 }
852 UnaryAction::Control => {
853 if is_token!(&token.token, if) {
854 self.parse_if_statement(token)?
855 } else if is_token!(&token.token, for) {
856 self.parse_for_loop(token)?
857 } else if is_token!(&token.token, while) {
858 self.parse_while_loop(token)?
859 } else if is_token!(&token.token, try) {
860 self.parse_try_statement(token)?
861 } else if is_token!(&token.token, new) {
862 self.parse_new_statement(token)?
863 } else {
864 unreachable!("control actions are assigned only to control keywords")
865 }
866 }
867 UnaryAction::Debug => self.parse_debug_clause(token)?,
868 UnaryAction::Delimiter => parse_delimited(token)?,
869 UnaryAction::Quote => {
870 let operator = token.token.description();
871 let quoted = match self.consume() {
872 Lookahead::Token(quoted) => quoted,
873 Lookahead::End(span) => {
874 return Err(NativeParseError::MissingOperand { operator, span });
875 }
876 };
877 let quoted_span = quoted.token.expect_span();
878 let Some(quoted_text) = quoted.token.spelling().map(str::to_owned) else {
879 return Err(unexpected!(quoted.token, "a quoted token"));
880 };
881 let quoted = typed_terminal(
882 Symbol::new(quoted_text, quoted_span),
883 quoted.trailing_trivia,
884 );
885 if is_token!(&token.token, symbol) {
886 Expr!(Quote::Symbol {
887 specifier: typed_token(token),
888 symbol: quoted,
889 })
890 } else if is_token!(&token.token, local) {
891 Expr!(Quote::Local {
892 specifier: typed_token(token),
893 symbol: quoted,
894 })
895 } else if is_token!(&token.token, global) {
896 Expr!(Quote::Global {
897 specifier: typed_token(token),
898 symbol: quoted,
899 })
900 } else if is_token!(&token.token, threadVariable) {
901 Expr!(Quote::ThreadVariable {
902 specifier: typed_token(token),
903 symbol: quoted,
904 })
905 } else if is_token!(&token.token, threadLocal) {
906 Expr!(Quote::ThreadLocal {
907 specifier: typed_token(token),
908 symbol: quoted,
909 })
910 } else {
911 unreachable!("quote actions are assigned only to quote specifiers")
912 }
913 }
914 UnaryAction::Error => {
915 return Err(unexpected!(token.token, "an expression"));
916 }
917 };
918 self.accumulate(result, level)
919 }
920
921 fn parse_if_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
923 let condition = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
924 let then_keyword = self.consume_exact("then")?;
925 let then_value = self.required_clause_expression(PREC_CONTROL, &then_keyword.token)?;
926 let then_clause = ThenClause::new(typed_token(then_keyword), Box::new(then_value));
927 let else_clause = self
928 .take_exact("else")
929 .map(|else_keyword| {
930 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword.token)?;
931 Ok::<_, NativeParseError>(ElseClause::new(
932 typed_token(else_keyword),
933 Box::new(value),
934 ))
935 })
936 .transpose()?;
937 Ok(Expr!(If {
938 if_token: typed_token(keyword),
939 condition: Box::new(condition),
940 then_clause,
941 else_clause,
942 }))
943 }
944
945 fn parse_for_loop(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
947 let variable = self.consume_symbol("a loop variable")?;
948
949 enum Domain {
950 Bare,
952 Range(Option<RangeBoundFrom>, Option<RangeBoundTo>),
954 In(SignificantToken, Box<Expr>),
956 }
957 let domain = if let Some(token) = self.take_exact("in") {
958 let collection = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
959 Domain::In(token, Box::new(collection))
960 } else {
961 let lower_bound = self
962 .take_exact("from")
963 .map(|token| {
964 let value = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
965 Ok::<_, NativeParseError>(RangeBoundFrom::new(
966 typed_token(token),
967 Box::new(value),
968 ))
969 })
970 .transpose()?;
971 let upper_bound = self
972 .take_exact("to")
973 .map(|token| {
974 let value = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
975 Ok::<_, NativeParseError>(RangeBoundTo::new(
976 typed_token(token),
977 Box::new(value),
978 ))
979 })
980 .transpose()?;
981 if lower_bound.is_some() || upper_bound.is_some() {
982 Domain::Range(lower_bound, upper_bound)
983 } else {
984 Domain::Bare
985 }
986 };
987
988 let when_condition = if let Some(token) = self.take_exact("when") {
989 let condition = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
990 Some(WhenCondition::new(typed_token(token), Box::new(condition)))
991 } else {
992 None
993 };
994 let body = self.parse_loop_body()?;
995
996 Ok(match domain {
997 Domain::Bare => Expr!(For::Bare {
998 for_token: typed_token(keyword),
999 variable,
1000 condition: when_condition,
1001 body,
1002 }),
1003 Domain::Range(lower_bound, upper_bound) => Expr!(For::Range {
1004 for_token: typed_token(keyword),
1005 variable,
1006 lower_bound,
1007 upper_bound,
1008 condition: when_condition,
1009 body,
1010 }),
1011 Domain::In(token, collection) => Expr!(For::In {
1012 for_token: typed_token(keyword),
1013 variable,
1014 in_token: typed_token(token),
1015 collection,
1016 condition: when_condition,
1017 body,
1018 }),
1019 })
1020 }
1021
1022 fn parse_while_loop(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1024 let condition = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
1025 let body = self.parse_loop_body()?;
1026 Ok(Expr!(While {
1027 while_token: typed_token(keyword),
1028 condition: Box::new(condition),
1029 body,
1030 }))
1031 }
1032
1033 fn parse_loop_body(&mut self) -> Result<LoopBody, NativeParseError> {
1035 let (list_step, do_step) = if let Some(token) = self.take_exact("list") {
1036 let listed_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
1037 let list_step = Some(ListStep::new(typed_token(token), Box::new(listed_value)));
1038 if let Some(token) = self.take_exact("do") {
1039 let ignored_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
1040 (
1041 list_step,
1042 Some(DoStep::new(typed_token(token), Box::new(ignored_value))),
1043 )
1044 } else {
1045 (list_step, None)
1046 }
1047 } else if let Some(token) = self.take_exact("do") {
1048 let ignored_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
1049 (
1050 None,
1051 Some(DoStep::new(typed_token(token), Box::new(ignored_value))),
1052 )
1053 } else {
1054 return Err(self.expected_at_lookahead("`list` or `do`"));
1055 };
1056
1057 Ok(LoopBody::new(list_step, do_step))
1058 }
1059
1060 fn parse_try_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1062 let value = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
1063 let then_clause = self
1064 .take_exact("then")
1065 .map(|then_keyword| {
1066 let value = self.required_clause_expression(PREC_CONTROL, &then_keyword.token)?;
1067 Ok::<_, NativeParseError>(ThenClause::new(
1068 typed_token(then_keyword),
1069 Box::new(value),
1070 ))
1071 })
1072 .transpose()?;
1073
1074 let fallback = if let Some(else_keyword) = self.take_exact("else") {
1075 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword.token)?;
1076 Some(TryFallback::Else(ElseClause::new(
1077 typed_token(else_keyword),
1078 Box::new(value),
1079 )))
1080 } else if let Some(except_keyword) = self.take_exact("except") {
1081 let exception = self.consume_symbol("an exception symbol")?;
1082 let do_keyword = self.consume_exact("do")?;
1083 let value = self.required_clause_expression(PREC_CONTROL, &do_keyword.token)?;
1084 Some(TryFallback!(Except {
1085 except_token: typed_token(except_keyword),
1086 exception,
1087 do_token: typed_token(do_keyword),
1088 value: Box::new(value),
1089 }))
1090 } else {
1091 None
1092 };
1093
1094 Ok(Expr!(Try {
1095 try_token: typed_token(keyword),
1096 value: Box::new(value),
1097 on_success: then_clause,
1098 fallback,
1099 }))
1100 }
1101
1102 fn parse_new_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1104 let class = self.required_clause_expression(PREC_LOOP_CLAUSE, &keyword.token)?;
1105 let parent_class = if let Some(token) = self.take_exact("of") {
1106 let parent = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
1107 Some(OfClass::new(typed_token(token), Box::new(parent)))
1108 } else {
1109 None
1110 };
1111 let instance = if let Some(token) = self.take_exact("from") {
1112 let instance = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
1113 Some(FromInstance::new(typed_token(token), Box::new(instance)))
1114 } else {
1115 None
1116 };
1117
1118 Ok(Expr!(New {
1119 new_token: typed_token(keyword),
1120 class: Box::new(class),
1121 parent_class,
1122 instance,
1123 }))
1124 }
1125
1126 fn parse_debug_clause(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
1128 let spelling = parsing_spelling(&keyword.token).to_owned();
1129 if matches!(
1130 spelling.as_str(),
1131 "time" | "timing" | "elapsedTime" | "elapsedTiming" | "profile"
1132 ) {
1133 let value = self
1134 .parse_required(PREC_CONTROL)
1135 .map_err(|error| error.missing_operand_for(&keyword.token))?;
1136 return Ok(match spelling.as_str() {
1137 "time" => Expr!(Profile::Time {
1138 modifier: typed_token(keyword),
1139 value: Box::new(value),
1140 }),
1141 "timing" => Expr!(Profile::Timing {
1142 modifier: typed_token(keyword),
1143 value: Box::new(value),
1144 }),
1145 "elapsedTime" => Expr!(Profile::ElapsedTime {
1146 modifier: typed_token(keyword),
1147 value: Box::new(value),
1148 }),
1149 "elapsedTiming" => Expr!(Profile::ElapsedTiming {
1150 modifier: typed_token(keyword),
1151 value: Box::new(value),
1152 }),
1153 "profile" => Expr!(Profile::Profile {
1154 modifier: typed_token(keyword),
1155 value: Box::new(value),
1156 }),
1157 _ => unreachable!(),
1158 });
1159 }
1160 let value_is_optional = matches!(spelling.as_str(), "step" | "finish");
1161 let value = if value_is_optional {
1162 self.parse_nullable(PREC_CONTROL)?
1163 } else {
1164 Some(
1165 self.parse_required(PREC_CONTROL)
1166 .map_err(|error| error.missing_operand_for(&keyword.token))?,
1167 )
1168 };
1169 let value = value.map(Box::new);
1170 Ok(match spelling.as_str() {
1171 "step" => Expr!(Debug::Step {
1172 keyword: typed_token(keyword),
1173 value,
1174 }),
1175 "finish" => Expr!(Debug::Finish {
1176 keyword: typed_token(keyword),
1177 value,
1178 }),
1179 "shield" => Expr!(Debug::Shield {
1180 keyword: typed_token(keyword),
1181 value,
1182 }),
1183 "TEST" => Expr!(Debug::Test {
1184 keyword: typed_token(keyword),
1185 value,
1186 }),
1187 "breakpoint" => Expr!(Debug::Breakpoint {
1188 keyword: typed_token(keyword),
1189 value,
1190 }),
1191 _ => unreachable!("debug actions are assigned only to debug keywords"),
1192 })
1193 }
1194
1195 fn required_clause_expression(
1197 &mut self,
1198 level: u8,
1199 keyword: &TokenTree,
1200 ) -> Result<Expr, NativeParseError> {
1201 match self.parse_nullable(level)? {
1202 None => Err(NativeParseError::MissingOperand {
1203 operator: keyword.description(),
1204 span: keyword.expect_span(),
1205 }),
1206 Some(expression) => Ok(expression),
1207 }
1208 }
1209
1210 fn consume_symbol(&mut self, expected: &'static str) -> Result<Symbol, NativeParseError> {
1212 match self.consume() {
1213 Lookahead::Token(token)
1214 if matches!(token.token, TokenTree::Ident(_))
1215 && matches!(parse_info(&token.token).unary, UnaryAction::Atom) =>
1216 {
1217 let span = token.token.expect_span();
1218 let text = token.token.description();
1219 Ok(typed_terminal(
1220 Symbol::new(text, span),
1221 token.trailing_trivia,
1222 ))
1223 }
1224 Lookahead::Token(token) => Err(unexpected!(token.token, expected)),
1225 Lookahead::End(span) => Err(NativeParseError::unexpected_end(expected, span)),
1226 }
1227 }
1228
1229 fn consume_exact(
1231 &mut self,
1232 spelling: &'static str,
1233 ) -> Result<SignificantToken, NativeParseError> {
1234 match self.consume() {
1235 Lookahead::Token(token) if parsing_spelling(&token.token) == spelling => Ok(token),
1236 Lookahead::Token(token) => Err(unexpected!(token.token, spelling)),
1237 Lookahead::End(span) => Err(NativeParseError::unexpected_end(spelling, span)),
1238 }
1239 }
1240
1241 fn take_exact(&mut self, spelling: &'static str) -> Option<SignificantToken> {
1243 if matches!(
1244 self.peek(),
1245 Lookahead::Token(token)
1246 if parsing_spelling(&token.token) == spelling
1247 ) {
1248 let Lookahead::Token(token) = self.consume() else {
1249 unreachable!("the token just peeked is consumable")
1250 };
1251 Some(token)
1252 } else {
1253 None
1254 }
1255 }
1256
1257 fn expected_at_lookahead(&self, expected: &'static str) -> NativeParseError {
1259 match self.peek() {
1260 Lookahead::Token(token) => unexpected!(token.token, expected),
1261 Lookahead::End(span) => NativeParseError::unexpected_end(expected, span),
1262 }
1263 }
1264
1265 fn accumulate(&mut self, mut left: Expr, level: u8) -> Result<Expr, NativeParseError> {
1267 loop {
1268 let Lookahead::Token(next) = self.peek() else {
1269 return Ok(left);
1270 };
1271 let info = if matches!(&next.token, TokenTree::Punct(punct) if punct.text().is_empty())
1272 {
1273 self.adjacency_info()
1274 } else {
1275 parse_info(&next.token)
1276 };
1277 if info.precedence <= level {
1278 return Ok(left);
1279 }
1280 let Lookahead::Token(operator) = self.consume() else {
1281 unreachable!("the token just peeked is consumable")
1282 };
1283 left = if matches!(&operator.token, TokenTree::Punct(punct) if punct.text().is_empty())
1284 {
1285 let right = self
1286 .parse_required(PREC_APPLICATION_RIGHT)
1287 .map_err(|error| error.missing_operand_for(&operator.token))?;
1288 let adjacency = typed_terminal(
1289 Adj::new("", operator.token.expect_span()),
1290 operator.trailing_trivia,
1291 );
1292 Expr!(Op::Bin::Adj {
1293 left_operand: Box::new(left),
1294 operator: adjacency,
1295 right_operand: Box::new(right),
1296 })
1297 } else if let Some(strength) = info.binary_strength {
1298 let left = BinaryLeft::prepare(left, &operator.token)?;
1299 let right = self
1300 .parse_required(strength)
1301 .map_err(|error| error.missing_operand_for(&operator.token))?;
1302 lower_binary(left, operator, right)?
1303 } else if info.postfix {
1304 let span = operator.token.expect_span();
1305 let spelling = operator.token.description();
1306 let operator = PostfixOperator::from_token_tree_with_trivia(
1307 operator.token,
1308 operator.trailing_trivia,
1309 )
1310 .ok_or(NativeParseError::Unsupported {
1311 syntax: spelling,
1312 span,
1313 })?;
1314 Expr!(Op::Postfix {
1315 operand: Box::new(left),
1316 operator,
1317 })
1318 } else if !matches!(info.unary, UnaryAction::Error) {
1319 if operator.crossed_newline {
1320 return Err(NativeParseError::NewlineInApplication {
1321 span: operator.token.expect_span(),
1322 });
1323 }
1324 let adjacency_span = operator.token.expect_span().subspan(0, 0);
1325 let right = self.parse_consumed(operator, PREC_APPLICATION_RIGHT)?;
1326 Expr!(Op::Bin::Adj {
1327 left_operand: Box::new(left),
1328 operator: Adj::new("", adjacency_span),
1329 right_operand: Box::new(right),
1330 })
1331 } else {
1332 return Err(unexpected!(operator.token, "an operator"));
1333 };
1334 }
1335 }
1336
1337 fn adjacency_info(&self) -> ParseInfo {
1339 let mut input = self.input.fork();
1340 let _ = input.next_significant();
1341 input.next_significant().map_or_else(
1342 || ParseInfo::stop(PREC_APPLICATION),
1343 |right| ParseInfo::binary(parse_info(&right.token).precedence, PREC_APPLICATION_RIGHT),
1344 )
1345 }
1346
1347 fn only_expression(&self, components: Components<Component>) -> Result<Expr, NativeParseError> {
1349 if components.is_punctuated() {
1350 return Err(NativeParseError::Unexpected {
1351 found: "a sequence".into(),
1352 expected: "one expression",
1353 span: components.first.expect_span(),
1354 });
1355 }
1356 match components.first {
1357 Component::Expr(value) => Ok(*value),
1358 value => Err(NativeParseError::Unexpected {
1359 found: "an empty component".into(),
1360 expected: "one expression",
1361 span: value.expect_span(),
1362 }),
1363 }
1364 }
1365
1366 fn packed_content(
1368 &self,
1369 components: Components<Component>,
1370 ) -> Result<PackedContent, NativeParseError> {
1371 match components.into_punctuated() {
1372 Ok(components) => Ok(ExprPack::new(components).into()),
1373 Err(Component::Expr(expression)) => Ok((*expression).into()),
1374 Err(value) => Err(NativeParseError::Unexpected {
1375 found: "an empty component".into(),
1376 expected: "one expression",
1377 span: value.expect_span(),
1378 }),
1379 }
1380 }
1381
1382 fn peek(&self) -> Lookahead {
1384 self.input.lookahead()
1385 }
1386
1387 fn consume(&mut self) -> Lookahead {
1389 self.input.consume_lookahead()
1390 }
1391
1392 fn skip_trivia(&mut self) {
1394 self.input.skip_trivia();
1395 }
1396
1397 fn at_end(&self) -> bool {
1399 matches!(self.peek(), Lookahead::End(_))
1400 }
1401
1402 fn at_punctuation(&self, spelling: &str) -> bool {
1404 matches!(
1405 self.peek(),
1406 Lookahead::Token(token)
1407 if token.token.spelling() == Some(spelling)
1408 )
1409 }
1410
1411 fn take_punctuation(&mut self, spelling: &str) -> Option<SignificantToken> {
1413 if !self.at_punctuation(spelling) {
1414 return None;
1415 }
1416 let Lookahead::Token(token) = self.consume() else {
1417 unreachable!("the punctuation just peeked is consumable")
1418 };
1419 Some(token)
1420 }
1421}
1422
1423fn parse_delimited(token: SignificantToken) -> Result<Expr, NativeParseError> {
1425 let group_trailing = token.trailing_trivia;
1426 let group = match token.token {
1427 TokenTree::Group(group) => group,
1428 token => return Err(unexpected!(token, "a delimited group")),
1429 };
1430 let kind = group.delim_kind();
1431 let delimiter_spans = group.delimiter().spans.clone();
1432 let mut group_contents = group.into_stream();
1433 let opening_trivia = group_contents.take_leading_trivia();
1434 let mut contents = Engine::new(group_contents);
1435 let mut muted = Vec::new();
1436 let elements = loop {
1437 let elements = contents.parse_optional_components()?;
1438 let Some(separator) = contents.take_punctuation(";") else {
1439 break elements;
1440 };
1441 let Some(elements) = elements else {
1442 return Err(unexpected!(separator.token, "a statement before `;`"));
1443 };
1444 muted.push(Statement::new(
1445 contents.packed_content(elements)?,
1446 typed_token(separator),
1447 ));
1448 };
1449 if let Lookahead::Token(token) = contents.peek() {
1450 return Err(unexpected!(token.token, "the end of the group"));
1451 }
1452
1453 let expression: Expr = match kind {
1454 DelimiterKind::Bracket => {
1455 let elements = elements
1456 .map(|elements| contents.packed_content(elements))
1457 .transpose()?;
1458 let mut value = Array::new(muted, elements);
1459 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1460 value.into()
1461 }
1462 DelimiterKind::Brace => {
1463 let elements = elements
1464 .map(|elements| contents.packed_content(elements))
1465 .transpose()?;
1466 let mut value = List::new(muted, elements);
1467 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1468 value.into()
1469 }
1470 DelimiterKind::AngleBar => {
1471 let elements = elements
1472 .map(|elements| contents.packed_content(elements))
1473 .transpose()?;
1474 let mut value = AngleBarList::new(muted, elements);
1475 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1476 value.into()
1477 }
1478 DelimiterKind::Parenthesis
1479 if !muted.is_empty() || elements.as_ref().is_some_and(Components::is_punctuated) =>
1480 {
1481 let mut value = if elements.as_ref().is_some_and(Components::is_punctuated) {
1482 Sequence::new(
1483 muted,
1484 elements
1485 .map(|elements| contents.packed_content(elements))
1486 .transpose()?,
1487 )
1488 } else {
1489 let value = elements
1490 .map(|elements| contents.only_expression(elements))
1491 .transpose()?;
1492 let mut value = Holder::new(muted, value.map(Box::new));
1493 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1494 return Ok(value.into());
1495 };
1496 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1497 value.into()
1498 }
1499 DelimiterKind::Parenthesis => {
1500 let value = elements
1501 .map(|elements| contents.only_expression(elements))
1502 .transpose()?;
1503 let mut value = Holder::new(Vec::new(), value.map(Box::new));
1504 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1505 value.into()
1506 }
1507 };
1508 Ok(expression)
1509}
1510
1511fn typed_delimiter<D: DelimiterToken>(
1513 spans: crate::DoubleSpan,
1514 opening_trivia: TrailingTrivia,
1515 closing_trivia: TrailingTrivia,
1516) -> D {
1517 let mut delimiter = D::new(spans);
1518 *delimiter.opening_trivia_mut() = opening_trivia;
1519 *delimiter.closing_trivia_mut() = closing_trivia;
1520 delimiter
1521}
1522
1523fn lower_prefix_statement(keyword: SignificantToken, value: Option<Expr>) -> Expr {
1525 if is_token!(&keyword.token, break) {
1526 Expr!(Control::Break {
1527 break_token: typed_token(keyword),
1528 value: value.map(Box::new),
1529 })
1530 } else if is_token!(&keyword.token, continue) {
1531 Expr!(Control::Continue {
1532 continue_token: typed_token(keyword),
1533 value: value.map(Box::new),
1534 })
1535 } else if is_token!(&keyword.token, return) {
1536 Expr!(Control::Return {
1537 return_token: typed_token(keyword),
1538 value: value.map(Box::new),
1539 })
1540 } else {
1541 let value = value.expect("catch, throw, and trap require a value");
1542 if is_token!(&keyword.token, catch) {
1543 Expr!(Catch {
1544 catch_token: typed_token(keyword),
1545 value: Box::new(value),
1546 })
1547 } else if is_token!(&keyword.token, throw) {
1548 Expr!(Throw {
1549 throw_token: typed_token(keyword),
1550 value: Box::new(value),
1551 })
1552 } else if is_token!(&keyword.token, trap) {
1553 Expr!(Trap {
1554 trap_token: typed_token(keyword),
1555 value: Box::new(value),
1556 })
1557 } else {
1558 unreachable!("statement actions are assigned only to statement keywords")
1559 }
1560 }
1561}
1562
1563fn lower_atom(token: SignificantToken) -> Result<Expr, NativeParseError> {
1565 match token.token {
1566 TokenTree::Ident(raw) => Ok(typed_terminal(
1567 Symbol::new(raw.text(), raw.expect_span()),
1568 token.trailing_trivia,
1569 )
1570 .into()),
1571 TokenTree::Literal(raw) => {
1572 let span = raw.expect_span();
1573 Ok(match raw.kind {
1574 LiteralKind::Integer => {
1575 typed_terminal(IntegerLiteral::new(raw.text(), span), token.trailing_trivia)
1576 .into()
1577 }
1578 LiteralKind::Float => {
1579 typed_terminal(FloatLiteral::new(raw.text(), span), token.trailing_trivia)
1580 .into()
1581 }
1582 LiteralKind::String => {
1583 lower_string_literal(raw.text(), span, token.trailing_trivia)
1584 }
1585 LiteralKind::RawString => {
1586 lower_raw_string_literal(raw.text(), span, token.trailing_trivia)
1587 }
1588 })
1589 }
1590 token => Err(unexpected!(token, "an expression")),
1591 }
1592}
1593
1594enum BinaryLeft {
1596 Expression(Box<Expr>),
1598 Assignment {
1600 target: AssignmentTarget,
1602 local: bool,
1604 },
1605 Lambda(LambdaArguments),
1607}
1608
1609pub(crate) enum LambdaArguments {
1611 Variadic(Symbol),
1613 List(Box<Delimited<Option<ArgumentListContent>>>),
1615}
1616
1617impl BinaryLeft {
1618 fn prepare(left: Expr, operator: &TokenTree) -> Result<Self, NativeParseError> {
1620 let span = operator.expect_span();
1621 Ok(match operator.spelling() {
1622 Some("=") => Self::Assignment {
1623 target: AssignmentTarget::parse(left, false, span)?,
1624 local: false,
1625 },
1626 Some(":=") => Self::Assignment {
1627 target: AssignmentTarget::parse(left, true, span)?,
1628 local: true,
1629 },
1630 Some("->") => Self::Lambda(
1631 lambda_arguments(left).ok_or(NativeParseError::InvalidLambdaArguments { span })?,
1632 ),
1633 _ => Self::Expression(Box::new(left)),
1634 })
1635 }
1636}
1637
1638enum AssignmentTarget {
1640 Symbol(Symbol),
1642 Operator(ExprOp),
1644 New(ExprNew),
1646 List(Box<AssignmentList>),
1648}
1649
1650impl AssignmentTarget {
1651 fn parse(expression: Expr, local: bool, span: Span) -> Result<Self, NativeParseError> {
1653 match expression {
1654 Expr::Symbol(variable) => Ok(Self::Symbol(variable)),
1655 Expr::Op(expression) => Ok(Self::Operator(expression)),
1656 Expr::New(statement) if local => Ok(Self::New(statement)),
1657 expression => assignment_list(expression)
1658 .map(Box::new)
1659 .map(Self::List)
1660 .ok_or(NativeParseError::InvalidAssignmentTarget { span }),
1661 }
1662 }
1663}
1664
1665fn lower_binary(
1667 left: BinaryLeft,
1668 operator: SignificantToken,
1669 right: Expr,
1670) -> Result<Expr, NativeParseError> {
1671 let span = operator.token.expect_span();
1672 let spelling = operator
1673 .token
1674 .spelling()
1675 .expect("binary actions are assigned only to spelled tokens");
1676 match left {
1677 BinaryLeft::Assignment { target, local } => {
1678 Ok(lower_assignment(target, operator, right, local))
1679 }
1680 BinaryLeft::Lambda(arguments) => Ok(match arguments {
1681 LambdaArguments::Variadic(argument) => Expr!(Lambda::Variadic {
1682 argument,
1683 operator: typed_token(operator),
1684 body: Box::new(right),
1685 }),
1686 LambdaArguments::List(arguments) => Expr!(Lambda::List {
1687 arguments: *arguments,
1688 operator: typed_token(operator),
1689 body: Box::new(right),
1690 }),
1691 }),
1692 BinaryLeft::Expression(left) if spelling == "<-" => Ok(Expr!(Assign::Evaluated {
1693 evaluated_domain: left,
1694 operator: typed_token(operator),
1695 value: Box::new(right),
1696 })),
1697 BinaryLeft::Expression(left) if spelling == "=>" => Ok(Expr!(Option {
1698 key: left,
1699 operator: typed_token(operator),
1700 value: Box::new(right),
1701 })),
1702 BinaryLeft::Expression(left)
1703 if GENERATED_AUGMENTED_OPERATOR_SPELLINGS.contains(&spelling) =>
1704 {
1705 let operator = AugmentedOperator::from_token_tree_with_trivia(
1706 operator.token,
1707 operator.trailing_trivia,
1708 )
1709 .expect("the augmented operator table and category have the same source");
1710 Ok(Expr!(Assign::Augmented {
1711 target: left,
1712 operator,
1713 value: Box::new(right),
1714 }))
1715 }
1716 BinaryLeft::Expression(left) if matches!(spelling, "." | ".?") => Ok(match spelling {
1717 "." => Expr!(Op::Bin::Member::Dot {
1718 receiver: left,
1719 operator: typed_token::<Token![.]>(operator),
1720 member: Box::new(right),
1721 }),
1722 ".?" => Expr!(Op::Bin::Member::Optional {
1723 receiver: left,
1724 operator: typed_token::<Token![.?]>(operator),
1725 member: Box::new(right),
1726 }),
1727 _ => unreachable!(),
1728 }),
1729 BinaryLeft::Expression(left) if spelling == "#" => Ok(Expr!(Op::Bin::Index {
1730 receiver: left,
1731 operator: typed_token(operator),
1732 index: Box::new(right),
1733 })),
1734 BinaryLeft::Expression(left) => {
1735 let spelling = spelling.to_owned();
1736 let operator = BinaryOperator::from_token_tree_with_trivia(
1737 operator.token,
1738 operator.trailing_trivia,
1739 )
1740 .ok_or(NativeParseError::Unsupported {
1741 syntax: spelling,
1742 span,
1743 })?;
1744 Ok(Expr!(Op::Bin::Regular {
1745 left_operand: left,
1746 operator,
1747 right_operand: Box::new(right),
1748 }))
1749 }
1750 }
1751}
1752
1753fn lower_assignment(
1755 target: AssignmentTarget,
1756 operator: SignificantToken,
1757 right: Expr,
1758 local: bool,
1759) -> Expr {
1760 match (local, target) {
1761 (false, AssignmentTarget::Symbol(variable)) => {
1762 Expr!(Assign::Simple::Global {
1763 variable,
1764 operator: typed_token(operator),
1765 value: Box::new(right),
1766 })
1767 }
1768 (true, AssignmentTarget::Symbol(variable)) => {
1769 Expr!(Assign::Simple::Local {
1770 variable,
1771 operator: typed_token(operator),
1772 value: Box::new(right),
1773 })
1774 }
1775 (false, AssignmentTarget::Operator(argument_expr)) => {
1776 Expr!(Assign::Op {
1777 argument_expr,
1778 operator: typed_token(operator),
1779 value_expr: Box::new(right),
1780 })
1781 }
1782 (true, AssignmentTarget::Operator(ExprOp::Bin(ExprOpBin::Adj(application)))) => {
1783 let (typical_value, function) = installation_value(right);
1784 Expr!(Assign::Install::Method {
1785 method: application.left_operand,
1786 operator: application.operator,
1787 signature: application.right_operand,
1788 assign_op: typed_token(operator),
1789 typical_value,
1790 function: Box::new(function),
1791 })
1792 }
1793 (true, AssignmentTarget::Operator(domain_expr)) => {
1794 let (typical_value, function) = installation_value(right);
1795 Expr!(Assign::Install::Op {
1796 domain_expr,
1797 assign_op: typed_token(operator),
1798 typical_value,
1799 function: Box::new(function),
1800 })
1801 }
1802 (true, AssignmentTarget::New(new_statement)) => {
1803 Expr!(Assign::Install::New {
1804 new_statement,
1805 operator: typed_token(operator),
1806 function: Box::new(right),
1807 })
1808 }
1809 (local, AssignmentTarget::List(argument_list)) => {
1810 if local {
1811 Expr!(Assign::Parallel::Local {
1812 argument_list,
1813 operator: typed_token(operator),
1814 value: Box::new(right),
1815 })
1816 } else {
1817 Expr!(Assign::Parallel::Global {
1818 argument_list,
1819 operator: typed_token(operator),
1820 value: Box::new(right),
1821 })
1822 }
1823 }
1824 (false, AssignmentTarget::New(_)) => {
1825 unreachable!("global assignment preparation rejects new statements")
1826 }
1827 }
1828}
1829
1830pub(crate) fn installation_value(value: Expr) -> (Option<TypeAnnotation>, Expr) {
1832 match value {
1833 Expr::Option(value) => (
1834 Some(TypeAnnotation::new(value.key, value.operator)),
1835 *value.value,
1836 ),
1837 value => (None, value),
1838 }
1839}
1840
1841fn parse_cell_stream(cells: CellStream) -> Result<SourceFile, NativeParseError> {
1843 let mut elements = Vec::new();
1844 let eof_span = cells.physical_eof();
1845 let mut comments = CommentTrivia::default();
1846 let mut cells = cells.into_iter().peekable();
1847 while let Some(cell) = cells.next() {
1848 if cell.is_empty() {
1849 comments.append(CommentTrivia::take_inner(
1850 &mut cell.into_parser_token_stream(),
1851 ));
1852 continue;
1853 }
1854 let eoc = cells
1855 .peek()
1856 .and_then(cell_start_span)
1857 .unwrap_or_else(|| end_span(&cell));
1858 if let Some(element) = parse_raw_cell_at(cell, eoc)? {
1859 elements.push(element);
1860 }
1861 }
1862 let mut source_file = SourceFile::new(elements, EOF::new("", eof_span));
1863 source_file.comments = comments;
1864 Ok(source_file)
1865}
1866
1867fn tokenize_for_native_parser(tokens: TokenStream) -> Result<CellStream, NativeParseError> {
1869 match tokens.to_cell_stream() {
1870 Ok(cells) => Ok(cells),
1871 Err(tokenize_error) => {
1872 let incomplete = frame_recovering(tokens).incomplete;
1873 if let Some(cell) = incomplete
1874 && let Err(parse_error) = parse_raw_cell(cell)
1875 {
1876 return Err(parse_error);
1877 }
1878 Err(NativeParseError::Tokenize(tokenize_error))
1879 }
1880 }
1881}
1882
1883pub(crate) fn parse_raw_cell(
1885 tokens: CellTokenStream,
1886) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1887 let eoc = end_span(&tokens);
1888 parse_raw_cell_at(tokens, eoc)
1889}
1890
1891fn parse_raw_cell_at(
1893 tokens: CellTokenStream,
1894 eoc: Span,
1895) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1896 let ends_with_semicolon = ends_with_cell_semicolon(&tokens);
1897 let mut tokens = tokens.into_parser_token_stream();
1898 let comments = CommentTrivia::take_from_cell(&mut tokens);
1899 let semicolon = ends_with_semicolon
1900 .then(|| tokens.take_final_punctuation(";"))
1901 .flatten()
1902 .map(|(punctuation, trailing_trivia)| {
1903 <Token![;] as Token>::from_token_tree_with_trivia(
1904 TokenTree::Punct(punctuation),
1905 trailing_trivia,
1906 )
1907 .expect("a semicolon punctuation token lowers to Token![;]")
1908 });
1909 let mut cell = Engine::new(tokens).parse_cell(semicolon, eoc)?;
1910 if let Some(cell) = &mut cell {
1911 cell.comments = comments;
1912 }
1913 Ok(cell)
1914}
1915
1916fn cell_start_span(tokens: &CellTokenStream) -> Option<Span> {
1918 let token = tokens.iter().next()?;
1919 let span = token
1920 .leading_trivia()
1921 .first()
1922 .map_or_else(|| token.span(), Spanned::span);
1923 span.start().map(|start| span.at(start))
1924}
1925
1926impl Parse for Expr {
1927 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1928 let tokens = input.by_ref().collect::<TokenStream>();
1929 let mut engine = Engine::new(tokens);
1930 engine.skip_trivia();
1931 let value = engine
1932 .parse_required(PREC_CLOSER)
1933 .map_err(token_parse_error)?;
1934 engine.skip_trivia();
1935 match engine.peek() {
1936 Lookahead::End(_) => Ok(value),
1937 Lookahead::Token(token) => Err(TokenParseError::TrailingToken {
1938 found: token.token.description(),
1939 span: token.token.expect_span(),
1940 }),
1941 }
1942 }
1943}
1944
1945impl Parse for SourceFile {
1946 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1947 let tokens = input.by_ref().collect();
1948 tokenize_for_native_parser(tokens)
1949 .and_then(parse_cell_stream)
1950 .map_err(token_parse_error)
1951 }
1952}
1953
1954fn token_parse_error(error: NativeParseError) -> TokenParseError {
1956 let span = error.expect_span();
1957 TokenParseError::Syntax {
1958 message: error.to_string(),
1959 span,
1960 }
1961}
1962
1963fn parsing_spelling(token: &TokenTree) -> &str {
1965 token.spelling().map_or("", canonical_word_spelling)
1966}
1967
1968fn typed_token<T: Token>(token: SignificantToken) -> T {
1970 let spelling = token.token.description();
1971 T::from_token_tree_with_trivia(token.token, token.trailing_trivia)
1972 .unwrap_or_else(|| panic!("`{spelling}` cannot be lowered to `{}`", T::SPELLING))
1973}
1974
1975fn typed_terminal<T: Terminal>(mut terminal: T, trailing_trivia: TrailingTrivia) -> T {
1977 *terminal.trailing_trivia_mut() = trailing_trivia;
1978 terminal
1979}
1980
1981fn empty_span_at(lookahead: &Span) -> Span {
1983 lookahead.subspan(0, 0)
1984}
1985
1986fn lower_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
1988 let body = &text[1..text.len() - 1];
1989 let mut elements = Vec::new();
1990 let mut content_start = 0;
1991 let mut cursor = 0;
1992
1993 while cursor < body.len() {
1994 if body.as_bytes()[cursor] != b'\\' {
1995 cursor += 1;
1996 continue;
1997 }
1998 if content_start < cursor {
1999 elements.push(StringElement::Content(StringContent::new(
2000 &body[content_start..cursor],
2001 span.subspan(content_start + 1, cursor + 1),
2002 )));
2003 }
2004 let escape_end = match body.as_bytes()[cursor + 1] {
2005 b'x' => cursor + 4,
2006 b'u' => cursor + 6,
2007 b'0'..=b'7' => {
2008 let mut end = cursor + 2;
2009 while end < body.len()
2010 && end < cursor + 4
2011 && body.as_bytes()[end].is_ascii_digit()
2012 && body.as_bytes()[end] < b'8'
2013 {
2014 end += 1;
2015 }
2016 end
2017 }
2018 _ => cursor + 2,
2019 };
2020 elements.push(StringElement::Escape(EscapeSequence::new(
2021 &body[cursor..escape_end],
2022 span.subspan(cursor + 1, escape_end + 1),
2023 )));
2024 cursor = escape_end;
2025 content_start = cursor;
2026 }
2027 if content_start < body.len() {
2028 elements.push(StringElement::Content(StringContent::new(
2029 &body[content_start..],
2030 span.subspan(content_start + 1, text.len() - 1),
2031 )));
2032 }
2033 typed_terminal(StringLiteral::new(elements, span), trailing_trivia).into()
2034}
2035
2036fn lower_raw_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
2038 let body = &text[3..text.len() - 3];
2039 let mut elements = Vec::new();
2040 let mut content_start = 0;
2041 let mut cursor = 0;
2042
2043 while cursor + 1 < body.len() {
2044 if &body.as_bytes()[cursor..cursor + 2] != b"//" {
2045 cursor += 1;
2046 continue;
2047 }
2048 if content_start < cursor {
2049 elements.push(RawStringElement::Content(RawStringContent::new(
2050 &body[content_start..cursor],
2051 span.subspan(content_start + 3, cursor + 3),
2052 )));
2053 }
2054 elements.push(RawStringElement::Escape(EscapeSequence::new(
2055 "//",
2056 span.subspan(cursor + 3, cursor + 5),
2057 )));
2058 cursor += 2;
2059 content_start = cursor;
2060 }
2061 if content_start < body.len() {
2062 elements.push(RawStringElement::Content(RawStringContent::new(
2063 &body[content_start..],
2064 span.subspan(content_start + 3, text.len() - 3),
2065 )));
2066 }
2067 typed_terminal(RawStringLiteral::new(elements, span), trailing_trivia).into()
2068}
2069
2070fn collection_contents(expression: Expr) -> Option<(crate::Delimiter, Option<PackedContent>)> {
2072 match expression {
2073 Expr::Collection(ExprCollection::Sequence(value)) if value.statements.is_empty() => {
2074 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2075 }
2076 Expr::Collection(ExprCollection::List(value)) if value.statements.is_empty() => {
2077 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2078 }
2079 Expr::Collection(ExprCollection::Array(value)) if value.statements.is_empty() => {
2080 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2081 }
2082 Expr::Collection(ExprCollection::AngleBar(value)) if value.statements.is_empty() => {
2083 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
2084 }
2085 Expr::Holder(value) if value.muted.is_empty() => {
2086 let elements = value.value.map(|value| (*value).into());
2087 Some((DelimiterValue::delimiter(&value.delimiter), elements))
2088 }
2089 _ => None,
2090 }
2091}
2092
2093pub(crate) fn assignment_list(expression: Expr) -> Option<AssignmentList> {
2095 let (delimiter, elements) = collection_contents(expression)?;
2096 let contents = match elements {
2097 Some(elements) => {
2098 let components = packed_components(elements).map(assignment_argument)?;
2099 Some(match components.into_punctuated() {
2100 Ok(arguments) => AssignmentListContent!(Pack { arguments }),
2101 Err(argument) => argument.into(),
2102 })
2103 }
2104 None => None,
2105 };
2106 Some(AssignmentList::new(Delimited::new(delimiter, contents)))
2107}
2108
2109fn assignment_argument(component: Component) -> Option<AssignmentArgument> {
2111 match component {
2112 Component::Empty(value) => Some(AssignmentArgument::Empty(value)),
2113 Component::Expr(value) => match *value {
2114 Expr::Symbol(value) => Some(AssignmentArgument::Symbol(value)),
2115 Expr::Op(value) => Some(AssignmentArgument::Op(value)),
2116 value => assignment_list(value).map(Into::into),
2117 },
2118 }
2119}
2120
2121fn expr_pack_symbols(elements: ExprPack) -> Option<Punctuated<Symbol>> {
2123 elements
2124 .pack
2125 .try_map(
2126 |component| match component {
2127 Component::Expr(value) => match *value {
2128 Expr::Symbol(value) => Ok(value),
2129 _ => Err(()),
2130 },
2131 Component::Empty(_) => Err(()),
2132 },
2133 Ok,
2134 )
2135 .ok()
2136}
2137
2138fn packed_components(content: PackedContent) -> Components<Component> {
2140 match content {
2141 PackedContent::Expr(expression) => Components {
2142 first: Component::Expr(expression),
2143 rest: Vec::new(),
2144 },
2145 PackedContent::Pack(pack) => Components::from_punctuated(pack.pack),
2146 }
2147}
2148
2149pub(crate) fn lambda_arguments(expression: Expr) -> Option<LambdaArguments> {
2151 match expression {
2152 Expr::Symbol(value) => Some(LambdaArguments::Variadic(value)),
2153 expression => {
2154 let (delimiter, elements) = collection_contents(expression)?;
2155 let arguments = match elements {
2156 Some(PackedContent::Expr(expression)) => match *expression {
2157 Expr::Symbol(value) => Some(ArgumentListContent::Symbol(value)),
2158 _ => return None,
2159 },
2160 Some(PackedContent::Pack(pack)) => Some(ArgumentListContent!(Pack {
2161 arguments: expr_pack_symbols(pack)?,
2162 })),
2163 None => None,
2164 };
2165 Some(LambdaArguments::List(Box::new(Delimited::new(
2166 delimiter, arguments,
2167 ))))
2168 }
2169 }
2170}
2171
2172fn token_parse_rule(spelling: &str) -> Option<TokenParseRule> {
2174 TOKEN_PARSE_RULES
2175 .binary_search_by_key(&spelling, |(declared, _)| *declared)
2176 .ok()
2177 .map(|index| TOKEN_PARSE_RULES[index].1)
2178}
2179
2180fn keyword_action(spelling: &str) -> Option<UnaryAction> {
2182 Some(match spelling {
2183 "break" | "continue" | "return" | "catch" | "throw" | "trap" => UnaryAction::Statement,
2184 "if" | "while" | "try" | "for" | "new" => UnaryAction::Control,
2185 "TEST" | "time" | "timing" | "elapsedTime" | "elapsedTiming" | "breakpoint" | "profile"
2186 | "shield" | "step" | "finish" => UnaryAction::Debug,
2187 "symbol" | "global" | "local" | "threadLocal" | "threadVariable" => UnaryAction::Quote,
2188 _ => return None,
2189 })
2190}
2191
2192fn parse_info(token: &TokenTree) -> ParseInfo {
2194 if matches!(token, TokenTree::Punct(punctuation) if punctuation.text().is_empty()) {
2195 return ParseInfo::binary(PREC_APPLICATION, PREC_APPLICATION_RIGHT);
2196 }
2197 if let TokenTree::Group(group) = token {
2198 return match group.delim_kind() {
2199 DelimiterKind::Bracket | DelimiterKind::AngleBar => {
2200 ParseInfo::delimiter(PREC_COLLECTION)
2201 }
2202 DelimiterKind::Parenthesis | DelimiterKind::Brace => {
2203 ParseInfo::delimiter(PREC_APPLICATION)
2204 }
2205 };
2206 }
2207
2208 let text = parsing_spelling(token);
2209 if let Some(rule) = token_parse_rule(text) {
2210 let mut info = ParseInfo::from(rule);
2211 if let Some(action) = keyword_action(text) {
2212 info.unary = action;
2213 }
2214 return info;
2215 }
2216
2217 match token {
2218 TokenTree::Ident(_) | TokenTree::Literal(_) => ParseInfo::atom(PREC_APPLICATION),
2219 _ => ParseInfo::stop(PREC_APPLICATION),
2220 }
2221}
2222
2223#[cfg(test)]
2224mod tests {
2225 use super::{NativeCellParser, NativeCellState};
2226 use crate::cell_stream::frame_recovering;
2227 use crate::{Spanned, lex_str};
2228
2229 #[test]
2233 fn cells_use_operator_clause_and_delimiter_state() {
2234 fn cells(source: &str) -> usize {
2235 let framed = frame_recovering(lex_str(source).unwrap());
2236 framed.cells.len() + usize::from(framed.incomplete.is_some())
2237 }
2238
2239 assert_eq!(cells("1\n2"), 2);
2240 assert_eq!(cells("1 +\n2"), 1);
2241 assert_eq!(cells("not\n1"), 1);
2242 assert_eq!(cells("1!\n2"), 2);
2243 assert_eq!(cells("if condition\nthen value"), 1);
2244 assert_eq!(cells("if condition\nthen value\nnext"), 2);
2245 assert_eq!(cells("symbol if\nnext"), 2);
2246 assert_eq!(cells("symbol +\nnext"), 2);
2247 assert_eq!(cells("1 -* comment\n*- 2"), 2);
2248 assert_eq!(cells("1 + -* comment\n*- 2"), 1);
2249 assert_eq!(cells("1;2"), 2);
2250 assert_eq!(cells("(1\n2;3)"), 1);
2253 assert_eq!(cells("symbol ;"), 1);
2255 }
2256
2257 #[test]
2258 fn invalid_binary_left_side_wins_over_a_missing_right_operand() {
2259 for (source, state, diagnostic, diagnostic_text) in [
2260 (
2261 "1 + 1 =",
2262 NativeCellState::Incomplete,
2263 "expected an operand after `=`, found end of input",
2264 "=",
2265 ),
2266 (
2267 "2 =",
2268 NativeCellState::Invalid,
2269 "invalid assignment target",
2270 "=",
2271 ),
2272 (
2273 "(x, y) ->",
2274 NativeCellState::Incomplete,
2275 "expected an operand after `->`, found end of input",
2276 "->",
2277 ),
2278 (
2279 "(x + y) ->",
2280 NativeCellState::Invalid,
2281 "invalid lambda argument list",
2282 "->",
2283 ),
2284 ] {
2285 let mut parser = NativeCellParser::new();
2286 assert_eq!(parser.push_line(source), state, "source: `{source}`");
2287 let error = parser
2288 .parse_error()
2289 .unwrap_or_else(|| panic!("expected a diagnostic for `{source}`"));
2290 assert_eq!(error.to_string(), diagnostic, "source: `{source}`");
2291 assert_eq!(error.span().text(), Some(diagnostic_text));
2292 }
2293 }
2294}