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, CommentTrivia, Delimited, DelimiterKind, DelimiterToken,
17 DelimiterValue, LexError, LexErrorKind, LiteralKind, Parse, ParseStream, Parser, Punctuated,
18 Recovered, Span, Spanned, Terminal, Token, TokenParseError, TokenStream, TokenTree, Tokenize,
19 TrailingTrivia, lex_str, lex_str_recovering,
20};
21
22macro_rules! is_token {
23 ($token:expr, $($pattern:tt)*) => {
24 <Token![$($pattern)*] as Token>::matches_token_tree($token)
25 };
26}
27
28macro_rules! unexpected {
29 ($token:expr, $expected:expr) => {{
30 let token = $token;
31 NativeParseError::Unexpected {
32 span: token.expect_span(),
33 found: token.description(),
34 expected: $expected,
35 }
36 }};
37}
38
39#[derive(Debug)]
41pub struct NativeParser;
42
43impl Parser for NativeParser {
44 type Error = NativeParseError;
45
46 fn parse_cells(&mut self, cells: CellStream) -> Result<SourceFile, Self::Error> {
47 parse_cell_stream(cells)
48 }
49}
50
51pub fn parse_native(source: &str) -> Result<SourceFile, NativeParseError> {
58 let tokens = lex_str(source).map_err(NativeParseError::Lex)?;
59 let cells = tokenize_for_native_parser(tokens)?;
60 NativeParser.parse_cells(cells)
61}
62
63pub fn parse_native_recovering(
74 source: &str,
75) -> Result<Recovered<SourceFile, LexError>, NativeParseError> {
76 let recovered = lex_str_recovering(source).map_err(NativeParseError::Lex)?;
77 let (tokens, diagnostics) = recovered.into_parts();
78 let source = tokens.source();
79 let framed = frame_recovering(tokens);
80 let cells = CellStream::from_cells_with_source(
81 framed.cells.into_iter().chain(framed.incomplete),
82 source,
83 );
84 let syntax = NativeParser.parse_cells(cells)?;
85 Ok(Recovered::new(syntax, diagnostics))
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
90pub enum NativeCellState {
91 Empty,
93 Complete,
95 Incomplete,
97 Invalid,
99}
100
101#[derive(Debug)]
103pub struct CompletedNativeCell {
104 source: Span,
105 syntax: crate::nodes::Cell,
106}
107
108impl CompletedNativeCell {
109 pub fn source(&self) -> &str {
115 self.source
116 .text()
117 .expect("completed cell source spans must resolve to text")
118 }
119
120 pub fn syntax(&self) -> &crate::nodes::Cell {
122 &self.syntax
123 }
124
125 pub fn into_parts(self) -> (Span, crate::nodes::Cell) {
127 (self.source, self.syntax)
128 }
129}
130
131#[derive(Debug)]
156pub struct NativeCellParser {
157 active_source: String,
158 active_tokens: TokenStream,
159 active_syntax: Option<crate::nodes::Cell>,
160 completed: Vec<CompletedNativeCell>,
161 lexer_diagnostics: Vec<LexError>,
162 parse_error: Option<NativeParseError>,
163 state: NativeCellState,
164}
165
166impl Default for NativeCellParser {
167 fn default() -> Self {
168 Self::new()
169 }
170}
171
172impl NativeCellParser {
173 pub fn new() -> Self {
175 Self {
176 active_source: String::new(),
177 active_tokens: TokenStream::new(),
178 active_syntax: None,
179 completed: Vec::new(),
180 lexer_diagnostics: Vec::new(),
181 parse_error: None,
182 state: NativeCellState::Empty,
183 }
184 }
185
186 pub fn push_line(&mut self, line: &str) -> NativeCellState {
193 self.active_source.push_str(line);
194 if !line.ends_with('\n') {
195 self.active_source.push('\n');
196 }
197 self.refresh()
198 }
199
200 pub fn state(&self) -> NativeCellState {
202 self.state
203 }
204
205 pub fn active_source(&self) -> &str {
207 &self.active_source
208 }
209
210 pub fn active_tokens(&self) -> &TokenStream {
212 &self.active_tokens
213 }
214
215 pub fn active_syntax(&self) -> Option<&crate::nodes::Cell> {
217 self.active_syntax.as_ref()
218 }
219
220 pub fn lexer_diagnostics(&self) -> &[LexError] {
222 &self.lexer_diagnostics
223 }
224
225 pub fn parse_error(&self) -> Option<&NativeParseError> {
227 self.parse_error.as_ref()
228 }
229
230 pub fn completed(&self) -> &[CompletedNativeCell] {
232 &self.completed
233 }
234
235 pub fn take_completed(&mut self) -> Vec<CompletedNativeCell> {
237 let completed = std::mem::take(&mut self.completed);
238 if self.state == NativeCellState::Complete {
239 self.state = NativeCellState::Empty;
240 }
241 completed
242 }
243
244 pub fn reset_active(&mut self) {
246 self.active_source.clear();
247 self.active_tokens = TokenStream::new();
248 self.active_syntax = None;
249 self.lexer_diagnostics.clear();
250 self.parse_error = None;
251 self.state = if self.completed.is_empty() {
252 NativeCellState::Empty
253 } else {
254 NativeCellState::Complete
255 };
256 }
257
258 fn refresh(&mut self) -> NativeCellState {
259 self.active_tokens = TokenStream::new();
260 self.active_syntax = None;
261 self.lexer_diagnostics.clear();
262 self.parse_error = None;
263
264 loop {
265 let recovered = match lex_str_recovering(&self.active_source) {
266 Ok(recovered) => recovered,
267 Err(error) => {
268 self.state = if incomplete_lex_error(error.kind()) {
269 NativeCellState::Incomplete
270 } else {
271 NativeCellState::Invalid
272 };
273 self.lexer_diagnostics.push(error);
274 return self.state;
275 }
276 };
277 let (tokens, diagnostics) = recovered.into_parts();
278 let framed = frame_recovering(tokens.clone());
279 let has_incomplete = framed.incomplete.is_some();
280 let mut cells = framed.cells.into_iter().map(|cell| (cell, true));
281 let first = cells
282 .next()
283 .or_else(|| framed.incomplete.map(|cell| (cell, false)));
284 let Some((cell, cell_complete)) = first else {
285 self.active_tokens = tokens;
286 self.lexer_diagnostics = diagnostics;
287 self.state = if self.completed.is_empty() {
288 NativeCellState::Empty
289 } else {
290 NativeCellState::Complete
291 };
292 return self.state;
293 };
294
295 let has_following_cell = cells.next().is_some() || has_incomplete;
296 let ended_by_semicolon = ends_with_cell_semicolon(&cell);
297 let boundary = end_span(&cell);
298 let end = boundary.end().unwrap_or(self.active_source.len());
299 let source = Span::ranged(std::sync::Arc::clone(boundary.source()), 0..end);
300
301 match parse_raw_cell(cell) {
302 Ok(Some(syntax)) if cell_complete && has_following_cell => {
303 self.completed.push(CompletedNativeCell { source, syntax });
304 self.active_source.replace_range(..end, "");
305 }
306 Ok(Some(syntax)) if cell_complete && diagnostics.is_empty() => {
307 self.completed.push(CompletedNativeCell { source, syntax });
308 self.active_source.clear();
309 self.active_tokens = TokenStream::new();
310 self.state = NativeCellState::Complete;
311 return self.state;
312 }
313 Ok(Some(syntax)) => {
314 self.active_tokens = tokens;
315 self.active_syntax = Some(syntax);
316 self.lexer_diagnostics = diagnostics;
317 self.state = NativeCellState::Incomplete;
318 return self.state;
319 }
320 Ok(None) => {
321 self.active_tokens = tokens;
322 self.lexer_diagnostics = diagnostics;
323 self.state = if self.completed.is_empty() {
324 NativeCellState::Empty
325 } else {
326 NativeCellState::Complete
327 };
328 return self.state;
329 }
330 Err(error) => {
331 let can_append_to_cell =
332 !cell_complete || (!has_following_cell && !ended_by_semicolon);
333 self.state = if can_append_to_cell && incomplete_parse_error(&error) {
334 NativeCellState::Incomplete
335 } else {
336 NativeCellState::Invalid
337 };
338 self.active_tokens = tokens;
339 self.lexer_diagnostics = diagnostics;
340 self.parse_error = Some(error);
341 return self.state;
342 }
343 }
344 }
345 }
346}
347
348pub(crate) fn incomplete_lex_error(kind: LexErrorKind) -> bool {
349 matches!(
350 kind,
351 LexErrorKind::UnterminatedGroup
352 | LexErrorKind::UnterminatedString
353 | LexErrorKind::UnterminatedRawString
354 | LexErrorKind::UnterminatedBlockComment
355 )
356}
357
358pub(crate) fn incomplete_parse_error(error: &NativeParseError) -> bool {
359 match error {
360 NativeParseError::MissingOperand { .. } => true,
361 NativeParseError::Unexpected { found, .. } => found == "end of input",
362 NativeParseError::Lex(error) => incomplete_lex_error(error.kind()),
363 NativeParseError::Tokenize(_) => true,
364 NativeParseError::NewlineInApplication { .. }
365 | NativeParseError::InvalidAssignmentTarget { .. }
366 | NativeParseError::InvalidLambdaParameters { .. }
367 | NativeParseError::Unsupported { .. } => false,
368 }
369}
370
371#[derive(Debug, Spanned)]
372pub enum NativeParseError {
374 Lex(LexError),
376 Tokenize(CellStreamError),
378 Unexpected {
380 found: String,
382 expected: &'static str,
384 span: Span,
386 },
387 MissingOperand {
389 operator: String,
391 span: Span,
393 },
394 NewlineInApplication {
396 span: Span,
398 },
399 InvalidAssignmentTarget {
401 span: Span,
403 },
404 InvalidLambdaParameters {
406 span: Span,
408 },
409 Unsupported {
411 syntax: String,
413 span: Span,
415 },
416}
417
418impl NativeParseError {
419 fn unexpected_end(expected: &'static str, span: Span) -> Self {
420 Self::Unexpected {
421 found: "end of input".into(),
422 expected,
423 span,
424 }
425 }
426
427 fn missing_operand_for(self, operator: &TokenTree) -> Self {
428 if matches!(self, Self::MissingOperand { .. }) {
429 Self::MissingOperand {
430 operator: operator.description(),
431 span: operator.expect_span(),
432 }
433 } else {
434 self
435 }
436 }
437}
438
439impl Display for NativeParseError {
440 fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
441 match self {
442 Self::Lex(error) => error.fmt(formatter),
443 Self::Tokenize(error) => error.fmt(formatter),
444 Self::Unexpected {
445 found, expected, ..
446 } => write!(formatter, "expected {expected}, found `{found}`"),
447 Self::MissingOperand { operator, .. } => {
448 write!(
449 formatter,
450 "expected an operand after `{operator}`, found end of input"
451 )
452 }
453 Self::NewlineInApplication { .. } => {
454 formatter.write_str("implicit application cannot cross a line break")
455 }
456 Self::InvalidAssignmentTarget { .. } => {
457 formatter.write_str("invalid assignment target")
458 }
459 Self::InvalidLambdaParameters { .. } => {
460 formatter.write_str("invalid lambda parameter list")
461 }
462 Self::Unsupported { syntax, .. } => {
463 write!(
464 formatter,
465 "native parsing of `{syntax}` is not implemented yet"
466 )
467 }
468 }
469 }
470}
471
472impl Error for NativeParseError {
473 fn source(&self) -> Option<&(dyn Error + 'static)> {
474 match self {
475 Self::Lex(error) => Some(error),
476 Self::Tokenize(error) => Some(error),
477 _ => None,
478 }
479 }
480}
481
482#[derive(Debug, Clone, Copy)]
483enum UnaryAction {
489 Atom,
490 Prefix,
491 Statement,
492 Control,
493 Debug,
494 Delimiter,
495 Quote,
496 Error,
497}
498
499#[derive(Debug, Clone, Copy)]
500struct ParseInfo {
501 precedence: u8,
502 binary_strength: Option<u8>,
503 unary_strength: Option<u8>,
504 unary: UnaryAction,
505 postfix: bool,
506}
507
508impl From<TokenParseRule> for ParseInfo {
509 fn from(rule: TokenParseRule) -> Self {
510 match rule {
511 TokenParseRule::Precedence(precedence) => Self::stop(precedence),
512 TokenParseRule::Postfix(precedence) => Self::postfix(precedence),
513 TokenParseRule::Binary(precedence, strength) => Self::binary(precedence, strength),
514 TokenParseRule::Prefix(precedence, strength) => {
515 Self::unary(precedence, UnaryAction::Prefix, strength)
516 }
517 TokenParseRule::PrefixBinary(precedence, binary, unary) => {
518 Self::prefix_binary(precedence, binary, unary)
519 }
520 TokenParseRule::Unary(precedence, strength) => {
521 Self::unary(precedence, UnaryAction::Error, strength)
522 }
523 }
524 }
525}
526
527impl ParseInfo {
528 const fn atom(precedence: u8) -> Self {
529 Self {
530 precedence,
531 binary_strength: None,
532 unary_strength: None,
533 unary: UnaryAction::Atom,
534 postfix: false,
535 }
536 }
537
538 const fn binary(precedence: u8, strength: u8) -> Self {
539 Self {
540 precedence,
541 binary_strength: Some(strength),
542 unary_strength: None,
543 unary: UnaryAction::Error,
544 postfix: false,
545 }
546 }
547
548 const fn prefix_binary(precedence: u8, binary_strength: u8, unary_strength: u8) -> Self {
549 Self {
550 precedence,
551 binary_strength: Some(binary_strength),
552 unary_strength: Some(unary_strength),
553 unary: UnaryAction::Prefix,
554 postfix: false,
555 }
556 }
557
558 const fn unary(precedence: u8, unary: UnaryAction, strength: u8) -> Self {
562 Self {
563 precedence,
564 binary_strength: None,
565 unary_strength: Some(strength),
566 unary,
567 postfix: false,
568 }
569 }
570
571 const fn postfix(precedence: u8) -> Self {
572 Self {
573 precedence,
574 binary_strength: None,
575 unary_strength: None,
576 unary: UnaryAction::Error,
577 postfix: true,
578 }
579 }
580
581 const fn delimiter(precedence: u8) -> Self {
582 Self {
583 precedence,
584 binary_strength: None,
585 unary_strength: Some(PREC_CLOSER),
586 unary: UnaryAction::Delimiter,
587 postfix: false,
588 }
589 }
590
591 const fn stop(precedence: u8) -> Self {
592 Self {
593 precedence,
594 binary_strength: None,
595 unary_strength: None,
596 unary: UnaryAction::Error,
597 postfix: false,
598 }
599 }
600}
601
602struct Engine {
603 input: ParseStream,
604}
605
606impl Engine {
607 fn new(tokens: TokenStream) -> Self {
608 Self {
609 input: ParseStream::new(tokens),
610 }
611 }
612
613 fn parse_cell(
614 mut self,
615 semicolon: Option<Token![;]>,
616 eoc_span: Span,
617 ) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
618 self.skip_trivia();
619 if matches!(self.peek(), Lookahead::End(_)) {
620 return match semicolon {
621 None => Ok(None),
622 Some(semicolon) => Err(NativeParseError::Unexpected {
623 found: ";".into(),
624 expected: "a statement before `;`",
625 span: semicolon.expect_span(),
626 }),
627 };
628 }
629
630 let (components, _) = self.parse_components()?;
631
632 if let Lookahead::Token(token) = self.peek() {
633 return Err(unexpected!(token.token, "the end of the cell"));
634 }
635
636 let eoc = EOC::new("", eoc_span);
637 Ok(Some(crate::nodes::Cell::new(
638 ExprPack::new(components),
639 semicolon,
640 eoc,
641 )))
642 }
643
644 fn parse_components(&mut self) -> Result<(Punctuated<Component>, bool), NativeParseError> {
645 let first = if self.at_punctuation(",") {
646 Component::Empty(Empty::new("", empty_span_at(&self.peek().expect_span())))
647 } else {
648 self.parse_required(PREC_COMMA)?.into()
649 };
650 let mut elements = Punctuated::from_single(first);
651 let mut has_comma = false;
652
653 while let Some(comma) = self.take_punctuation(",") {
654 has_comma = true;
655 let next = if self.at_end() || self.at_punctuation(";") || self.at_punctuation(",") {
656 Component::Empty(Empty::new("", empty_span_at(&self.peek().expect_span())))
657 } else {
658 self.parse_required(PREC_COMMA)?.into()
659 };
660 elements.push(typed_token(comma), next);
661 }
662
663 Ok((elements, has_comma))
664 }
665
666 fn parse_optional_components(
667 &mut self,
668 ) -> Result<Option<(Punctuated<Component>, bool)>, NativeParseError> {
669 if self.at_end() || self.at_punctuation(";") {
670 Ok(None)
671 } else {
672 self.parse_components().map(Some)
673 }
674 }
675
676 fn parse_required(&mut self, level: u8) -> Result<Expr, NativeParseError> {
677 let token = match self.consume() {
678 Lookahead::Token(token) => token,
679 Lookahead::End(span) => {
680 return Err(NativeParseError::MissingOperand {
681 operator: "end of input".into(),
682 span,
683 });
684 }
685 };
686 self.parse_consumed(token, level)
687 }
688
689 fn parse_nullable(&mut self, level: u8) -> Result<Option<Expr>, NativeParseError> {
690 let lookahead = self.peek();
691 let Lookahead::Token(token) = lookahead else {
692 return Ok(None);
693 };
694 if parse_info(&token.token).precedence <= level {
695 return Ok(None);
696 }
697 let Lookahead::Token(token) = self.consume() else {
698 unreachable!("the token just peeked is consumable")
699 };
700 self.parse_consumed(token, level).map(Some)
701 }
702
703 fn parse_consumed(
704 &mut self,
705 token: SignificantToken,
706 level: u8,
707 ) -> Result<Expr, NativeParseError> {
708 let info = parse_info(&token.token);
709 let result = match info.unary {
710 UnaryAction::Atom => lower_atom(token)?,
711 UnaryAction::Prefix => {
712 let strength = info.unary_strength.expect("prefix operators have U");
713 let operand = self.parse_required(level.max(strength))?;
714 let span = token.token.expect_span();
715 let spelling = token.token.description();
716 let operator =
717 PrefixOperator::from_token_tree_with_trivia(token.token, token.trailing_trivia)
718 .ok_or({
719 NativeParseError::Unsupported {
720 syntax: spelling,
721 span,
722 }
723 })?;
724 PrefixExpr::new(operator, operand).into()
725 }
726 UnaryAction::Statement => {
727 let strength = info
728 .unary_strength
729 .expect("prefix statements have a unary binding strength");
730 let operand = if is_token!(&token.token, break)
731 || is_token!(&token.token, continue)
732 || is_token!(&token.token, return)
733 {
734 self.parse_nullable(level.max(strength))?
735 } else {
736 self.parse_required(level.max(strength))
737 .map_err(|error| error.missing_operand_for(&token.token))?
738 .into()
739 };
740 lower_prefix_statement(token, operand)
741 }
742 UnaryAction::Control => {
743 if is_token!(&token.token, if) {
744 self.parse_if_statement(token)?
745 } else if is_token!(&token.token, for) {
746 self.parse_for_loop(token)?
747 } else if is_token!(&token.token, while) {
748 self.parse_while_loop(token)?
749 } else if is_token!(&token.token, try) {
750 self.parse_try_statement(token)?
751 } else if is_token!(&token.token, new) {
752 self.parse_new_statement(token)?
753 } else {
754 unreachable!("control actions are assigned only to control keywords")
755 }
756 }
757 UnaryAction::Debug => self.parse_debug_clause(token)?,
758 UnaryAction::Delimiter => parse_delimited(token)?,
759 UnaryAction::Quote => {
760 let operator = token.token.description();
761 let quoted = match self.consume() {
762 Lookahead::Token(quoted) => quoted,
763 Lookahead::End(span) => {
764 return Err(NativeParseError::MissingOperand { operator, span });
765 }
766 };
767 let specifier = if is_token!(&token.token, symbol) {
768 QuoteSpecifier::Symbol(typed_token(token))
769 } else if is_token!(&token.token, local) {
770 QuoteSpecifier::Local(typed_token(token))
771 } else if is_token!(&token.token, global) {
772 QuoteSpecifier::Global(typed_token(token))
773 } else if is_token!(&token.token, threadVariable) {
774 QuoteSpecifier::ThreadVariable(typed_token(token))
775 } else if is_token!(&token.token, threadLocal) {
776 QuoteSpecifier::ThreadLocal(typed_token(token))
777 } else {
778 unreachable!("quote actions are assigned only to quote specifiers")
779 };
780 let quoted_span = quoted.token.expect_span();
781 let Some(quoted_text) = quoted.token.spelling().map(str::to_owned) else {
782 return Err(unexpected!(quoted.token, "a quoted token"));
783 };
784 let quoted = typed_terminal(
785 Symbol::new(quoted_text, quoted_span),
786 quoted.trailing_trivia,
787 );
788 QuoteExpression::new(specifier, quoted).into()
789 }
790 UnaryAction::Error => {
791 return Err(unexpected!(token.token, "an expression"));
792 }
793 };
794 self.accumulate(result, level)
795 }
796
797 fn parse_if_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
798 let condition = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
799 let then_keyword = self.consume_exact("then")?;
800 let then_value = self.required_clause_expression(PREC_CONTROL, &then_keyword.token)?;
801 let then_clause = ThenClause::new(typed_token(then_keyword), then_value);
802 let else_clause = self
803 .take_exact("else")
804 .map(|else_keyword| {
805 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword.token)?;
806 Ok::<_, NativeParseError>(ElseClause::new(typed_token(else_keyword), value))
807 })
808 .transpose()?;
809 Ok(IfStatement::new(typed_token(keyword), condition, then_clause, else_clause).into())
810 }
811
812 fn parse_for_loop(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
813 let variable = self.consume_symbol("a loop variable")?;
814
815 let iteration_domain = if let Some(token) = self.take_exact("in") {
816 let collection = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
817 Some(IterIn::new(typed_token(token), collection).into())
818 } else {
819 let lower_bound = self
820 .take_exact("from")
821 .map(|token| {
822 let value = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
823 Ok::<_, NativeParseError>(RangeBoundFrom::new(typed_token(token), value))
824 })
825 .transpose()?;
826 let upper_bound = self
827 .take_exact("to")
828 .map(|token| {
829 let value = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
830 Ok::<_, NativeParseError>(RangeBoundTo::new(typed_token(token), value))
831 })
832 .transpose()?;
833 (lower_bound.is_some() || upper_bound.is_some())
834 .then(|| IterRange::new(lower_bound, upper_bound).into())
835 };
836
837 let when_condition = if let Some(token) = self.take_exact("when") {
838 let condition = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
839 Some(WhenCondition::new(typed_token(token), condition))
840 } else {
841 None
842 };
843 let body = self.parse_loop_body()?;
844
845 Ok(ForLoop::new(
846 typed_token(keyword),
847 variable,
848 iteration_domain,
849 when_condition,
850 body,
851 )
852 .into())
853 }
854
855 fn parse_while_loop(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
856 let condition = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
857 let body = self.parse_loop_body()?;
858 Ok(WhileLoop::new(typed_token(keyword), condition, body).into())
859 }
860
861 fn parse_loop_body(&mut self) -> Result<LoopBody, NativeParseError> {
862 let (list_step, do_step) = if let Some(token) = self.take_exact("list") {
863 let listed_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
864 let list_step = Some(ListStep::new(typed_token(token), listed_value));
865 if let Some(token) = self.take_exact("do") {
866 let ignored_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
867 (
868 list_step,
869 Some(DoStep::new(typed_token(token), ignored_value)),
870 )
871 } else {
872 (list_step, None)
873 }
874 } else if let Some(token) = self.take_exact("do") {
875 let ignored_value = self.required_clause_expression(PREC_CONTROL, &token.token)?;
876 (None, Some(DoStep::new(typed_token(token), ignored_value)))
877 } else {
878 return Err(self.expected_at_lookahead("`list` or `do`"));
879 };
880
881 Ok(LoopBody::new(list_step, do_step))
882 }
883
884 fn parse_try_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
885 let value = self.required_clause_expression(PREC_CONTROL, &keyword.token)?;
886 let then_clause = self
887 .take_exact("then")
888 .map(|then_keyword| {
889 let value = self.required_clause_expression(PREC_CONTROL, &then_keyword.token)?;
890 Ok::<_, NativeParseError>(ThenClause::new(typed_token(then_keyword), value))
891 })
892 .transpose()?;
893
894 let fallback = if let Some(else_keyword) = self.take_exact("else") {
895 let value = self.required_clause_expression(PREC_CONTROL, &else_keyword.token)?;
896 Some(TryFallback::ElseClause(ElseClause::new(
897 typed_token(else_keyword),
898 value,
899 )))
900 } else if let Some(except_keyword) = self.take_exact("except") {
901 let exception = self.consume_symbol("an exception symbol")?;
902 let do_keyword = self.consume_exact("do")?;
903 let value = self.required_clause_expression(PREC_CONTROL, &do_keyword.token)?;
904 Some(TryFallback::ExceptDo(ExceptDo::new(
905 typed_token(except_keyword),
906 exception,
907 typed_token(do_keyword),
908 value,
909 )))
910 } else {
911 None
912 };
913
914 Ok(TryStatement::new(typed_token(keyword), value, then_clause, fallback).into())
915 }
916
917 fn parse_new_statement(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
918 let class = self.required_clause_expression(PREC_LOOP_CLAUSE, &keyword.token)?;
919 let parent_class = if let Some(token) = self.take_exact("of") {
920 let parent = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
921 Some(OfClass::new(typed_token(token), parent))
922 } else {
923 None
924 };
925 let instance = if let Some(token) = self.take_exact("from") {
926 let instance = self.required_clause_expression(PREC_LOOP_CLAUSE, &token.token)?;
927 Some(FromInstance::new(typed_token(token), instance))
928 } else {
929 None
930 };
931
932 Ok(NewStatement::new(typed_token(keyword), class, parent_class, instance).into())
933 }
934
935 fn parse_debug_clause(&mut self, keyword: SignificantToken) -> Result<Expr, NativeParseError> {
936 let spelling = parsing_spelling(&keyword.token).to_owned();
937 if matches!(
938 spelling.as_str(),
939 "time" | "timing" | "elapsedTime" | "elapsedTiming" | "profile"
940 ) {
941 let value = self
942 .parse_required(PREC_CONTROL)
943 .map_err(|error| error.missing_operand_for(&keyword.token))?;
944 let modifier = match spelling.as_str() {
945 "time" => ProfilingModifier::Time(typed_token(keyword)),
946 "timing" => ProfilingModifier::Timing(typed_token(keyword)),
947 "elapsedTime" => ProfilingModifier::ElapsedTime(typed_token(keyword)),
948 "elapsedTiming" => ProfilingModifier::ElapsedTiming(typed_token(keyword)),
949 "profile" => ProfilingModifier::Profile(typed_token(keyword)),
950 _ => unreachable!(),
951 };
952 return Ok(ProfilingExpr::new(modifier, value).into());
953 }
954 let value_is_optional = matches!(spelling.as_str(), "step" | "finish");
955 let value = if value_is_optional {
956 self.parse_nullable(PREC_CONTROL)?
957 } else {
958 Some(
959 self.parse_required(PREC_CONTROL)
960 .map_err(|error| error.missing_operand_for(&keyword.token))?,
961 )
962 };
963 let keyword = match spelling.as_str() {
964 "step" => DebugKeyword::Step(typed_token(keyword)),
965 "finish" => DebugKeyword::Finish(typed_token(keyword)),
966 "shield" => DebugKeyword::Shield(typed_token(keyword)),
967 "TEST" => DebugKeyword::Test(typed_token(keyword)),
968 "breakpoint" => DebugKeyword::Breakpoint(typed_token(keyword)),
969 _ => unreachable!("debug actions are assigned only to debug keywords"),
970 };
971 Ok(DebugExpr::new(keyword, value).into())
972 }
973
974 fn required_clause_expression(
975 &mut self,
976 level: u8,
977 keyword: &TokenTree,
978 ) -> Result<Expr, NativeParseError> {
979 match self.parse_nullable(level)? {
980 None => Err(NativeParseError::MissingOperand {
981 operator: keyword.description(),
982 span: keyword.expect_span(),
983 }),
984 Some(expression) => Ok(expression),
985 }
986 }
987
988 fn consume_symbol(&mut self, expected: &'static str) -> Result<Symbol, NativeParseError> {
989 match self.consume() {
990 Lookahead::Token(token)
991 if matches!(token.token, TokenTree::Ident(_))
992 && matches!(parse_info(&token.token).unary, UnaryAction::Atom) =>
993 {
994 let span = token.token.expect_span();
995 let text = token.token.description();
996 Ok(typed_terminal(
997 Symbol::new(text, span),
998 token.trailing_trivia,
999 ))
1000 }
1001 Lookahead::Token(token) => Err(unexpected!(token.token, expected)),
1002 Lookahead::End(span) => Err(NativeParseError::unexpected_end(expected, span)),
1003 }
1004 }
1005
1006 fn consume_exact(
1007 &mut self,
1008 spelling: &'static str,
1009 ) -> Result<SignificantToken, NativeParseError> {
1010 match self.consume() {
1011 Lookahead::Token(token) if parsing_spelling(&token.token) == spelling => Ok(token),
1012 Lookahead::Token(token) => Err(unexpected!(token.token, spelling)),
1013 Lookahead::End(span) => Err(NativeParseError::unexpected_end(spelling, span)),
1014 }
1015 }
1016
1017 fn take_exact(&mut self, spelling: &'static str) -> Option<SignificantToken> {
1018 if matches!(
1019 self.peek(),
1020 Lookahead::Token(token)
1021 if parsing_spelling(&token.token) == spelling
1022 ) {
1023 let Lookahead::Token(token) = self.consume() else {
1024 unreachable!("the token just peeked is consumable")
1025 };
1026 Some(token)
1027 } else {
1028 None
1029 }
1030 }
1031
1032 fn expected_at_lookahead(&self, expected: &'static str) -> NativeParseError {
1033 match self.peek() {
1034 Lookahead::Token(token) => unexpected!(token.token, expected),
1035 Lookahead::End(span) => NativeParseError::unexpected_end(expected, span),
1036 }
1037 }
1038
1039 fn accumulate(&mut self, mut left: Expr, level: u8) -> Result<Expr, NativeParseError> {
1040 loop {
1041 let Lookahead::Token(next) = self.peek() else {
1042 return Ok(left);
1043 };
1044 let info = if matches!(&next.token, TokenTree::Punct(punct) if punct.text().is_empty())
1045 {
1046 self.adjacency_info()
1047 } else {
1048 parse_info(&next.token)
1049 };
1050 if info.precedence <= level {
1051 return Ok(left);
1052 }
1053 let Lookahead::Token(operator) = self.consume() else {
1054 unreachable!("the token just peeked is consumable")
1055 };
1056 left = if matches!(&operator.token, TokenTree::Punct(punct) if punct.text().is_empty())
1057 {
1058 let right = self
1059 .parse_required(PREC_APPLICATION_RIGHT)
1060 .map_err(|error| error.missing_operand_for(&operator.token))?;
1061 let adjacency = typed_terminal(
1062 Adj::new("", operator.token.expect_span()),
1063 operator.trailing_trivia,
1064 );
1065 AdjacentExpr::new(left, adjacency, right).into()
1066 } else if let Some(strength) = info.binary_strength {
1067 let left = BinaryLeft::prepare(left, &operator.token)?;
1068 let right = self
1069 .parse_required(strength)
1070 .map_err(|error| error.missing_operand_for(&operator.token))?;
1071 lower_binary(left, operator, right)?
1072 } else if info.postfix {
1073 let span = operator.token.expect_span();
1074 let spelling = operator.token.description();
1075 let operator = PostfixOperator::from_token_tree_with_trivia(
1076 operator.token,
1077 operator.trailing_trivia,
1078 )
1079 .ok_or(NativeParseError::Unsupported {
1080 syntax: spelling,
1081 span,
1082 })?;
1083 PostfixExpr::new(left, operator).into()
1084 } else if !matches!(info.unary, UnaryAction::Error) {
1085 if operator.crossed_newline {
1086 return Err(NativeParseError::NewlineInApplication {
1087 span: operator.token.expect_span(),
1088 });
1089 }
1090 let adjacency_span = operator.token.expect_span().subspan(0, 0);
1091 let right = self.parse_consumed(operator, PREC_APPLICATION_RIGHT)?;
1092 AdjacentExpr::new(left, Adj::new("", adjacency_span), right).into()
1093 } else {
1094 return Err(unexpected!(operator.token, "an operator"));
1095 };
1096 }
1097 }
1098
1099 fn adjacency_info(&self) -> ParseInfo {
1100 let mut input = self.input.fork();
1101 let _ = input.next_significant();
1102 input.next_significant().map_or_else(
1103 || ParseInfo::stop(PREC_APPLICATION),
1104 |right| ParseInfo::binary(parse_info(&right.token).precedence, PREC_APPLICATION_RIGHT),
1105 )
1106 }
1107
1108 fn only_expression(&self, components: Punctuated<Component>) -> Result<Expr, NativeParseError> {
1109 let mut components = components.into_iter();
1110 match (components.next(), components.next()) {
1111 (Some(Component::Expr(value)), None) => Ok(*value),
1112 (Some(value), _) => Err(NativeParseError::Unexpected {
1113 found: "a sequence".into(),
1114 expected: "one expression",
1115 span: value.expect_span(),
1116 }),
1117 (None, _) => Err(NativeParseError::MissingOperand {
1118 operator: "empty expression".into(),
1119 span: self.input.eof_span(),
1120 }),
1121 }
1122 }
1123
1124 fn peek(&self) -> Lookahead {
1125 self.input.lookahead()
1126 }
1127
1128 fn consume(&mut self) -> Lookahead {
1129 self.input.consume_lookahead()
1130 }
1131
1132 fn skip_trivia(&mut self) {
1133 self.input.skip_trivia();
1134 }
1135
1136 fn at_end(&self) -> bool {
1137 matches!(self.peek(), Lookahead::End(_))
1138 }
1139
1140 fn at_punctuation(&self, spelling: &str) -> bool {
1141 matches!(
1142 self.peek(),
1143 Lookahead::Token(token)
1144 if token.token.spelling() == Some(spelling)
1145 )
1146 }
1147
1148 fn take_punctuation(&mut self, spelling: &str) -> Option<SignificantToken> {
1149 if !self.at_punctuation(spelling) {
1150 return None;
1151 }
1152 let Lookahead::Token(token) = self.consume() else {
1153 unreachable!("the punctuation just peeked is consumable")
1154 };
1155 Some(token)
1156 }
1157}
1158
1159fn parse_delimited(token: SignificantToken) -> Result<Expr, NativeParseError> {
1160 let group_trailing = token.trailing_trivia;
1161 let group = match token.token {
1162 TokenTree::Group(group) => group,
1163 token => return Err(unexpected!(token, "a delimited group")),
1164 };
1165 let kind = group.delim_kind();
1166 let delimiter_spans = group.delimiter().spans.clone();
1167 let mut group_contents = group.into_stream();
1168 let opening_trivia = group_contents.take_leading_trivia();
1169 let mut contents = Engine::new(group_contents);
1170 let mut muted = Vec::new();
1171 let (elements, comma) = loop {
1172 let elements = contents.parse_optional_components()?;
1173 let Some(separator) = contents.take_punctuation(";") else {
1174 break elements.map_or((None, false), |(elements, comma)| (Some(elements), comma));
1175 };
1176 let Some((elements, _)) = elements else {
1177 return Err(unexpected!(separator.token, "a statement before `;`"));
1178 };
1179 muted.push(Statement::new(
1180 ExprPack::new(elements),
1181 typed_token(separator),
1182 ));
1183 };
1184 if let Lookahead::Token(token) = contents.peek() {
1185 return Err(unexpected!(token.token, "the end of the group"));
1186 }
1187
1188 let expression: Expr = match kind {
1189 DelimiterKind::Bracket => {
1190 let mut value = Array::new(muted, elements.map(ExprPack::new));
1191 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1192 value.into()
1193 }
1194 DelimiterKind::Brace => {
1195 let mut value = List::new(muted, elements.map(ExprPack::new));
1196 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1197 value.into()
1198 }
1199 DelimiterKind::AngleBar => {
1200 let mut value = AngleBarList::new(muted, elements.map(ExprPack::new));
1201 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1202 value.into()
1203 }
1204 DelimiterKind::Parenthesis if !muted.is_empty() || comma => {
1205 let mut value = if comma {
1206 Sequence::new(
1207 muted,
1208 Some(ExprPack::new(
1209 elements.expect("a comma pack always contains components"),
1210 )),
1211 )
1212 } else {
1213 let value = elements
1214 .map(|elements| contents.only_expression(elements))
1215 .transpose()?;
1216 let mut value = Holder::new(muted, value);
1217 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1218 return Ok(value.into());
1219 };
1220 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1221 value.into()
1222 }
1223 DelimiterKind::Parenthesis => {
1224 let value = elements
1225 .map(|elements| contents.only_expression(elements))
1226 .transpose()?;
1227 let mut value = Holder::new(Vec::new(), value);
1228 value.delimiter = typed_delimiter(delimiter_spans, opening_trivia, group_trailing);
1229 value.into()
1230 }
1231 };
1232 Ok(expression)
1233}
1234
1235fn typed_delimiter<D: DelimiterToken>(
1236 spans: crate::DoubleSpan,
1237 opening_trivia: TrailingTrivia,
1238 closing_trivia: TrailingTrivia,
1239) -> D {
1240 let mut delimiter = D::new(spans);
1241 *delimiter.opening_trivia_mut() = opening_trivia;
1242 *delimiter.closing_trivia_mut() = closing_trivia;
1243 delimiter
1244}
1245
1246fn lower_prefix_statement(keyword: SignificantToken, value: Option<Expr>) -> Expr {
1247 if is_token!(&keyword.token, break) {
1248 BreakExpr::new(typed_token(keyword), value).into()
1249 } else if is_token!(&keyword.token, continue) {
1250 ContinueExpr::new(typed_token(keyword), value).into()
1251 } else if is_token!(&keyword.token, return) {
1252 ReturnExpr::new(typed_token(keyword), value).into()
1253 } else {
1254 let value = value.expect("catch, throw, and trap require a value");
1255 if is_token!(&keyword.token, catch) {
1256 Catch::new(typed_token(keyword), value).into()
1257 } else if is_token!(&keyword.token, throw) {
1258 Throw::new(typed_token(keyword), value).into()
1259 } else if is_token!(&keyword.token, trap) {
1260 Trap::new(typed_token(keyword), value).into()
1261 } else {
1262 unreachable!("statement actions are assigned only to statement keywords")
1263 }
1264 }
1265}
1266
1267fn lower_atom(token: SignificantToken) -> Result<Expr, NativeParseError> {
1268 match token.token {
1269 TokenTree::Ident(raw) => Ok(typed_terminal(
1270 Symbol::new(raw.text(), raw.expect_span()),
1271 token.trailing_trivia,
1272 )
1273 .into()),
1274 TokenTree::Literal(raw) => {
1275 let span = raw.expect_span();
1276 Ok(match raw.kind {
1277 LiteralKind::Integer => {
1278 typed_terminal(IntegerLiteral::new(raw.text(), span), token.trailing_trivia)
1279 .into()
1280 }
1281 LiteralKind::Float => {
1282 typed_terminal(FloatLiteral::new(raw.text(), span), token.trailing_trivia)
1283 .into()
1284 }
1285 LiteralKind::String => {
1286 lower_string_literal(raw.text(), span, token.trailing_trivia)
1287 }
1288 LiteralKind::RawString => {
1289 lower_raw_string_literal(raw.text(), span, token.trailing_trivia)
1290 }
1291 })
1292 }
1293 token => Err(unexpected!(token, "an expression")),
1294 }
1295}
1296
1297enum BinaryLeft {
1299 Expression(Expr),
1300 Assignment {
1301 target: AssignmentTarget,
1302 local: bool,
1303 },
1304 Lambda(LambdaParameters),
1305}
1306
1307impl BinaryLeft {
1308 fn prepare(left: Expr, operator: &TokenTree) -> Result<Self, NativeParseError> {
1309 let span = operator.expect_span();
1310 Ok(match operator.spelling() {
1311 Some("=") => Self::Assignment {
1312 target: AssignmentTarget::parse(left, false, span)?,
1313 local: false,
1314 },
1315 Some(":=") => Self::Assignment {
1316 target: AssignmentTarget::parse(left, true, span)?,
1317 local: true,
1318 },
1319 Some("->") => Self::Lambda(
1320 lambda_parameters(left)
1321 .ok_or(NativeParseError::InvalidLambdaParameters { span })?,
1322 ),
1323 _ => Self::Expression(left),
1324 })
1325 }
1326}
1327
1328enum AssignmentTarget {
1330 Symbol(Symbol),
1331 Operator(OperatorExpr),
1332 New(NewStatement),
1333 Pack(AssignmentPack),
1334}
1335
1336impl AssignmentTarget {
1337 fn parse(expression: Expr, local: bool, span: Span) -> Result<Self, NativeParseError> {
1338 match expression {
1339 Expr::Symbol(variable) => Ok(Self::Symbol(variable)),
1340 Expr::OperatorExpr(expression) => Ok(Self::Operator(expression)),
1341 Expr::NewStatement(statement) if local => Ok(Self::New(statement)),
1342 expression => assignment_pack(expression)
1343 .map(Self::Pack)
1344 .ok_or(NativeParseError::InvalidAssignmentTarget { span }),
1345 }
1346 }
1347}
1348
1349fn lower_binary(
1350 left: BinaryLeft,
1351 operator: SignificantToken,
1352 right: Expr,
1353) -> Result<Expr, NativeParseError> {
1354 let span = operator.token.expect_span();
1355 let spelling = operator
1356 .token
1357 .spelling()
1358 .expect("binary actions are assigned only to spelled tokens");
1359 match left {
1360 BinaryLeft::Assignment { target, local } => {
1361 Ok(lower_assignment(target, operator, right, local))
1362 }
1363 BinaryLeft::Lambda(parameters) => {
1364 Ok(LambdaExpression::new(parameters, typed_token(operator), right).into())
1365 }
1366 BinaryLeft::Expression(left) if spelling == "<-" => {
1367 Ok(EvaluatedAssignment::new(left, typed_token(operator), right).into())
1368 }
1369 BinaryLeft::Expression(left) if spelling == "=>" => {
1370 Ok(OptionExpression::new(left, typed_token(operator), right).into())
1371 }
1372 BinaryLeft::Expression(left) => {
1373 let spelling = spelling.to_owned();
1374 let operator = BinaryOperator::from_token_tree_with_trivia(
1375 operator.token,
1376 operator.trailing_trivia,
1377 )
1378 .ok_or(NativeParseError::Unsupported {
1379 syntax: spelling,
1380 span,
1381 })?;
1382 Ok(BinaryExpr::new(left, operator, right).into())
1383 }
1384 }
1385}
1386
1387fn lower_assignment(
1388 target: AssignmentTarget,
1389 operator: SignificantToken,
1390 right: Expr,
1391 local: bool,
1392) -> Expr {
1393 match (local, target) {
1394 (false, AssignmentTarget::Symbol(variable)) => {
1395 GlobalBinding::new(variable, typed_token(operator), right).into()
1396 }
1397 (true, AssignmentTarget::Symbol(variable)) => {
1398 LocalBinding::new(variable, typed_token(operator), right).into()
1399 }
1400 (false, AssignmentTarget::Operator(argument_expr)) => {
1401 OperatorAssignment::new(argument_expr, typed_token(operator), right).into()
1402 }
1403 (true, AssignmentTarget::Operator(OperatorExpr::AdjacentExpr(application))) => {
1404 let (typical_value, function) = installation_value(right);
1405 MethodInstallation::new(
1406 *application.left_operand,
1407 *application.right_operand,
1408 typed_token(operator),
1409 typical_value,
1410 function,
1411 )
1412 .into()
1413 }
1414 (true, AssignmentTarget::Operator(domain_expr)) => {
1415 let (typical_value, function) = installation_value(right);
1416 OperatorInstallation::new(domain_expr, typed_token(operator), typical_value, function)
1417 .into()
1418 }
1419 (true, AssignmentTarget::New(new_statement)) => {
1420 NewInstallation::new(new_statement, typed_token(operator), right).into()
1421 }
1422 (local, AssignmentTarget::Pack(argument_pack)) => {
1423 if local {
1424 LocalParallelAssignment::new(argument_pack, typed_token(operator), right).into()
1425 } else {
1426 GlobalParallelAssignment::new(argument_pack, typed_token(operator), right).into()
1427 }
1428 }
1429 (false, AssignmentTarget::New(_)) => {
1430 unreachable!("global assignment preparation rejects new statements")
1431 }
1432 }
1433}
1434
1435pub(crate) fn installation_value(value: Expr) -> (Option<TypeAnnotation>, Expr) {
1436 match value {
1437 Expr::OptionExpression(value) => (
1438 Some(TypeAnnotation::new(*value.key, value.operator)),
1439 *value.value,
1440 ),
1441 value => (None, value),
1442 }
1443}
1444
1445fn parse_cell_stream(cells: CellStream) -> Result<SourceFile, NativeParseError> {
1446 let mut elements = Vec::new();
1447 let eof_span = cells.physical_eof();
1448 let mut comments = CommentTrivia::default();
1449 let mut cells = cells.into_iter().peekable();
1450 while let Some(mut cell) = cells.next() {
1451 if !cell.has_significant_tokens() {
1452 comments.append(CommentTrivia::take_inner(&mut cell));
1453 continue;
1454 }
1455 let eoc = cells
1456 .peek()
1457 .and_then(cell_start_span)
1458 .unwrap_or_else(|| end_span(&cell));
1459 if let Some(element) = parse_raw_cell_at(cell, eoc)? {
1460 elements.push(element);
1461 }
1462 }
1463 let mut source_file = SourceFile::new(elements, EOF::new("", eof_span));
1464 source_file.comments = comments;
1465 Ok(source_file)
1466}
1467
1468fn tokenize_for_native_parser(tokens: TokenStream) -> Result<CellStream, NativeParseError> {
1469 match tokens.to_cell_stream() {
1470 Ok(cells) => Ok(cells),
1471 Err(tokenize_error) => {
1472 let incomplete = frame_recovering(tokens).incomplete;
1473 if let Some(cell) = incomplete
1474 && let Err(parse_error) = parse_raw_cell(cell)
1475 {
1476 return Err(parse_error);
1477 }
1478 Err(NativeParseError::Tokenize(tokenize_error))
1479 }
1480 }
1481}
1482
1483pub(crate) fn parse_raw_cell(
1484 tokens: TokenStream,
1485) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1486 let eoc = end_span(&tokens);
1487 parse_raw_cell_at(tokens, eoc)
1488}
1489
1490fn parse_raw_cell_at(
1491 mut tokens: TokenStream,
1492 eoc: Span,
1493) -> Result<Option<crate::nodes::Cell>, NativeParseError> {
1494 let comments = CommentTrivia::take_from_cell(&mut tokens);
1495 let semicolon = ends_with_cell_semicolon(&tokens)
1496 .then(|| tokens.take_final_punctuation(";"))
1497 .flatten()
1498 .map(|(punctuation, trailing_trivia)| {
1499 <Token![;] as Token>::from_token_tree_with_trivia(
1500 TokenTree::Punct(punctuation),
1501 trailing_trivia,
1502 )
1503 .expect("a semicolon punctuation token lowers to Token![;]")
1504 });
1505 let mut cell = Engine::new(tokens).parse_cell(semicolon, eoc)?;
1506 if let Some(cell) = &mut cell {
1507 cell.comments = comments;
1508 }
1509 Ok(cell)
1510}
1511
1512fn cell_start_span(tokens: &TokenStream) -> Option<Span> {
1513 let token = tokens.iter().next()?;
1514 let span = token
1515 .leading_trivia()
1516 .as_slice()
1517 .first()
1518 .map_or_else(|| token.span(), Spanned::span);
1519 span.start().map(|start| span.at(start))
1520}
1521
1522impl Parse for Expr {
1523 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1524 let tokens = input.by_ref().collect::<TokenStream>();
1525 let mut engine = Engine::new(tokens);
1526 engine.skip_trivia();
1527 let value = engine
1528 .parse_required(PREC_CLOSER)
1529 .map_err(token_parse_error)?;
1530 engine.skip_trivia();
1531 match engine.peek() {
1532 Lookahead::End(_) => Ok(value),
1533 Lookahead::Token(token) => Err(TokenParseError::TrailingToken {
1534 found: token.token.description(),
1535 span: token.token.expect_span(),
1536 }),
1537 }
1538 }
1539}
1540
1541impl Parse for SourceFile {
1542 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
1543 let tokens = input.by_ref().collect();
1544 tokenize_for_native_parser(tokens)
1545 .and_then(parse_cell_stream)
1546 .map_err(token_parse_error)
1547 }
1548}
1549
1550fn token_parse_error(error: NativeParseError) -> TokenParseError {
1551 let span = error.expect_span();
1552 TokenParseError::Syntax {
1553 message: error.to_string(),
1554 span,
1555 }
1556}
1557
1558fn parsing_spelling(token: &TokenTree) -> &str {
1559 token.spelling().map_or("", canonical_word_spelling)
1560}
1561
1562fn typed_token<T: Token>(token: SignificantToken) -> T {
1563 let spelling = token.token.description();
1564 T::from_token_tree_with_trivia(token.token, token.trailing_trivia)
1565 .unwrap_or_else(|| panic!("`{spelling}` cannot be lowered to `{}`", T::SPELLING))
1566}
1567
1568fn typed_terminal<T: Terminal>(mut terminal: T, trailing_trivia: TrailingTrivia) -> T {
1569 *terminal.trailing_trivia_mut() = trailing_trivia;
1570 terminal
1571}
1572
1573fn empty_span_at(lookahead: &Span) -> Span {
1574 lookahead.subspan(0, 0)
1575}
1576
1577fn lower_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
1578 let body = &text[1..text.len() - 1];
1579 let mut elements = Vec::new();
1580 let mut content_start = 0;
1581 let mut cursor = 0;
1582
1583 while cursor < body.len() {
1584 if body.as_bytes()[cursor] != b'\\' {
1585 cursor += 1;
1586 continue;
1587 }
1588 if content_start < cursor {
1589 elements.push(StringElement::StringContent(StringContent::new(
1590 &body[content_start..cursor],
1591 span.subspan(content_start + 1, cursor + 1),
1592 )));
1593 }
1594 let escape_end = match body.as_bytes()[cursor + 1] {
1595 b'x' => cursor + 4,
1596 b'u' => cursor + 6,
1597 b'0'..=b'7' => {
1598 let mut end = cursor + 2;
1599 while end < body.len()
1600 && end < cursor + 4
1601 && body.as_bytes()[end].is_ascii_digit()
1602 && body.as_bytes()[end] < b'8'
1603 {
1604 end += 1;
1605 }
1606 end
1607 }
1608 _ => cursor + 2,
1609 };
1610 elements.push(StringElement::EscapeSequence(EscapeSequence::new(
1611 &body[cursor..escape_end],
1612 span.subspan(cursor + 1, escape_end + 1),
1613 )));
1614 cursor = escape_end;
1615 content_start = cursor;
1616 }
1617 if content_start < body.len() {
1618 elements.push(StringElement::StringContent(StringContent::new(
1619 &body[content_start..],
1620 span.subspan(content_start + 1, text.len() - 1),
1621 )));
1622 }
1623 typed_terminal(StringLiteral::new(elements, span), trailing_trivia).into()
1624}
1625
1626fn lower_raw_string_literal(text: &str, span: Span, trailing_trivia: TrailingTrivia) -> Expr {
1627 let body = &text[3..text.len() - 3];
1628 let mut elements = Vec::new();
1629 let mut content_start = 0;
1630 let mut cursor = 0;
1631
1632 while cursor + 1 < body.len() {
1633 if &body.as_bytes()[cursor..cursor + 2] != b"//" {
1634 cursor += 1;
1635 continue;
1636 }
1637 if content_start < cursor {
1638 elements.push(RawStringElement::RawStringContent(RawStringContent::new(
1639 &body[content_start..cursor],
1640 span.subspan(content_start + 3, cursor + 3),
1641 )));
1642 }
1643 elements.push(RawStringElement::EscapeSequence(EscapeSequence::new(
1644 "//",
1645 span.subspan(cursor + 3, cursor + 5),
1646 )));
1647 cursor += 2;
1648 content_start = cursor;
1649 }
1650 if content_start < body.len() {
1651 elements.push(RawStringElement::RawStringContent(RawStringContent::new(
1652 &body[content_start..],
1653 span.subspan(content_start + 3, text.len() - 3),
1654 )));
1655 }
1656 typed_terminal(RawStringLiteral::new(elements, span), trailing_trivia).into()
1657}
1658
1659fn collection_contents(expression: Expr) -> Option<(crate::Delimiter, Option<ExprPack>)> {
1660 match expression {
1661 Expr::Collection(Collection::Sequence(value)) if value.statements.is_empty() => {
1662 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
1663 }
1664 Expr::Collection(Collection::List(value)) if value.statements.is_empty() => {
1665 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
1666 }
1667 Expr::Collection(Collection::Array(value)) if value.statements.is_empty() => {
1668 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
1669 }
1670 Expr::Collection(Collection::AngleBarList(value)) if value.statements.is_empty() => {
1671 Some((DelimiterValue::delimiter(&value.delimiter), value.elements))
1672 }
1673 Expr::Holder(value) if value.muted.is_empty() => {
1674 let elements = value
1675 .value
1676 .map(|value| ExprPack::new(Punctuated::from_single(Component::Expr(value))));
1677 Some((DelimiterValue::delimiter(&value.delimiter), elements))
1678 }
1679 _ => None,
1680 }
1681}
1682
1683pub(crate) fn assignment_pack(expression: Expr) -> Option<AssignmentPack> {
1684 let (delimiter, elements) = collection_contents(expression)?;
1685 let contents = match elements {
1686 Some(elements) => Some(map_punctuated(elements.pack, assignment_pack_component)?),
1687 None => None,
1688 };
1689 Some(AssignmentPack::new(Delimited::new(delimiter, contents)))
1690}
1691
1692fn assignment_pack_component(component: Component) -> Option<AssignmentPackComponent> {
1693 match component {
1694 Component::Empty(value) => Some(AssignmentPackComponent::Empty(value)),
1695 Component::Expr(value) => match *value {
1696 Expr::Symbol(value) => Some(AssignmentPackComponent::Symbol(value)),
1697 Expr::OperatorExpr(value) => Some(AssignmentPackComponent::OperatorExpr(value)),
1698 value => assignment_pack(value).map(Into::into),
1699 },
1700 }
1701}
1702
1703fn expr_pack_symbols(elements: ExprPack) -> Option<Punctuated<Symbol>> {
1704 map_punctuated(elements.pack, |component| match component {
1705 Component::Expr(value) => match *value {
1706 Expr::Symbol(value) => Some(value),
1707 _ => None,
1708 },
1709 Component::Empty(_) => None,
1710 })
1711}
1712
1713fn map_punctuated<S, T>(
1714 values: Punctuated<S>,
1715 mut map: impl FnMut(S) -> Option<T>,
1716) -> Option<Punctuated<T>> {
1717 let (first, rest) = values.into_parts();
1718 let first = map(first)?;
1719 let rest = rest
1720 .into_iter()
1721 .map(|(punctuation, value)| Some((punctuation, map(value)?)))
1722 .collect::<Option<Vec<_>>>()?;
1723 Some(Punctuated::new(first, rest))
1724}
1725
1726pub(crate) fn lambda_parameters(expression: Expr) -> Option<LambdaParameters> {
1727 match expression {
1728 Expr::Symbol(value) => Some(LambdaParameters::Variadic(Variadic::new(value))),
1729 expression => {
1730 let (delimiter, elements) = collection_contents(expression)?;
1731 let parameters = match elements {
1732 Some(elements) => Some(expr_pack_symbols(elements)?),
1733 None => None,
1734 };
1735 Some(LambdaParameters::FixedArity(FixedArity::new(
1736 Delimited::new(delimiter, parameters),
1737 )))
1738 }
1739 }
1740}
1741
1742fn token_parse_rule(spelling: &str) -> Option<TokenParseRule> {
1744 TOKEN_PARSE_RULES
1745 .binary_search_by_key(&spelling, |(declared, _)| *declared)
1746 .ok()
1747 .map(|index| TOKEN_PARSE_RULES[index].1)
1748}
1749
1750fn keyword_action(spelling: &str) -> Option<UnaryAction> {
1751 Some(match spelling {
1752 "break" | "continue" | "return" | "catch" | "throw" | "trap" => UnaryAction::Statement,
1753 "if" | "while" | "try" | "for" | "new" => UnaryAction::Control,
1754 "TEST" | "time" | "timing" | "elapsedTime" | "elapsedTiming" | "breakpoint" | "profile"
1755 | "shield" | "step" | "finish" => UnaryAction::Debug,
1756 "symbol" | "global" | "local" | "threadLocal" | "threadVariable" => UnaryAction::Quote,
1757 _ => return None,
1758 })
1759}
1760
1761fn parse_info(token: &TokenTree) -> ParseInfo {
1762 if matches!(token, TokenTree::Punct(punctuation) if punctuation.text().is_empty()) {
1763 return ParseInfo::binary(PREC_APPLICATION, PREC_APPLICATION_RIGHT);
1764 }
1765 if let TokenTree::Group(group) = token {
1766 return match group.delim_kind() {
1767 DelimiterKind::Bracket | DelimiterKind::AngleBar => {
1768 ParseInfo::delimiter(PREC_COLLECTION)
1769 }
1770 DelimiterKind::Parenthesis | DelimiterKind::Brace => {
1771 ParseInfo::delimiter(PREC_APPLICATION)
1772 }
1773 };
1774 }
1775
1776 let text = parsing_spelling(token);
1777 if let Some(rule) = token_parse_rule(text) {
1778 let mut info = ParseInfo::from(rule);
1779 if let Some(action) = keyword_action(text) {
1780 info.unary = action;
1781 }
1782 return info;
1783 }
1784
1785 match token {
1786 TokenTree::Ident(_) | TokenTree::Literal(_) => ParseInfo::atom(PREC_APPLICATION),
1787 _ => ParseInfo::stop(PREC_APPLICATION),
1788 }
1789}
1790
1791#[cfg(test)]
1792mod tests {
1793 use super::{NativeCellParser, NativeCellState};
1794 use crate::cell_stream::frame_recovering;
1795 use crate::{Spanned, lex_str};
1796
1797 #[test]
1801 fn cells_use_operator_clause_and_delimiter_state() {
1802 fn cells(source: &str) -> usize {
1803 let framed = frame_recovering(lex_str(source).unwrap());
1804 framed.cells.len() + usize::from(framed.incomplete.is_some())
1805 }
1806
1807 assert_eq!(cells("1\n2"), 2);
1808 assert_eq!(cells("1 +\n2"), 1);
1809 assert_eq!(cells("not\n1"), 1);
1810 assert_eq!(cells("1!\n2"), 2);
1811 assert_eq!(cells("if condition\nthen value"), 1);
1812 assert_eq!(cells("if condition\nthen value\nnext"), 2);
1813 assert_eq!(cells("symbol if\nnext"), 2);
1814 assert_eq!(cells("symbol +\nnext"), 2);
1815 assert_eq!(cells("1 -* comment\n*- 2"), 2);
1816 assert_eq!(cells("1 + -* comment\n*- 2"), 1);
1817 assert_eq!(cells("1;2"), 2);
1818 assert_eq!(cells("(1\n2;3)"), 1);
1821 assert_eq!(cells("symbol ;"), 1);
1823 }
1824
1825 #[test]
1826 fn invalid_binary_left_side_wins_over_a_missing_right_operand() {
1827 for (source, state, diagnostic, diagnostic_text) in [
1828 (
1829 "1 + 1 =",
1830 NativeCellState::Incomplete,
1831 "expected an operand after `=`, found end of input",
1832 "=",
1833 ),
1834 (
1835 "2 =",
1836 NativeCellState::Invalid,
1837 "invalid assignment target",
1838 "=",
1839 ),
1840 (
1841 "(x, y) ->",
1842 NativeCellState::Incomplete,
1843 "expected an operand after `->`, found end of input",
1844 "->",
1845 ),
1846 (
1847 "(x + y) ->",
1848 NativeCellState::Invalid,
1849 "invalid lambda parameter list",
1850 "->",
1851 ),
1852 ] {
1853 let mut parser = NativeCellParser::new();
1854 assert_eq!(parser.push_line(source), state, "source: `{source}`");
1855 let error = parser
1856 .parse_error()
1857 .unwrap_or_else(|| panic!("expected a diagnostic for `{source}`"));
1858 assert_eq!(error.to_string(), diagnostic, "source: `{source}`");
1859 assert_eq!(error.span().text(), Some(diagnostic_text));
1860 }
1861 }
1862}