1use std::error::Error;
38use std::fmt::{Display, Formatter, Result as FmtResult};
39use std::mem::take;
40use std::ops::Deref;
41use std::slice::Iter;
42use std::sync::Arc;
43use std::vec::IntoIter;
44
45use crate::lexer::{canonical_word_spelling, is_quote_specifier, newline_ends_cell};
46use crate::token_stream::TokenStreamParts;
47use crate::{
48 Delimiter, DelimiterKind, IdentToken, LeadingTrivia, Lex, LiteralToken, Punct, Source, Span,
49 Spanned, TOKEN_PARSE_RULES, Terminal, TokenGroup, TokenParseRule, TokenStream, TokenTree,
50 TrailingTrivia, Trivia,
51};
52
53#[derive(Debug, Clone, Default)]
54struct CellTokenStreamData {
56 trees: Vec<CellTokenTree>,
58 prefix: TrailingTrivia,
60 suffix: LeadingTrivia,
62 source: Option<Arc<Source>>,
64}
65
66impl PartialEq for CellTokenStreamData {
67 fn eq(&self, other: &Self) -> bool {
68 self.trees == other.trees
69 && self.prefix == other.prefix
70 && self.suffix == other.suffix
71 && match (&self.source, &other.source) {
72 (Some(left), Some(right)) => Arc::ptr_eq(left, right),
73 (None, None) => true,
74 _ => false,
75 }
76 }
77}
78
79impl Eq for CellTokenStreamData {}
80
81#[derive(Debug, Clone, PartialEq, Eq)]
82pub enum CellTokenTree {
88 Group(CellTokenGroup),
90 Literal(LiteralToken),
92 Punct(Punct),
94 Ident(IdentToken),
96 Adj(Span),
98}
99
100impl CellTokenTree {
101 pub fn spelling(&self) -> Option<&str> {
103 match self {
104 Self::Group(_) => None,
105 Self::Literal(token) => Some(token.text()),
106 Self::Punct(token) => Some(token.text()),
107 Self::Ident(token) => Some(token.text()),
108 Self::Adj(_) => Some(""),
109 }
110 }
111
112 pub fn leading_trivia(&self) -> &[Trivia] {
114 match self {
115 Self::Group(token) => token.leading_trivia().as_slice(),
116 Self::Literal(token) => token.leading_trivia().as_slice(),
117 Self::Punct(token) => token.leading_trivia().as_slice(),
118 Self::Ident(token) => token.leading_trivia().as_slice(),
119 Self::Adj(_) => &[],
120 }
121 }
122
123 pub fn trailing_trivia(&self) -> &[Trivia] {
125 match self {
126 Self::Group(token) => token.trailing_trivia().as_slice(),
127 Self::Literal(token) => token.trailing_trivia().as_slice(),
128 Self::Punct(token) => token.trailing_trivia().as_slice(),
129 Self::Ident(token) => token.trailing_trivia().as_slice(),
130 Self::Adj(_) => &[],
131 }
132 }
133
134 fn from_augmented(tree: TokenTree) -> Self {
136 match tree {
137 TokenTree::Group(group) => Self::Group(CellTokenGroup::from_augmented(group)),
138 TokenTree::Literal(token) => Self::Literal(token),
139 TokenTree::Punct(token) if token.text().is_empty() => Self::Adj(token.expect_span()),
140 TokenTree::Punct(token) => Self::Punct(token),
141 TokenTree::Ident(token) => Self::Ident(token),
142 }
143 }
144
145 fn into_lexical(self) -> Option<TokenTree> {
147 match self {
148 Self::Group(group) => Some(TokenTree::Group(group.into_lexical())),
149 Self::Literal(token) => Some(TokenTree::Literal(token)),
150 Self::Punct(token) => Some(TokenTree::Punct(token)),
151 Self::Ident(token) => Some(TokenTree::Ident(token)),
152 Self::Adj(_) => None,
153 }
154 }
155
156 fn into_parser_token(self) -> TokenTree {
158 match self {
159 Self::Group(group) => TokenTree::Group(group.into_parser_group()),
160 Self::Literal(token) => TokenTree::Literal(token),
161 Self::Punct(token) => TokenTree::Punct(token),
162 Self::Ident(token) => TokenTree::Ident(token),
163 Self::Adj(span) => TokenTree::Punct(Punct::from_span(span)),
164 }
165 }
166}
167
168impl Spanned for CellTokenTree {
169 fn try_span(&self) -> Option<Span> {
170 match self {
171 Self::Group(token) => token.try_span(),
172 Self::Literal(token) => token.try_span(),
173 Self::Punct(token) => token.try_span(),
174 Self::Ident(token) => token.try_span(),
175 Self::Adj(span) => Some(span.clone()),
176 }
177 }
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct CellTokenGroup {
183 delimiter: Delimiter,
185 stream: CellTokenStream,
187 leading_trivia: LeadingTrivia,
189 trailing_trivia: TrailingTrivia,
191}
192
193impl CellTokenGroup {
194 pub fn delimiter(&self) -> &Delimiter {
196 &self.delimiter
197 }
198
199 pub fn delim_kind(&self) -> DelimiterKind {
201 self.delimiter.kind
202 }
203
204 pub fn stream(&self) -> &CellTokenStream {
206 &self.stream
207 }
208
209 pub fn into_stream(self) -> CellTokenStream {
211 self.stream
212 }
213
214 fn from_augmented(group: TokenGroup) -> Self {
216 let (delimiter, stream, leading_trivia, trailing_trivia) = group.into_parts();
217 Self {
218 delimiter,
219 stream: CellTokenStream::from_augmented(stream),
220 leading_trivia,
221 trailing_trivia,
222 }
223 }
224
225 fn into_lexical(self) -> TokenGroup {
227 TokenGroup::from_parts(
228 self.delimiter,
229 self.stream.into_token_stream(),
230 self.leading_trivia,
231 self.trailing_trivia,
232 )
233 }
234
235 fn into_parser_group(self) -> TokenGroup {
237 TokenGroup::from_parts(
238 self.delimiter,
239 self.stream.into_parser_token_stream(),
240 self.leading_trivia,
241 self.trailing_trivia,
242 )
243 }
244}
245
246impl Spanned for CellTokenGroup {
247 fn try_span(&self) -> Option<Span> {
248 self.delimiter.try_span()
249 }
250}
251
252impl Terminal for CellTokenGroup {
253 fn leading_trivia(&self) -> &LeadingTrivia {
254 &self.leading_trivia
255 }
256
257 fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia {
258 &mut self.leading_trivia
259 }
260
261 fn trailing_trivia(&self) -> &TrailingTrivia {
262 &self.trailing_trivia
263 }
264
265 fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia {
266 &mut self.trailing_trivia
267 }
268}
269
270#[derive(Debug, Clone, Default, PartialEq, Eq)]
271pub struct CellTokenStream(Arc<CellTokenStreamData>);
282
283impl CellTokenStream {
284 pub fn fork(&self) -> Self {
288 self.clone()
289 }
290
291 pub fn into_token_stream(self) -> TokenStream {
296 let CellTokenStreamData {
297 trees,
298 prefix,
299 suffix,
300 source,
301 } = self.into_data();
302 TokenStream::from_parts(TokenStreamParts {
303 trees: trees
304 .into_iter()
305 .filter_map(CellTokenTree::into_lexical)
306 .collect(),
307 prefix,
308 suffix,
309 source,
310 })
311 }
312
313 pub fn to_token_stream(&self) -> TokenStream {
317 self.clone().into_token_stream()
318 }
319
320 fn data(&self) -> &CellTokenStreamData {
322 &self.0
323 }
324
325 fn into_data(self) -> CellTokenStreamData {
327 Arc::try_unwrap(self.0).unwrap_or_else(|data| (*data).clone())
328 }
329
330 pub(crate) fn from_augmented(tokens: TokenStream) -> Self {
332 let TokenStreamParts {
333 trees,
334 prefix,
335 suffix,
336 source,
337 } = tokens.into_parts();
338 Self(Arc::new(CellTokenStreamData {
339 trees: trees
340 .into_iter()
341 .map(CellTokenTree::from_augmented)
342 .collect(),
343 prefix,
344 suffix,
345 source,
346 }))
347 }
348
349 pub(crate) fn source(&self) -> Option<Arc<Source>> {
351 self.data().source.clone().or_else(|| {
352 self.iter()
353 .find_map(Spanned::try_span)
354 .map(|span| Arc::clone(span.source()))
355 })
356 }
357
358 #[cfg(test)]
359 pub(crate) fn shares_storage(&self, other: &Self) -> bool {
360 Arc::ptr_eq(&self.0, &other.0)
361 }
362
363 pub(crate) fn into_parser_token_stream(self) -> TokenStream {
368 let CellTokenStreamData {
369 trees,
370 prefix,
371 suffix,
372 source,
373 } = self.into_data();
374 let mut tokens = TokenStream::from_parts(TokenStreamParts {
375 trees: trees
376 .into_iter()
377 .map(CellTokenTree::into_parser_token)
378 .collect(),
379 prefix,
380 suffix,
381 source,
382 });
383 tokens.settle_trivia();
384 tokens
385 }
386
387 pub(crate) fn from_framed_cells(cells: impl IntoIterator<Item = CellTokenStream>) -> Self {
389 let mut tokens = TokenStream::new();
390 for cell in cells {
391 tokens.extend([cell.into_parser_token_stream()]);
392 }
393 Self::from_augmented(tokens)
394 }
395}
396
397impl Deref for CellTokenStream {
398 type Target = [CellTokenTree];
399
400 fn deref(&self) -> &Self::Target {
401 &self.data().trees
402 }
403}
404
405impl AsRef<[CellTokenTree]> for CellTokenStream {
406 fn as_ref(&self) -> &[CellTokenTree] {
407 self
408 }
409}
410
411impl Spanned for CellTokenStream {
412 fn try_span(&self) -> Option<Span> {
413 Span::join_all(
414 self.data()
415 .prefix
416 .try_span()
417 .into_iter()
418 .chain(self.iter().filter_map(Spanned::try_span))
419 .chain(self.data().suffix.try_span()),
420 )
421 }
422}
423
424impl Display for CellTokenStream {
425 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
426 self.to_token_stream().fmt(formatter)
427 }
428}
429
430impl IntoIterator for CellTokenStream {
431 type Item = CellTokenTree;
432 type IntoIter = IntoIter<CellTokenTree>;
433
434 fn into_iter(self) -> Self::IntoIter {
435 self.into_data().trees.into_iter()
436 }
437}
438
439impl<'syntax> IntoIterator for &'syntax CellTokenStream {
440 type Item = &'syntax CellTokenTree;
441 type IntoIter = Iter<'syntax, CellTokenTree>;
442
443 fn into_iter(self) -> Self::IntoIter {
444 self.iter()
445 }
446}
447
448#[derive(Debug, Clone, Default)]
449struct CellStreamData {
450 cells: Vec<CellTokenStream>,
451 source: Option<Arc<Source>>,
452 bof: Option<Span>,
454 eof: Option<Span>,
456}
457
458#[derive(Debug, Clone, Default)]
459pub struct CellStream(Arc<CellStreamData>);
471
472impl PartialEq for CellStream {
473 fn eq(&self, other: &Self) -> bool {
474 self.as_ref() == other.as_ref()
475 }
476}
477
478impl Eq for CellStream {}
479
480impl Deref for CellStream {
481 type Target = [CellTokenStream];
482
483 fn deref(&self) -> &Self::Target {
484 &self.data().cells
485 }
486}
487
488impl AsRef<[CellTokenStream]> for CellStream {
489 fn as_ref(&self) -> &[CellTokenStream] {
490 self
491 }
492}
493
494impl CellStream {
495 pub fn new(tokens: TokenStream) -> Result<Self, CellStreamError> {
508 let source = tokens.source();
509 let bof = leading_layout_span(source.as_ref());
510 let eof = trailing_layout_span(source.as_ref());
511 let FramedCells { cells, incomplete } = frame_recovering(tokens);
512 match incomplete {
513 Some(tokens) => Err(CellStreamError {
514 span: end_span(&tokens),
515 }),
516 None => Ok(Self(Arc::new(CellStreamData {
517 cells,
518 source,
519 bof,
520 eof,
521 }))),
522 }
523 }
524
525 pub fn from_cells(cells: impl IntoIterator<Item = CellTokenStream>) -> Self {
531 Self::from_cells_with_source(cells, None)
532 }
533
534 pub(crate) fn from_cells_with_source(
536 cells: impl IntoIterator<Item = CellTokenStream>,
537 source: Option<Arc<Source>>,
538 ) -> Self {
539 Self(Arc::new(CellStreamData {
540 cells: cells.into_iter().collect(),
541 bof: leading_layout_span(source.as_ref()),
542 eof: trailing_layout_span(source.as_ref()),
543 source,
544 }))
545 }
546
547 pub fn fork(&self) -> Self {
554 self.clone()
555 }
556
557 fn data(&self) -> &CellStreamData {
559 &self.0
560 }
561
562 fn data_mut(&mut self) -> &mut CellStreamData {
564 Arc::make_mut(&mut self.0)
565 }
566
567 fn into_data(self) -> CellStreamData {
569 Arc::try_unwrap(self.0).unwrap_or_else(|data| (*data).clone())
570 }
571
572 pub fn into_token_stream(self) -> TokenStream {
578 let source = self.complete_source();
579 let mut tokens = flatten_cells(self.into_data().cells);
580 if let Some(source) = source {
581 tokens.set_source(source);
582 }
583 tokens
584 }
585
586 pub fn to_token_stream(&self) -> TokenStream {
591 let mut tokens = flatten_cells(self.iter().cloned());
592 if let Some(source) = self.complete_source() {
593 tokens.set_source(source);
594 }
595 tokens
596 }
597
598 pub(crate) fn complete_source(&self) -> Option<Arc<Source>> {
600 let source = self.data().source.as_ref()?;
601 let mut cursor = 0;
602 for cell in self {
603 if !covers_stream(cell, source, &mut cursor) {
604 return None;
605 }
606 }
607 source.text()[cursor..]
608 .bytes()
609 .all(|byte| byte.is_ascii_whitespace())
610 .then(|| Arc::clone(source))
611 }
612
613 pub(crate) fn physical_bof(&self) -> Span {
620 if let Some(source) = self.complete_source() {
621 let leading = source.leading_whitespace();
622 return Span::ranged(Arc::clone(&source), leading);
623 }
624 self.first()
625 .and_then(cell_first_span)
626 .and_then(|span| span.start().map(|start| span.at(start)))
627 .unwrap_or_else(|| Span::for_text(""))
628 }
629
630 pub(crate) fn physical_eof(&self) -> Span {
637 if let Some(source) = self.complete_source() {
638 let trailing = source.trailing_whitespace();
639 return Span::ranged(Arc::clone(&source), trailing);
640 }
641 self.last().map_or_else(|| Span::for_text(""), end_span)
642 }
643
644 pub(crate) fn from_source_file(source_file: &crate::SourceFile) -> Self {
646 let mut cells = source_file
647 .cells
648 .iter()
649 .map(Lex::to_token_stream)
650 .collect::<Vec<_>>();
651 for (index, comments) in [
652 (0, &source_file.leading_trivia),
653 (cells.len(), source_file.eof.leading_trivia()),
654 ]
655 .into_iter()
656 .rev()
657 {
658 if !comments.is_empty() {
659 let mut comment_cell = TokenStream::new();
660 comment_cell.extend(comments.as_slice().iter().cloned());
661 cells.insert(index, comment_cell);
662 }
663 }
664 Self(Arc::new(CellStreamData {
665 cells: cells
666 .into_iter()
667 .map(CellTokenStream::from_augmented)
668 .collect(),
669 source: None,
670 bof: source_file.bof.try_span(),
671 eof: source_file.eof.try_span(),
672 }))
673 }
674}
675
676fn covers_stream(stream: &CellTokenStream, source: &Arc<Source>, cursor: &mut usize) -> bool {
678 for trivia in stream.data().prefix.as_slice() {
679 if !covers_span(trivia.span(), source, cursor) {
680 return false;
681 }
682 }
683 for token in stream.iter() {
684 for trivia in token.leading_trivia() {
685 if !covers_span(trivia.span(), source, cursor) {
686 return false;
687 }
688 }
689 let covered = match token {
690 CellTokenTree::Group(group) => {
691 covers_span(group.delimiter().opening_span(), source, cursor)
692 && covers_stream(group.stream(), source, cursor)
693 && group
694 .delimiter()
695 .closing_span()
696 .is_none_or(|span| covers_span(span, source, cursor))
697 }
698 _ => covers_span(token.span(), source, cursor),
699 };
700 if !covered {
701 return false;
702 }
703 for trivia in token.trailing_trivia() {
704 if !covers_span(trivia.span(), source, cursor) {
705 return false;
706 }
707 }
708 }
709 stream
710 .data()
711 .suffix
712 .as_slice()
713 .iter()
714 .all(|trivia| covers_span(trivia.span(), source, cursor))
715}
716
717fn covers_span(span: Span, source: &Arc<Source>, cursor: &mut usize) -> bool {
719 if !Arc::ptr_eq(span.source(), source) {
720 return false;
721 }
722 let (Some(start), Some(end)) = (span.start(), span.end()) else {
723 return false;
724 };
725 if start == end {
726 return start >= *cursor;
727 }
728 if start < *cursor
729 || !source.text()[*cursor..start]
730 .bytes()
731 .all(|byte| byte.is_ascii_whitespace())
732 {
733 return false;
734 }
735 *cursor = end;
736 true
737}
738
739impl Display for CellStream {
740 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
741 write_leading_layout(
742 formatter,
743 self.data().bof.as_ref(),
744 self.first().and_then(cell_first_span).as_ref(),
745 )?;
746 let mut previous: Option<Span> = None;
747 for (index, cell) in self.iter().enumerate() {
748 if index != 0 {
749 let next = cell_first_span(cell);
750 let mut recovered = false;
751 if let Some((left, right)) = previous.as_ref().zip(next.as_ref())
752 && left.shares_source(right)
753 && let (Some(end), Some(start)) = (left.end(), right.start())
754 && end <= start
755 {
756 let gap = &left.source().text()[end..start];
757 let written = !gap.is_empty() || !left.source().file().is_synthetic();
760 if written && gap.bytes().all(|byte| byte.is_ascii_whitespace()) {
761 formatter.write_str(gap)?;
762 recovered = true;
763 }
764 }
765 if !recovered {
766 formatter.write_str("\n")?;
767 }
768 }
769 cell.fmt(formatter)?;
770 previous = cell_last_span(cell);
771 }
772 write_trailing_layout(formatter, self.data().eof.as_ref(), previous.as_ref())
773 }
774}
775
776fn leading_layout_span(source: Option<&Arc<Source>>) -> Option<Span> {
778 source.map(|source| Span::ranged(Arc::clone(source), source.leading_whitespace()))
779}
780
781fn write_leading_layout(
788 formatter: &mut Formatter<'_>,
789 bof: Option<&Span>,
790 first_cell: Option<&Span>,
791) -> FmtResult {
792 let (Some(bof), Some(first)) = (bof, first_cell) else {
793 return Ok(());
794 };
795 if !first.shares_source(bof) {
796 return Ok(());
797 }
798 let Some((start, stop)) = bof.start().zip(first.start()) else {
799 return Ok(());
800 };
801 match bof.source().text().get(start..stop) {
802 Some(prefix) if prefix.bytes().all(|byte| byte.is_ascii_whitespace()) => {
803 formatter.write_str(prefix)
804 }
805 _ => Ok(()),
806 }
807}
808
809fn trailing_layout_span(source: Option<&Arc<Source>>) -> Option<Span> {
811 source.map(|source| Span::ranged(Arc::clone(source), source.trailing_whitespace()))
812}
813
814fn write_trailing_layout(
820 formatter: &mut Formatter<'_>,
821 eof: Option<&Span>,
822 last_cell: Option<&Span>,
823) -> FmtResult {
824 let Some(eof) = eof else {
825 return Ok(());
826 };
827 let resume = match last_cell {
828 Some(last) if last.shares_source(eof) => last.end(),
829 Some(_) => return Ok(()),
830 None => eof.start(),
831 };
832 let Some((resume, stop)) = resume.zip(eof.end()) else {
833 return Ok(());
834 };
835 match eof.source().text().get(resume..stop) {
836 Some(suffix) if suffix.bytes().all(|byte| byte.is_ascii_whitespace()) => {
837 formatter.write_str(suffix)
838 }
839 _ => Ok(()),
840 }
841}
842
843fn cell_first_span(tokens: &CellTokenStream) -> Option<Span> {
845 tokens
846 .data()
847 .prefix
848 .as_slice()
849 .first()
850 .map(Spanned::span)
851 .or_else(|| {
852 tokens.iter().next().map(|token| {
853 token
854 .leading_trivia()
855 .first()
856 .map_or_else(|| token.span(), Spanned::span)
857 })
858 })
859 .or_else(|| tokens.data().suffix.as_slice().first().map(Spanned::span))
860}
861
862fn cell_last_span(tokens: &CellTokenStream) -> Option<Span> {
864 tokens
865 .data()
866 .suffix
867 .as_slice()
868 .last()
869 .map(Spanned::span)
870 .or_else(|| tokens.iter().next_back().map(token_end_span))
871 .or_else(|| tokens.data().prefix.as_slice().last().map(Spanned::span))
872}
873
874impl IntoIterator for CellStream {
875 type Item = CellTokenStream;
876 type IntoIter = IntoIter<CellTokenStream>;
877
878 fn into_iter(self) -> Self::IntoIter {
879 self.into_data().cells.into_iter()
880 }
881}
882
883impl<'syntax> IntoIterator for &'syntax CellStream {
884 type Item = &'syntax CellTokenStream;
885 type IntoIter = Iter<'syntax, CellTokenStream>;
886
887 fn into_iter(self) -> Self::IntoIter {
888 self.iter()
889 }
890}
891
892impl FromIterator<CellTokenStream> for CellStream {
893 fn from_iter<T: IntoIterator<Item = CellTokenStream>>(iter: T) -> Self {
894 Self::from_cells(iter)
895 }
896}
897
898fn flatten_cells(cells: impl IntoIterator<Item = CellTokenStream>) -> TokenStream {
900 let mut output = TokenStream::new();
901 for cell in cells {
902 output.extend([cell.into_token_stream()]);
903 }
904 output
905}
906
907#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
908pub struct CellStreamError {
914 span: Span,
916}
917
918impl Display for CellStreamError {
919 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
920 formatter.write_str("input ends inside an incomplete cell")
921 }
922}
923
924impl Error for CellStreamError {}
925
926pub trait Tokenize {
952 fn tokenize(&self, output: &mut CellStream) -> Result<(), CellStreamError>;
959
960 fn to_cell_stream(&self) -> Result<CellStream, CellStreamError> {
969 let mut output = CellStream::default();
970 self.tokenize(&mut output)?;
971 Ok(output)
972 }
973}
974
975impl Tokenize for TokenStream {
976 fn tokenize(&self, output: &mut CellStream) -> Result<(), CellStreamError> {
977 let tokenized = CellStream::new(self.clone())?.into_data();
978 let output = output.data_mut();
979 if output.cells.is_empty() {
980 output.source = tokenized.source;
981 output.bof = tokenized.bof;
982 output.eof = tokenized.eof;
983 } else {
984 output.source = None;
985 output.eof = None;
986 }
987 output.cells.extend(tokenized.cells);
988 Ok(())
989 }
990}
991
992impl crate::SourceFile {
993 pub(crate) fn set_closing_comments(&mut self, comments: Vec<Trivia>) {
996 if self.cells.is_empty() {
997 self.leading_trivia = LeadingTrivia::new(comments);
998 } else {
999 self.eof.set_leading_trivia(comments);
1000 }
1001 }
1002}
1003
1004impl Tokenize for crate::SourceFile {
1005 fn tokenize(&self, output: &mut CellStream) -> Result<(), CellStreamError> {
1006 let tokenized = CellStream::from_source_file(self).into_data();
1007 let output = output.data_mut();
1008 if output.cells.is_empty() {
1009 output.bof = tokenized.bof;
1010 }
1011 output.eof = output.cells.is_empty().then_some(tokenized.eof).flatten();
1012 output.cells.extend(tokenized.cells);
1013 output.source = None;
1014 Ok(())
1015 }
1016}
1017
1018impl Tokenize for crate::ParsedFile {
1019 fn tokenize(&self, output: &mut CellStream) -> Result<(), CellStreamError> {
1020 self.cst().tokenize(output)
1021 }
1022}
1023
1024impl<T: Tokenize + ?Sized> Tokenize for &T {
1025 fn tokenize(&self, output: &mut CellStream) -> Result<(), CellStreamError> {
1026 (*self).tokenize(output)
1027 }
1028}
1029
1030pub(crate) struct FramedCells {
1036 pub(crate) cells: Vec<CellTokenStream>,
1038 pub(crate) incomplete: Option<CellTokenStream>,
1040}
1041
1042pub(crate) fn frame_recovering(tokens: TokenStream) -> FramedCells {
1056 let mut tokens = tokens;
1057 let prefix_trivia = tokens.take_prefix_trivia();
1060 let suffix_trivia = tokens.take_suffix_trivia();
1061 let mut cells = Vec::new();
1062 let mut current = TokenStream::new();
1063 current.extend(prefix_trivia.into_vec());
1064 let mut pending_boundary = false;
1065 let mut quote_next = false;
1066
1067 for token in tokens {
1068 if pending_boundary {
1071 cells.push(insert_adjacency(take(&mut current)));
1072 pending_boundary = false;
1073 quote_next = false;
1074 } else if current
1075 .last()
1076 .is_some_and(|left| tokens_cross_line_break(left, &token))
1077 && newline_ends_cell(¤t)
1078 {
1079 cells.push(insert_adjacency(take(&mut current)));
1080 quote_next = false;
1081 }
1082
1083 let quoted = take(&mut quote_next);
1084 let quotes_next = !quoted
1085 && matches!(&token, TokenTree::Ident(identifier)
1086 if is_quote_specifier(canonical_word_spelling(identifier.text())));
1087 let semicolon = !quoted && token.spelling() == Some(";");
1088
1089 current.extend([token]);
1090 if semicolon {
1091 pending_boundary = true;
1092 }
1093 if quotes_next {
1094 quote_next = true;
1095 }
1096 }
1097
1098 current.extend(suffix_trivia.into_vec());
1099
1100 if pending_boundary {
1103 cells.push(insert_adjacency(current));
1104 return FramedCells {
1105 cells,
1106 incomplete: None,
1107 };
1108 }
1109
1110 if !has_syntax(¤t) {
1113 if current.has_trivia() {
1114 cells.push(CellTokenStream::from_augmented(current));
1115 }
1116 return FramedCells {
1117 cells,
1118 incomplete: None,
1119 };
1120 }
1121
1122 if !ends_in_incomplete_group(¤t) && newline_ends_cell(¤t) {
1125 cells.push(insert_adjacency(current));
1126 FramedCells {
1127 cells,
1128 incomplete: None,
1129 }
1130 } else {
1131 FramedCells {
1132 cells,
1133 incomplete: Some(insert_adjacency(current)),
1134 }
1135 }
1136}
1137
1138pub(crate) fn end_span(tokens: &CellTokenStream) -> Span {
1140 let ends_with_semicolon = ends_with_cell_semicolon(tokens);
1141 let span = tokens
1142 .iter()
1143 .next_back()
1144 .map(token_end_span)
1145 .or_else(|| tokens.data().suffix.as_slice().last().map(Spanned::span))
1146 .or_else(|| tokens.data().prefix.as_slice().last().map(Spanned::span));
1147 let Some(span) = span else {
1148 return Span::for_text("");
1149 };
1150 let Some(end) = span.end() else {
1151 return Span::unlocated(Arc::clone(span.source()));
1152 };
1153 if !ends_with_semicolon && let Some(newline) = span.source().text()[end..].find('\n') {
1154 return span.at(end + newline + 1);
1155 }
1156 span.at(end)
1157}
1158
1159fn token_end_span(token: &CellTokenTree) -> Span {
1161 if let Some(trivia) = token.trailing_trivia().last() {
1162 return trivia.span();
1163 }
1164 if let CellTokenTree::Group(group) = token
1165 && !group.delimiter().is_closed()
1166 {
1167 let contents = group.stream();
1168 if let Some(inner) = contents.iter().next_back() {
1169 return token_end_span(inner);
1170 }
1171 if let Some(trivia) = contents
1172 .data()
1173 .suffix
1174 .as_slice()
1175 .last()
1176 .or_else(|| contents.data().prefix.as_slice().last())
1177 {
1178 return trivia.span();
1179 }
1180 }
1181 token.span()
1182}
1183
1184pub(crate) fn ends_with_cell_semicolon(tokens: &CellTokenStream) -> bool {
1186 let mut quote_next = false;
1187 let mut final_semicolon = false;
1188 for token in tokens.iter() {
1189 let quoted = take(&mut quote_next);
1190 final_semicolon = !quoted && token.spelling() == Some(";");
1191 quote_next = !quoted
1192 && matches!(token, CellTokenTree::Ident(identifier)
1193 if is_quote_specifier(canonical_word_spelling(identifier.text())));
1194 }
1195 final_semicolon
1196}
1197
1198fn has_syntax(stream: &TokenStream) -> bool {
1200 !stream.is_empty()
1201}
1202
1203fn ends_in_incomplete_group(stream: &TokenStream) -> bool {
1205 matches!(stream.iter().next_back(), Some(TokenTree::Group(group)) if !group.delimiter().is_closed())
1206}
1207
1208fn insert_adjacency(mut tokens: TokenStream) -> CellTokenStream {
1210 let prefix = tokens.take_prefix_trivia();
1211 let suffix = tokens.take_suffix_trivia();
1212 let mut output = TokenStream::new();
1213 output.extend(prefix.into_vec());
1214 let mut left_can_end = false;
1215 let mut quote_next = false;
1216
1217 for mut token in tokens {
1218 if let TokenTree::Group(group) = &mut token {
1219 let contents = take(group.stream_mut());
1220 *group.stream_mut() = insert_adjacency(contents).into_parser_token_stream();
1221 }
1222
1223 let quoted = take(&mut quote_next);
1224 let crossed_newline = output
1225 .last()
1226 .is_some_and(|left| tokens_cross_line_break(left, &token));
1227 if left_can_end && !quoted && !crossed_newline && can_begin_implicit_operand(&token) {
1228 let span = token.expect_span().subspan(0, 0);
1229 output.extend([TokenTree::Punct(Punct::from_span(span))]);
1230 }
1231
1232 let quotes_next = !quoted
1233 && matches!(&token, TokenTree::Ident(identifier)
1234 if is_quote_specifier(canonical_word_spelling(identifier.text())));
1235 left_can_end = quoted || can_end_operand(&token);
1236 quote_next = quotes_next;
1237 output.extend([token]);
1238 }
1239 for trivia in suffix.into_vec() {
1240 output.push_leading_trivia(trivia);
1241 }
1242 CellTokenStream::from_augmented(output)
1243}
1244
1245fn tokens_cross_line_break(left: &TokenTree, right: &TokenTree) -> bool {
1247 let left = left.expect_span();
1248 let right = right.expect_span();
1249 if !left.shares_source(&right) {
1250 return false;
1251 }
1252 let (Some(end), Some(start)) = (left.end(), right.start()) else {
1253 return false;
1254 };
1255 end <= start && left.source().text()[end..start].contains('\n')
1256}
1257
1258fn token_parse_rule(token: &TokenTree) -> Option<TokenParseRule> {
1260 let spelling = token.spelling().map(canonical_word_spelling)?;
1261 TOKEN_PARSE_RULES
1262 .binary_search_by_key(&spelling, |(declared, _)| *declared)
1263 .ok()
1264 .map(|index| TOKEN_PARSE_RULES[index].1)
1265}
1266
1267fn can_begin_implicit_operand(token: &TokenTree) -> bool {
1269 match token_parse_rule(token) {
1270 Some(TokenParseRule::Prefix(_, _) | TokenParseRule::Unary(_, _)) => true,
1271 Some(_) => false,
1272 None => matches!(
1273 token,
1274 TokenTree::Ident(_) | TokenTree::Literal(_) | TokenTree::Group(_)
1275 ),
1276 }
1277}
1278
1279fn can_end_operand(token: &TokenTree) -> bool {
1281 match token_parse_rule(token) {
1282 Some(TokenParseRule::Postfix(_)) => true,
1283 Some(_) => false,
1284 None => matches!(
1285 token,
1286 TokenTree::Ident(_) | TokenTree::Literal(_) | TokenTree::Group(_)
1287 ),
1288 }
1289}
1290
1291#[cfg(test)]
1292mod tests {
1293 use super::{Arc, CellStream};
1294 use crate::{CellTokenTree, TokenTree, Tokenize, TriviaKind, lex_str};
1295
1296 fn count_cell_adjacency(tokens: &[CellTokenTree]) -> usize {
1297 tokens
1298 .iter()
1299 .map(|token| match token {
1300 CellTokenTree::Group(group) => count_cell_adjacency(group.stream()),
1301 CellTokenTree::Adj(_) => 1,
1302 _ => 0,
1303 })
1304 .sum()
1305 }
1306
1307 fn count_raw_adjacency(tokens: &[TokenTree]) -> usize {
1308 tokens
1309 .iter()
1310 .map(|token| match token {
1311 TokenTree::Group(group) => count_raw_adjacency(group.stream()),
1312 TokenTree::Punct(punctuation) if punctuation.text().is_empty() => 1,
1313 _ => 0,
1314 })
1315 .sum()
1316 }
1317
1318 #[test]
1319 fn cells_are_structural_partitions() {
1320 let cells = CellStream::new(lex_str("f \t-- note\n x").unwrap()).unwrap();
1321 assert_eq!(cells.len(), 2);
1322 assert_eq!(cells.to_string(), "f \t-- note\n x");
1323 }
1324
1325 #[test]
1326 fn same_line_application_gets_one_empty_punctuation() {
1327 let cells = lex_str("f x").unwrap().to_cell_stream().unwrap();
1328 assert_eq!(
1329 cells
1330 .iter()
1331 .flat_map(|cell| cell.iter())
1332 .filter(|token| matches!(token, CellTokenTree::Adj(_)))
1333 .count(),
1334 1,
1335 );
1336 }
1337
1338 #[test]
1339 fn flattening_a_framed_cell_restores_lexical_tokens() {
1340 let raw = lex_str("f (g x)").unwrap();
1341 assert_eq!(count_raw_adjacency(&raw), 0);
1342
1343 let cells = raw.to_cell_stream().unwrap();
1344 assert_eq!(count_cell_adjacency(&cells[0]), 2);
1345
1346 let raw = cells.into_token_stream();
1347 assert_eq!(count_raw_adjacency(&raw), 0);
1348 assert_eq!(raw.to_string(), "f (g x)");
1349 }
1350
1351 #[test]
1352 fn line_comment_blocks_begin_the_cell_on_their_right() {
1353 let cells = CellStream::new(lex_str("x\n-- first\n-- second\ny").unwrap()).unwrap();
1354 assert_eq!(cells.len(), 2);
1355 let comments = cells[1].iter().next().unwrap().leading_trivia();
1356 assert_eq!(comments.len(), 1);
1357 assert_eq!(comments[0].kind(), TriviaKind::LineComment);
1358 assert_eq!(comments[0].text(), "-- first\n-- second");
1359 }
1360
1361 #[test]
1362 fn a_blank_line_separates_outer_comment_blocks() {
1363 let cells = CellStream::new(lex_str("-- first\n\n-- second\ny").unwrap()).unwrap();
1364 let comments = cells[0].iter().next().unwrap().leading_trivia();
1365
1366 assert_eq!(comments.len(), 2);
1367 assert_eq!(comments[0].text(), "-- first");
1368 assert_eq!(comments[1].text(), "-- second");
1369 }
1370
1371 #[test]
1372 fn line_comments_do_not_split_an_incomplete_cell() {
1373 let cells = CellStream::new(lex_str("x + -- reason\ny").unwrap()).unwrap();
1374 assert_eq!(cells.len(), 1);
1375 assert!(cells[0].iter().any(|token| {
1376 token
1377 .trailing_trivia()
1378 .iter()
1379 .any(|trivia| trivia.kind() == TriviaKind::LineComment)
1380 }));
1381 }
1382
1383 #[test]
1384 fn fork_copies_only_the_modified_cell_path() {
1385 let original = CellStream::new(lex_str("left; right").unwrap()).unwrap();
1386 let mut fork = original.fork();
1387
1388 assert!(Arc::ptr_eq(&original.0, &fork.0));
1389
1390 fork.data_mut().cells.pop();
1391
1392 assert!(!Arc::ptr_eq(&original.0, &fork.0));
1393 assert_eq!(original.to_string(), "left; right");
1394 assert_eq!(fork.to_string(), "left;");
1395 assert!(original[0].shares_storage(&fork[0]));
1396 }
1397}