Skip to main content

m2_syn/lex/
token_stream.rs

1use std::fmt::{Display, Formatter, Result};
2use std::mem::take;
3use std::ops::Deref;
4use std::sync::Arc;
5use std::vec::IntoIter;
6
7use crate::{Source, Span, Spanned, lexer::punctuation_would_merge};
8use these_macros_should_be_illegal::strutuct;
9
10#[path = "token_stream/delim.rs"]
11pub mod delim;
12use delim::{Delimiter, DelimiterKind};
13
14#[path = "token_stream/punct.rs"]
15/// Internal support for punct.
16mod punct;
17pub use punct::Punct;
18
19strutuct! {
20    #[derive(Debug, Clone, PartialEq, Eq)]
21    /// A literal spelling together with its lexical category and source span.
22    LiteralToken
23    /// The literal's lexical category.
24    #[derive(Copy, Hash)]
25    kind: LiteralKind {
26        /// A double-quoted string.
27        String,
28        /// A slash-delimited raw string.
29        RawString,
30        /// An integer number.
31        Integer,
32        /// A floating-point number.
33        Float,
34    },
35    span: Span,
36    leading_trivia: LeadingTrivia,
37    trailing_trivia: TrailingTrivia,
38}
39
40impl LiteralToken {
41    /// Creates a literal token from its source span.
42    pub fn from_span(kind: LiteralKind, span: Span) -> Self {
43        Self {
44            kind,
45            span,
46            leading_trivia: LeadingTrivia::default(),
47            trailing_trivia: TrailingTrivia::default(),
48        }
49    }
50
51    /// Creates a literal token.
52    pub fn new(kind: LiteralKind, text: impl Into<Arc<str>>, span: Span) -> Self {
53        Self {
54            kind,
55            span: span_for_spelling(text.into(), span),
56            leading_trivia: LeadingTrivia::default(),
57            trailing_trivia: TrailingTrivia::default(),
58        }
59    }
60
61    /// Returns the complete source spelling, including string delimiters.
62    ///
63    /// # Panics
64    ///
65    /// Panics when `sources` cannot resolve this token's span.
66    pub fn text(&self) -> &str {
67        self.span
68            .text()
69            .expect("literal spans must resolve to source text")
70    }
71}
72
73impl Spanned for LiteralToken {
74    fn try_span(&self) -> Option<Span> {
75        Some(self.span.clone())
76    }
77}
78
79impl Lex for LiteralToken {
80    fn to_tokens(&self, output: &mut TokenStream) {
81        output.push(TokenTree::Literal(self.clone()));
82    }
83}
84
85impl Terminal for LiteralToken {
86    fn leading_trivia(&self) -> &LeadingTrivia {
87        &self.leading_trivia
88    }
89
90    fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia {
91        &mut self.leading_trivia
92    }
93
94    fn trailing_trivia(&self) -> &TrailingTrivia {
95        &self.trailing_trivia
96    }
97
98    fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia {
99        &mut self.trailing_trivia
100    }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq)]
104/// An identifier spelling and its source span.
105pub struct IdentToken {
106    /// The span.
107    span: Span,
108    /// The source qualifier.
109    source_qualifier: Option<Span>,
110    /// The index qualifier.
111    index_qualifier: Option<Span>,
112    /// The leading trivia.
113    leading_trivia: LeadingTrivia,
114    /// The trailing trivia.
115    trailing_trivia: TrailingTrivia,
116}
117
118impl IdentToken {
119    /// Creates an identifier from its source span.
120    ///
121    /// # Panics
122    ///
123    /// Panics when the span cannot resolve its source text.
124    pub fn from_span(span: Span) -> Self {
125        let text = span
126            .text()
127            .expect("identifier spans must resolve to source text");
128        let (source_qualifier, index_qualifier) = identifier_qualifier_spans(text, &span);
129        Self {
130            span,
131            source_qualifier,
132            index_qualifier,
133            leading_trivia: LeadingTrivia::default(),
134            trailing_trivia: TrailingTrivia::default(),
135        }
136    }
137
138    /// Creates an identifier token.
139    pub fn new(text: impl Into<Arc<str>>, span: Span) -> Self {
140        Self::from_span(span_for_spelling(text.into(), span))
141    }
142
143    /// Returns the identifier spelling.
144    ///
145    /// # Panics
146    ///
147    /// Panics when `sources` cannot resolve this token's span.
148    pub fn text(&self) -> &str {
149        self.span
150            .text()
151            .expect("identifier spans must resolve to source text")
152    }
153
154    /// Returns the `Source$` prefix, including its `$`, when present.
155    pub fn source_qualifier(&self) -> Option<&Span> {
156        self.source_qualifier.as_ref()
157    }
158
159    /// Returns the `$0` suffix, including its `$`, when present.
160    pub fn index_qualifier(&self) -> Option<&Span> {
161        self.index_qualifier.as_ref()
162    }
163}
164
165impl Spanned for IdentToken {
166    fn try_span(&self) -> Option<Span> {
167        Some(self.span.clone())
168    }
169}
170
171impl Lex for IdentToken {
172    fn to_tokens(&self, output: &mut TokenStream) {
173        output.push(TokenTree::Ident(self.clone()));
174    }
175}
176
177impl Terminal for IdentToken {
178    fn leading_trivia(&self) -> &LeadingTrivia {
179        &self.leading_trivia
180    }
181
182    fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia {
183        &mut self.leading_trivia
184    }
185
186    fn trailing_trivia(&self) -> &TrailingTrivia {
187        &self.trailing_trivia
188    }
189
190    fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia {
191        &mut self.trailing_trivia
192    }
193}
194
195#[derive(Debug, Clone, PartialEq, Eq)]
196/// A delimited raw token stream.
197pub struct TokenGroup {
198    /// The delimiter.
199    delimiter: Delimiter,
200    /// The stream.
201    stream: TokenStream,
202    /// The leading trivia.
203    leading_trivia: LeadingTrivia,
204    /// The trailing trivia.
205    trailing_trivia: TrailingTrivia,
206}
207
208impl Spanned for TokenGroup {
209    fn try_span(&self) -> Option<Span> {
210        self.delimiter.try_span()
211    }
212}
213
214impl TokenGroup {
215    /// Creates a group from its delimiter and contents.
216    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
217        Self {
218            delimiter,
219            stream,
220            leading_trivia: LeadingTrivia::default(),
221            trailing_trivia: TrailingTrivia::default(),
222        }
223    }
224
225    /// Borrows the group's delimiter data.
226    pub fn delimiter(&self) -> &Delimiter {
227        &self.delimiter
228    }
229
230    /// Returns the group's delimiter family.
231    pub fn delim_kind(&self) -> DelimiterKind {
232        self.delimiter.kind
233    }
234
235    /// Borrows the tokens inside the group.
236    pub fn stream(&self) -> &TokenStream {
237        &self.stream
238    }
239
240    /// Mutably borrows the tokens inside the group.
241    pub fn stream_mut(&mut self) -> &mut TokenStream {
242        &mut self.stream
243    }
244
245    /// Consumes the group and returns its contents.
246    pub fn into_stream(self) -> TokenStream {
247        self.stream
248    }
249
250    /// Converts the value into parts.
251    pub(crate) fn into_parts(self) -> (Delimiter, TokenStream, LeadingTrivia, TrailingTrivia) {
252        (
253            self.delimiter,
254            self.stream,
255            self.leading_trivia,
256            self.trailing_trivia,
257        )
258    }
259
260    /// Creates the value from parts.
261    pub(crate) fn from_parts(
262        delimiter: Delimiter,
263        stream: TokenStream,
264        leading_trivia: LeadingTrivia,
265        trailing_trivia: TrailingTrivia,
266    ) -> Self {
267        Self {
268            delimiter,
269            stream,
270            leading_trivia,
271            trailing_trivia,
272        }
273    }
274}
275
276impl Lex for TokenGroup {
277    fn to_tokens(&self, output: &mut TokenStream) {
278        output.push(TokenTree::Group(self.clone()));
279    }
280}
281
282impl Terminal for TokenGroup {
283    fn leading_trivia(&self) -> &LeadingTrivia {
284        &self.leading_trivia
285    }
286
287    fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia {
288        &mut self.leading_trivia
289    }
290
291    fn trailing_trivia(&self) -> &TrailingTrivia {
292        &self.trailing_trivia
293    }
294
295    fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia {
296        &mut self.trailing_trivia
297    }
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
301/// The lexical category of source trivia.
302pub enum TriviaKind {
303    /// A comment extending to the end of a line.
304    LineComment,
305    /// A delimited block comment.
306    BlockComment,
307}
308
309#[derive(Debug, Clone, PartialEq, Eq, Hash, Spanned)]
310/// A comment retained alongside a lexical atom.
311pub struct Trivia {
312    /// The kind.
313    kind: TriviaKind,
314    /// The span.
315    span: Span,
316}
317
318impl Trivia {
319    /// Creates trivia from its category and source span.
320    pub fn from_span(kind: TriviaKind, span: Span) -> Self {
321        Self { kind, span }
322    }
323
324    /// Creates trivia from its category, exact text, and span.
325    pub fn new(kind: TriviaKind, text: impl Into<Arc<str>>, span: Span) -> Self {
326        Self {
327            kind,
328            span: span_for_spelling(text.into(), span),
329        }
330    }
331
332    /// Returns the trivia category.
333    pub fn kind(&self) -> TriviaKind {
334        self.kind
335    }
336
337    /// Returns the trivia exactly as it appeared in source.
338    ///
339    /// # Panics
340    ///
341    /// Panics when `sources` cannot resolve this trivia's span.
342    pub fn text(&self) -> &str {
343        self.span
344            .text()
345            .expect("trivia spans must resolve to source text")
346    }
347}
348
349impl Lex for Trivia {
350    fn to_tokens(&self, output: &mut TokenStream) {
351        output.push_trailing_trivia(self.clone());
352    }
353}
354
355#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
356/// Comments owned by the typed terminal to their left.
357pub struct TrailingTrivia(Vec<Trivia>);
358
359impl TrailingTrivia {
360    /// Creates retained trailing trivia from raw trivia tokens.
361    pub fn new(trivia: impl IntoIterator<Item = Trivia>) -> Self {
362        Self(trivia.into_iter().collect())
363    }
364
365    /// Borrows the retained trivia in source order.
366    pub fn as_slice(&self) -> &[Trivia] {
367        &self.0
368    }
369
370    /// Mutably borrows the retained trivia in source order.
371    pub fn as_mut_vec(&mut self) -> &mut Vec<Trivia> {
372        &mut self.0
373    }
374
375    /// Reports whether no comments follow the terminal.
376    pub fn is_empty(&self) -> bool {
377        self.0.is_empty()
378    }
379
380    /// Consumes the collection and returns its trivia tokens.
381    pub fn into_vec(self) -> Vec<Trivia> {
382        self.0
383    }
384}
385
386impl FromIterator<Trivia> for TrailingTrivia {
387    fn from_iter<T: IntoIterator<Item = Trivia>>(iter: T) -> Self {
388        Self::new(iter)
389    }
390}
391
392impl Spanned for TrailingTrivia {
393    fn try_span(&self) -> Option<Span> {
394        Span::join_all(self.0.iter().map(Spanned::try_span))
395    }
396}
397
398impl Lex for TrailingTrivia {
399    fn to_tokens(&self, output: &mut TokenStream) {
400        self.0.to_tokens(output);
401    }
402}
403
404#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
405/// Comments owned by the typed terminal to their right.
406pub struct LeadingTrivia(Vec<Trivia>);
407
408impl LeadingTrivia {
409    /// Creates leading trivia from raw trivia tokens.
410    pub fn new(trivia: impl IntoIterator<Item = Trivia>) -> Self {
411        Self(trivia.into_iter().collect())
412    }
413
414    /// Borrows the retained trivia in source order.
415    pub fn as_slice(&self) -> &[Trivia] {
416        &self.0
417    }
418
419    /// Mutably borrows the comment storage in source order.
420    pub fn as_mut_vec(&mut self) -> &mut Vec<Trivia> {
421        &mut self.0
422    }
423
424    /// Reports whether the block is empty.
425    pub fn is_empty(&self) -> bool {
426        self.0.is_empty()
427    }
428
429    /// Consumes the collection and returns its comments.
430    pub fn into_vec(self) -> Vec<Trivia> {
431        self.0
432    }
433}
434
435impl FromIterator<Trivia> for LeadingTrivia {
436    fn from_iter<T: IntoIterator<Item = Trivia>>(iter: T) -> Self {
437        Self::new(iter)
438    }
439}
440
441impl Spanned for LeadingTrivia {
442    fn try_span(&self) -> Option<Span> {
443        Span::join_all(self.0.iter().map(Spanned::try_span))
444    }
445}
446
447impl Lex for LeadingTrivia {
448    fn to_tokens(&self, output: &mut TokenStream) {
449        for trivia in self.0.iter().cloned() {
450            output.push_leading_trivia(trivia);
451        }
452    }
453}
454
455#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Spanned)]
456/// Comment blocks owned by one structural syntax item.
457///
458/// Outer comments are complete-line `--` blocks documenting the item on
459/// their right. Inner comments occur within the item, including delimited
460/// block comments and `--` comments following code on the same line.
461pub struct CommentTrivia {
462    /// The outer.
463    outer: Vec<Trivia>,
464    /// The inner.
465    inner: Vec<Trivia>,
466}
467
468impl CommentTrivia {
469    /// Borrows the complete-line comment blocks attached from above.
470    pub fn outer(&self) -> &[Trivia] {
471        &self.outer
472    }
473
474    /// Borrows comments contained by the owning syntax item.
475    pub fn inner(&self) -> &[Trivia] {
476        &self.inner
477    }
478
479    /// Reports whether the owner has no retained comments.
480    pub fn is_empty(&self) -> bool {
481        self.outer.is_empty() && self.inner.is_empty()
482    }
483
484    /// Takes from cell.
485    pub(crate) fn take_from_cell(tokens: &mut TokenStream) -> Self {
486        let mut outer = Vec::new();
487        if let Some(first) = tokens.data_mut().trees.first_mut() {
488            let leading = first.leading_trivia_mut().as_mut_vec();
489            let mut retained = Vec::with_capacity(leading.len());
490            for trivia in take(leading) {
491                if trivia.kind() == TriviaKind::LineComment {
492                    outer.push(trivia);
493                } else {
494                    retained.push(trivia);
495                }
496            }
497            *leading = retained;
498        }
499        let mut inner = take_stream_comments(tokens);
500        sort_comments(&mut outer);
501        sort_comments(&mut inner);
502        Self { outer, inner }
503    }
504
505    /// Takes inner.
506    pub(crate) fn take_inner(tokens: &mut TokenStream) -> Self {
507        let mut inner = take_stream_comments(tokens);
508        sort_comments(&mut inner);
509        Self {
510            outer: Vec::new(),
511            inner,
512        }
513    }
514
515    /// Handles append.
516    pub(crate) fn append(&mut self, mut comments: Self) {
517        self.outer.append(&mut comments.outer);
518        self.inner.append(&mut comments.inner);
519        sort_comments(&mut self.outer);
520        sort_comments(&mut self.inner);
521    }
522
523    /// Reattaches owned comments to a raw projection at their source-relative
524    /// positions.
525    #[doc(hidden)]
526    pub fn __apply_to(&self, output: &mut TokenStream) {
527        for comment in self.outer.iter().rev().cloned() {
528            output.prepend_comment(comment);
529        }
530        for comment in self.inner.iter().cloned() {
531            output.insert_inner_comment(comment);
532        }
533    }
534}
535
536/// Handles sort comments.
537fn sort_comments(comments: &mut [Trivia]) {
538    comments.sort_by_key(|comment| comment.span().start().unwrap_or(usize::MAX));
539}
540
541/// Takes stream comments.
542fn take_stream_comments(stream: &mut TokenStream) -> Vec<Trivia> {
543    let data = stream.data_mut();
544    let mut comments = take(&mut data.prefix).into_vec();
545    for token in &mut data.trees {
546        comments.extend(take(token.leading_trivia_mut()).into_vec());
547        if let TokenTree::Group(group) = token {
548            comments.extend(take_stream_comments(group.stream_mut()));
549        }
550        comments.extend(take(token.trailing_trivia_mut()).into_vec());
551    }
552    comments.extend(take(&mut data.suffix).into_vec());
553    comments
554}
555
556/// A typed terminal together with its adjacent comments.
557pub trait Terminal: Spanned {
558    /// Borrows the comments preceding this terminal.
559    fn leading_trivia(&self) -> &LeadingTrivia;
560
561    /// Mutably borrows the comments preceding this terminal.
562    fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia;
563
564    /// Borrows the comments following this terminal.
565    fn trailing_trivia(&self) -> &TrailingTrivia;
566
567    /// Mutably borrows the comments following this terminal.
568    fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia;
569
570    /// Replaces the comments preceding this terminal.
571    fn set_leading_trivia(&mut self, trivia: impl IntoIterator<Item = Trivia>)
572    where
573        Self: Sized,
574    {
575        *self.leading_trivia_mut() = LeadingTrivia::new(trivia);
576    }
577
578    /// Replaces the comments and layout characters following this terminal.
579    fn set_trailing_trivia(&mut self, trivia: impl IntoIterator<Item = Trivia>)
580    where
581        Self: Sized,
582    {
583        *self.trailing_trivia_mut() = TrailingTrivia::new(trivia);
584    }
585}
586
587/// Handles identifier qualifier spans.
588fn identifier_qualifier_spans(spelling: &str, span: &Span) -> (Option<Span>, Option<Span>) {
589    let separators = spelling
590        .match_indices('$')
591        .map(|(index, _)| index)
592        .collect::<Vec<_>>();
593    let source = separators.first().and_then(|separator| {
594        let name = &spelling[..*separator];
595        (!name.is_empty() && name.bytes().all(is_identifier_byte))
596            .then(|| span.subspan(0, separator + 1))
597    });
598    let index = separators.last().and_then(|separator| {
599        let digits = &spelling[separator + 1..];
600        (!digits.is_empty() && digits.bytes().all(|byte| byte.is_ascii_digit()))
601            .then(|| span.subspan(*separator, spelling.len()))
602    });
603    (source, index)
604}
605
606/// Returns whether the value is identifier byte.
607fn is_identifier_byte(byte: u8) -> bool {
608    byte == b'_' || byte.is_ascii_alphanumeric()
609}
610
611/// Handles span for spelling.
612fn span_for_spelling(text: Arc<str>, span: Span) -> Span {
613    if span.text() == Some(text.as_ref()) {
614        span
615    } else {
616        let source = Source::with_file(span.file(), text);
617        let len = source.text().len();
618        Span::ranged(source, 0..len)
619    }
620}
621
622#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
623/// One raw M2 token tree.
624pub enum TokenTree {
625    /// A delimited group.
626    Group(TokenGroup),
627    /// A literal.
628    Literal(LiteralToken),
629    /// Punctuation.
630    Punct(Punct),
631    /// An identifier or keyword spelling.
632    Ident(IdentToken),
633}
634
635impl TokenTree {
636    /// Returns the token's source spelling when it is a flat lexical atom.
637    pub fn spelling(&self) -> Option<&str> {
638        match self {
639            Self::Literal(token) => Some(token.text()),
640            Self::Punct(token) => Some(token.text()),
641            Self::Ident(token) => Some(token.text()),
642            Self::Group(_) => None,
643        }
644    }
645
646    /// Handles description.
647    pub(crate) fn description(&self) -> String {
648        match self {
649            Self::Group(group) => group.delim_kind().to_string(),
650            token => token.spelling().unwrap_or("").to_owned(),
651        }
652    }
653
654    /// Borrows the comments attached before this atom.
655    pub fn leading_trivia(&self) -> &LeadingTrivia {
656        match self {
657            Self::Group(token) => token.leading_trivia(),
658            Self::Literal(token) => token.leading_trivia(),
659            Self::Punct(token) => token.leading_trivia(),
660            Self::Ident(token) => token.leading_trivia(),
661        }
662    }
663
664    /// Mutably borrows the comments attached before this atom.
665    pub fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia {
666        match self {
667            Self::Group(token) => token.leading_trivia_mut(),
668            Self::Literal(token) => token.leading_trivia_mut(),
669            Self::Punct(token) => token.leading_trivia_mut(),
670            Self::Ident(token) => token.leading_trivia_mut(),
671        }
672    }
673
674    /// Borrows the comments attached after this atom.
675    pub fn trailing_trivia(&self) -> &TrailingTrivia {
676        match self {
677            Self::Group(token) => token.trailing_trivia(),
678            Self::Literal(token) => token.trailing_trivia(),
679            Self::Punct(token) => token.trailing_trivia(),
680            Self::Ident(token) => token.trailing_trivia(),
681        }
682    }
683
684    /// Mutably borrows the comments attached after this atom.
685    pub fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia {
686        match self {
687            Self::Group(token) => token.trailing_trivia_mut(),
688            Self::Literal(token) => token.trailing_trivia_mut(),
689            Self::Punct(token) => token.trailing_trivia_mut(),
690            Self::Ident(token) => token.trailing_trivia_mut(),
691        }
692    }
693}
694
695impl Lex for TokenTree {
696    fn to_tokens(&self, output: &mut TokenStream) {
697        output.push(self.clone());
698    }
699}
700
701#[derive(Debug, Clone, Default)]
702/// Internal state for TokenStreamData.
703struct TokenStreamData {
704    /// The trees.
705    trees: Vec<TokenTree>,
706    /// The prefix.
707    prefix: TrailingTrivia,
708    /// The suffix.
709    suffix: LeadingTrivia,
710    /// The source.
711    source: Option<Arc<Source>>,
712}
713
714/// Internal state for TokenStreamParts.
715pub(crate) struct TokenStreamParts {
716    /// The trees.
717    pub(crate) trees: Vec<TokenTree>,
718    /// The prefix.
719    pub(crate) prefix: TrailingTrivia,
720    /// The suffix.
721    pub(crate) suffix: LeadingTrivia,
722    /// The source.
723    pub(crate) source: Option<Arc<Source>>,
724}
725
726impl PartialEq for TokenStreamData {
727    fn eq(&self, other: &Self) -> bool {
728        self.trees == other.trees
729            && self.prefix == other.prefix
730            && self.suffix == other.suffix
731            && match (&self.source, &other.source) {
732                (Some(left), Some(right)) => Arc::ptr_eq(left, right),
733                (None, None) => true,
734                _ => false,
735            }
736    }
737}
738
739impl Eq for TokenStreamData {}
740
741#[derive(Debug, Clone, Default, PartialEq, Eq)]
742/// A persistent sequence of raw M2 token trees.
743///
744/// Clones and [`Self::fork`] share immutable backing storage. The first
745/// mutation of either value detaches that value through copy-on-write, so
746/// speculative consumers can retain the original stream without cloning its
747/// token trees eagerly.
748pub struct TokenStream(Arc<TokenStreamData>);
749
750impl Spanned for TokenStream {
751    fn try_span(&self) -> Option<Span> {
752        Span::join_all(
753            self.data()
754                .prefix
755                .try_span()
756                .into_iter()
757                .chain(self.iter().filter_map(Spanned::try_span))
758                .chain(self.data().suffix.try_span()),
759        )
760    }
761}
762
763impl Deref for TokenStream {
764    type Target = [TokenTree];
765
766    fn deref(&self) -> &Self::Target {
767        &self.data().trees
768    }
769}
770
771impl AsRef<[TokenTree]> for TokenStream {
772    fn as_ref(&self) -> &[TokenTree] {
773        self
774    }
775}
776
777impl TokenStream {
778    /// Creates an empty token stream.
779    pub fn new() -> Self {
780        Self::default()
781    }
782
783    /// Creates an independently mutable view over the same token storage.
784    ///
785    /// This operation is constant time. Mutating either stream preserves the
786    /// other stream and copies only the backing structures on the modified
787    /// path.
788    pub fn fork(&self) -> Self {
789        self.clone()
790    }
791
792    /// Borrows the shared backing data.
793    fn data(&self) -> &TokenStreamData {
794        &self.0
795    }
796
797    /// Borrows the shared backing data mutably.
798    fn data_mut(&mut self) -> &mut TokenStreamData {
799        Arc::make_mut(&mut self.0)
800    }
801
802    /// Converts the value into data.
803    fn into_data(self) -> TokenStreamData {
804        Arc::try_unwrap(self.0).unwrap_or_else(|data| (*data).clone())
805    }
806
807    /// Converts the value into parts.
808    pub(crate) fn into_parts(self) -> TokenStreamParts {
809        let TokenStreamData {
810            trees,
811            prefix,
812            suffix,
813            source,
814        } = self.into_data();
815        TokenStreamParts {
816            trees,
817            prefix,
818            suffix,
819            source,
820        }
821    }
822
823    /// Creates the value from parts.
824    pub(crate) fn from_parts(parts: TokenStreamParts) -> Self {
825        Self(Arc::new(TokenStreamData {
826            trees: parts.trees,
827            prefix: parts.prefix,
828            suffix: parts.suffix,
829            source: parts.source,
830        }))
831    }
832
833    /// Handles shares storage.
834    pub(crate) fn shares_storage(&self, other: &Self) -> bool {
835        Arc::ptr_eq(&self.0, &other.0)
836    }
837
838    #[cfg(feature = "tree-sitter")]
839    /// Returns whether the value has significant tokens.
840    pub(crate) fn has_significant_tokens(&self) -> bool {
841        !self.is_empty()
842    }
843
844    /// Returns whether the value has trivia.
845    pub(crate) fn has_trivia(&self) -> bool {
846        !self.data().prefix.is_empty() || !self.data().suffix.is_empty()
847    }
848
849    /// Handles prefix trivia.
850    pub(crate) fn prefix_trivia(&self) -> &[Trivia] {
851        self.data().prefix.as_slice()
852    }
853
854    /// Handles suffix trivia.
855    pub(crate) fn suffix_trivia(&self) -> &[Trivia] {
856        self.data().suffix.as_slice()
857    }
858
859    /// Returns the associated source snapshot.
860    pub(crate) fn source(&self) -> Option<Arc<Source>> {
861        let mut source = self.data().source.clone();
862        coherent_stream_source(self, &mut source)
863            .then_some(source)
864            .flatten()
865    }
866
867    /// Handles set source.
868    pub(crate) fn set_source(&mut self, source: Arc<Source>) {
869        self.data_mut().source = Some(source);
870    }
871
872    /// Takes final punctuation.
873    pub(crate) fn take_final_punctuation(
874        &mut self,
875        spelling: &str,
876    ) -> Option<(Punct, TrailingTrivia)> {
877        let position = self.data().trees.len().checked_sub(1)?;
878        let TokenTree::Punct(punctuation) = self.data().trees.get(position)? else {
879            return None;
880        };
881        if punctuation.text() != spelling {
882            return None;
883        }
884        let TokenTree::Punct(mut punctuation) = self.data_mut().trees.remove(position) else {
885            unreachable!("the final significant token was punctuation")
886        };
887        let trailing_trivia = take(punctuation.trailing_trivia_mut());
888        Some((punctuation, trailing_trivia))
889    }
890
891    /// Takes leading trivia.
892    pub(crate) fn take_leading_trivia(&mut self) -> TrailingTrivia {
893        let data = self.data_mut();
894        let mut trivia = take(&mut data.prefix).into_vec();
895        trivia.extend(take(&mut data.suffix).into_vec());
896        TrailingTrivia::new(trivia)
897    }
898
899    /// Takes prefix trivia.
900    pub(crate) fn take_prefix_trivia(&mut self) -> TrailingTrivia {
901        take(&mut self.data_mut().prefix)
902    }
903
904    /// Takes suffix trivia.
905    pub(crate) fn take_suffix_trivia(&mut self) -> LeadingTrivia {
906        take(&mut self.data_mut().suffix)
907    }
908
909    /// Handles push.
910    pub(crate) fn push(&mut self, mut token: TokenTree) {
911        let data = self.data_mut();
912        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
913            && !group.delimiter().is_closed()
914        {
915            group.stream_mut().push(token);
916        } else {
917            token
918                .leading_trivia_mut()
919                .as_mut_vec()
920                .splice(..0, take(&mut data.suffix).into_vec());
921            data.trees.push(token);
922        }
923    }
924
925    /// Pushes line comment.
926    pub(crate) fn push_line_comment(&mut self, comment: Trivia) {
927        let data = self.data_mut();
928        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
929            && !group.delimiter().is_closed()
930        {
931            group.stream_mut().push_line_comment(comment);
932        } else if let Some(comment) = complete_line_comment(&comment) {
933            push_line_comment_block(data.suffix.as_mut_vec(), comment);
934        } else if let Some(token) = data.trees.last_mut() {
935            token.trailing_trivia_mut().as_mut_vec().push(comment);
936        } else {
937            data.prefix.as_mut_vec().push(comment);
938        }
939    }
940
941    #[doc(hidden)]
942    pub fn push_leading_trivia(&mut self, trivia: Trivia) {
943        let data = self.data_mut();
944        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
945            && !group.delimiter().is_closed()
946        {
947            group.stream_mut().push_leading_trivia(trivia);
948        } else {
949            data.suffix.as_mut_vec().push(trivia);
950        }
951    }
952
953    /// Pushes block comment.
954    pub(crate) fn push_block_comment(&mut self, comment: Trivia) {
955        let data = self.data_mut();
956        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
957            && !group.delimiter().is_closed()
958        {
959            group.stream_mut().push_block_comment(comment);
960        } else if let Some(token) = data.trees.last_mut() {
961            token.trailing_trivia_mut().as_mut_vec().push(comment);
962        } else if !data.suffix.is_empty() {
963            data.suffix.as_mut_vec().push(comment);
964        } else {
965            data.prefix.as_mut_vec().push(comment);
966        }
967    }
968
969    /// Pushes trailing trivia.
970    pub(crate) fn push_trailing_trivia(&mut self, trivia: Trivia) {
971        let data = self.data_mut();
972        if let Some(token) = data.trees.last_mut() {
973            token.trailing_trivia_mut().as_mut_vec().push(trivia);
974        } else {
975            data.prefix.as_mut_vec().push(trivia);
976        }
977    }
978
979    /// Handles complete last group.
980    pub(crate) fn complete_last_group(&mut self, kind: DelimiterKind, close: Span) -> bool {
981        let Some(TokenTree::Group(group)) = self.data_mut().trees.last_mut() else {
982            return false;
983        };
984        if group.stream.complete_last_group(kind, close.clone()) {
985            return true;
986        }
987        if group.delim_kind() != kind || group.delimiter().is_closed() {
988            return false;
989        }
990        group.delimiter.spans.complete(close);
991        true
992    }
993
994    /// Handles last innermost.
995    pub(crate) fn last_innermost(&self) -> Option<&TokenTree> {
996        let last = self.last()?;
997        match last {
998            TokenTree::Group(group) if !group.delimiter().is_closed() => {
999                group.stream().last_innermost().or(Some(last))
1000            }
1001            _ => Some(last),
1002        }
1003    }
1004
1005    /// Handles prepend comment.
1006    fn prepend_comment(&mut self, comment: Trivia) {
1007        let data = self.data_mut();
1008        if let Some(first) = data.trees.first_mut() {
1009            first.leading_trivia_mut().as_mut_vec().insert(0, comment);
1010        } else {
1011            data.prefix.as_mut_vec().insert(0, comment);
1012        }
1013    }
1014
1015    /// Inserts inner comment.
1016    fn insert_inner_comment(&mut self, comment: Trivia) {
1017        let start = comment.span().start();
1018        let data = self.data_mut();
1019        if let Some(start) = start {
1020            for token in &mut data.trees {
1021                if let TokenTree::Group(group) = token {
1022                    let span = group.span();
1023                    if span.shares_source(&comment.span())
1024                        && span.start().is_some_and(|open| open <= start)
1025                        && span.end().is_some_and(|close| start <= close)
1026                    {
1027                        group.stream_mut().insert_inner_comment(comment);
1028                        return;
1029                    }
1030                }
1031            }
1032
1033            if let Some(token) = data.trees.iter_mut().rev().find(|token| {
1034                let span = token.span();
1035                span.shares_source(&comment.span())
1036                    && span.start().is_some_and(|token_start| token_start <= start)
1037            }) {
1038                token.trailing_trivia_mut().as_mut_vec().push(comment);
1039                return;
1040            }
1041
1042            if data
1043                .trees
1044                .iter()
1045                .any(|token| token.span().shares_source(&comment.span()))
1046            {
1047                data.prefix.as_mut_vec().push(comment);
1048                return;
1049            }
1050        }
1051
1052        if let Some(last) = data.trees.last_mut() {
1053            last.trailing_trivia_mut().as_mut_vec().push(comment);
1054        } else {
1055            data.prefix.as_mut_vec().push(comment);
1056        }
1057    }
1058
1059    #[doc(hidden)]
1060    pub fn starts_with_whitespace(&self) -> bool {
1061        false
1062    }
1063
1064    #[doc(hidden)]
1065    pub fn ends_with_whitespace(&self) -> bool {
1066        false
1067    }
1068
1069    #[doc(hidden)]
1070    pub fn ends_with_line_break(&self) -> bool {
1071        self.data()
1072            .trees
1073            .last()
1074            .is_some_and(|token| gap_after_contains(token, '\n'))
1075    }
1076
1077    #[doc(hidden)]
1078    pub fn ends_with_semicolon(&self) -> bool {
1079        matches!(self.data().trees.last(), Some(TokenTree::Punct(token)) if token.text() == ";")
1080    }
1081
1082    /// Appends one emitted syntax fragment with any separator required to keep
1083    /// adjacent word-like fragments lexically distinct.
1084    ///
1085    /// This is the composition operation used by [`crate::quote_m2!`]. The
1086    /// fragment retains all of its internal token structure and comments.
1087    /// Rendering inserts a conventional space when independently sourced atoms
1088    /// would otherwise merge into one lexical token.
1089    #[doc(hidden)]
1090    pub fn append_fragment<T: Lex + ?Sized>(&mut self, fragment: &T) {
1091        let fragment = fragment.to_token_stream();
1092        self.extend([fragment]);
1093    }
1094
1095    /// Removes and returns the final token tree, if any.
1096    pub fn pop(&mut self) -> Option<TokenTree> {
1097        self.data_mut().trees.pop()
1098    }
1099
1100    /// Migrates source text from the shared sources retained by its spans.
1101    pub fn to_source(&self) -> String {
1102        self.to_string()
1103    }
1104}
1105
1106/// Handles complete line comment.
1107fn complete_line_comment(comment: &Trivia) -> Option<Trivia> {
1108    let span = comment.span();
1109    let (Some(start), Some(end)) = (span.start(), span.end()) else {
1110        return None;
1111    };
1112    let source = span.source();
1113    let line_start = source.text()[..start]
1114        .rfind('\n')
1115        .map_or(0, |newline| newline + 1);
1116    source.text()[line_start..start]
1117        .bytes()
1118        .all(|byte| matches!(byte, b' ' | b'\t' | b'\r'))
1119        .then(|| {
1120            Trivia::from_span(
1121                TriviaKind::LineComment,
1122                Span::ranged(Arc::clone(source), line_start..end),
1123            )
1124        })
1125}
1126
1127/// Pushes line comment block.
1128fn push_line_comment_block(comments: &mut Vec<Trivia>, comment: Trivia) {
1129    let Some(previous) = comments.last_mut() else {
1130        comments.push(comment);
1131        return;
1132    };
1133    if previous.kind() != TriviaKind::LineComment || !previous.span().shares_source(&comment.span())
1134    {
1135        comments.push(comment);
1136        return;
1137    }
1138    let (Some(previous_start), Some(previous_end), Some(comment_start), Some(comment_end)) = (
1139        previous.span().start(),
1140        previous.span().end(),
1141        comment.span().start(),
1142        comment.span().end(),
1143    ) else {
1144        comments.push(comment);
1145        return;
1146    };
1147    let previous_span = previous.span();
1148    let gap = &previous_span.source().text()[previous_end..comment_start];
1149    let same_block = gap
1150        .strip_prefix("\r\n")
1151        .or_else(|| gap.strip_prefix('\n'))
1152        .is_some_and(|indent| indent.bytes().all(|byte| matches!(byte, b' ' | b'\t')));
1153    if same_block {
1154        *previous = Trivia::from_span(
1155            TriviaKind::LineComment,
1156            Span::ranged(
1157                Arc::clone(previous.span().source()),
1158                previous_start..comment_end,
1159            ),
1160        );
1161    } else {
1162        comments.push(comment);
1163    }
1164}
1165
1166/// Handles coherent stream source.
1167fn coherent_stream_source(stream: &TokenStream, source: &mut Option<Arc<Source>>) -> bool {
1168    for trivia in stream.prefix_trivia().iter().chain(stream.suffix_trivia()) {
1169        if !record_source(trivia.span(), source) {
1170            return false;
1171        }
1172    }
1173    for token in stream.iter() {
1174        if !record_source(token.span(), source)
1175            || !token
1176                .leading_trivia()
1177                .as_slice()
1178                .iter()
1179                .chain(token.trailing_trivia().as_slice())
1180                .all(|trivia| record_source(trivia.span(), source))
1181        {
1182            return false;
1183        }
1184        if let TokenTree::Group(group) = token
1185            && !coherent_stream_source(group.stream(), source)
1186        {
1187            return false;
1188        }
1189    }
1190    true
1191}
1192
1193/// Handles record source.
1194fn record_source(span: Span, source: &mut Option<Arc<Source>>) -> bool {
1195    match source {
1196        Some(expected) => Arc::ptr_eq(expected, span.source()),
1197        None => {
1198            *source = Some(Arc::clone(span.source()));
1199            true
1200        }
1201    }
1202}
1203
1204impl Display for TokenStream {
1205    fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
1206        write_stream(formatter, self)
1207    }
1208}
1209/// Handles needs separator.
1210fn needs_separator(left: &TokenTree, right: &TokenTree) -> bool {
1211    let left_span = left.span();
1212    let right_span = right.span();
1213    if left_span.shares_source(&right_span) && left_span.end() == right_span.start() {
1214        return false;
1215    }
1216    let wordlike = |tree: &TokenTree| {
1217        matches!(
1218            tree,
1219            TokenTree::Ident(_) | TokenTree::Literal(_) | TokenTree::Group(_)
1220        )
1221    };
1222    (wordlike(left) && wordlike(right))
1223        || matches!((left, right), (TokenTree::Punct(left), TokenTree::Punct(right))
1224            if punctuation_would_merge(left.text(), right.text()))
1225}
1226
1227/// Writes stream.
1228fn write_stream(formatter: &mut Formatter<'_>, stream: &TokenStream) -> Result {
1229    let mut previous_span = write_trivia(formatter, None, stream.data().prefix.as_slice())?;
1230    let mut previous_atom = None::<&TokenTree>;
1231    for tree in stream {
1232        if !tree.leading_trivia().is_empty() {
1233            previous_span =
1234                write_trivia(formatter, previous_span, tree.leading_trivia().as_slice())?;
1235            previous_atom = None;
1236        }
1237        if let Some(left) = previous_span {
1238            let recovered_space = write_source_spaces(formatter, left, tree.span())?;
1239            if !recovered_space && previous_atom.is_some_and(|left| needs_separator(left, tree)) {
1240                formatter.write_str(" ")?;
1241            }
1242        }
1243        write_tree(formatter, tree)?;
1244        previous_span = Some(tree.span());
1245        previous_atom = Some(tree);
1246        if !tree.trailing_trivia().is_empty() {
1247            previous_span =
1248                write_trivia(formatter, previous_span, tree.trailing_trivia().as_slice())?;
1249            previous_atom = None;
1250        }
1251    }
1252    write_trivia(formatter, previous_span, stream.data().suffix.as_slice())?;
1253    Ok(())
1254}
1255
1256/// Writes trivia.
1257fn write_trivia(
1258    formatter: &mut Formatter<'_>,
1259    mut previous: Option<Span>,
1260    trivia: &[Trivia],
1261) -> std::result::Result<Option<Span>, std::fmt::Error> {
1262    for item in trivia {
1263        if let Some(left) = previous {
1264            write_source_spaces(formatter, left, item.span())?;
1265        }
1266        formatter.write_str(item.text())?;
1267        previous = Some(item.span());
1268    }
1269    Ok(previous)
1270}
1271
1272/// Writes source spaces.
1273fn write_source_spaces(
1274    formatter: &mut Formatter<'_>,
1275    left: Span,
1276    right: Span,
1277) -> std::result::Result<bool, std::fmt::Error> {
1278    if !left.shares_source(&right) {
1279        return Ok(false);
1280    }
1281    let (Some(end), Some(start)) = (left.end(), right.start()) else {
1282        return Ok(false);
1283    };
1284    if end > start {
1285        return Ok(false);
1286    }
1287    let gap = &left.source().text()[end..start];
1288    if gap.bytes().all(|byte| byte.is_ascii_whitespace()) {
1289        formatter.write_str(gap)?;
1290        Ok(true)
1291    } else {
1292        Ok(false)
1293    }
1294}
1295
1296/// Writes tree.
1297fn write_tree(formatter: &mut Formatter<'_>, tree: &TokenTree) -> Result {
1298    match tree {
1299        TokenTree::Group(group) => {
1300            formatter.write_str(group.delim_kind().opening())?;
1301            let opening = group.delimiter().opening_span();
1302            if let Some(first) = group.stream.iter().next() {
1303                write_source_spaces(formatter, opening.clone(), first.span())?;
1304            }
1305            write_stream(formatter, &group.stream)?;
1306            if let Some(closing) = group.delimiter().closing_span() {
1307                let left = group
1308                    .stream
1309                    .iter()
1310                    .next_back()
1311                    .map_or(opening, Spanned::span);
1312                write_source_spaces(formatter, left, closing)?;
1313                formatter.write_str(group.delim_kind().closing())?;
1314            }
1315            Ok(())
1316        }
1317        TokenTree::Literal(literal) => formatter.write_str(literal.text()),
1318        TokenTree::Punct(punct) => formatter.write_str(punct.text()),
1319        TokenTree::Ident(ident) => formatter.write_str(ident.text()),
1320    }
1321}
1322
1323/// Handles gap after contains.
1324fn gap_after_contains(token: &TokenTree, character: char) -> bool {
1325    let span = token
1326        .trailing_trivia()
1327        .as_slice()
1328        .last()
1329        .map_or_else(|| token.span(), Spanned::span);
1330    let Some(end) = span.end() else {
1331        return false;
1332    };
1333    span.source().text()[end..].contains(character)
1334}
1335
1336/// Appends anything that can emit tokens, one item at a time.
1337///
1338/// `Lex` already states which types produce tokens; this states how a
1339/// `TokenStream` accepts them, by forwarding to `Lex::to_tokens`. It
1340/// subsumes the two concrete impls this replaced (`TokenTree` and
1341/// `TokenStream` itself both implement `Lex`), and works for any other `Lex`
1342/// type without a bespoke impl.
1343impl<T: Lex> Extend<T> for TokenStream {
1344    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1345        for item in iter {
1346            item.to_tokens(self);
1347        }
1348    }
1349}
1350
1351impl FromIterator<TokenTree> for TokenStream {
1352    fn from_iter<T: IntoIterator<Item = TokenTree>>(iter: T) -> Self {
1353        Self(Arc::new(TokenStreamData {
1354            trees: iter.into_iter().collect(),
1355            prefix: TrailingTrivia::default(),
1356            suffix: LeadingTrivia::default(),
1357            source: None,
1358        }))
1359    }
1360}
1361
1362impl IntoIterator for TokenStream {
1363    type Item = TokenTree;
1364    type IntoIter = IntoIter<TokenTree>;
1365    fn into_iter(self) -> Self::IntoIter {
1366        self.into_data().trees.into_iter()
1367    }
1368}
1369
1370impl<'syntax> IntoIterator for &'syntax TokenStream {
1371    type Item = &'syntax TokenTree;
1372    type IntoIter = std::slice::Iter<'syntax, TokenTree>;
1373
1374    fn into_iter(self) -> Self::IntoIter {
1375        self.iter()
1376    }
1377}
1378
1379impl Lex for TokenStream {
1380    fn to_tokens(&self, output: &mut TokenStream) {
1381        let preserve_source =
1382            output.is_empty() && output.data().prefix.is_empty() && output.data().suffix.is_empty();
1383        for trivia in self.data().prefix.as_slice().iter().cloned() {
1384            output.push_trailing_trivia(trivia);
1385        }
1386        for token in self.iter().cloned() {
1387            output.push(token);
1388        }
1389        output
1390            .data_mut()
1391            .suffix
1392            .as_mut_vec()
1393            .extend(self.data().suffix.as_slice().iter().cloned());
1394        output.data_mut().source = preserve_source.then(|| self.source()).flatten();
1395    }
1396}
1397
1398/// Emits a typed or raw syntax value into the shared token representation.
1399pub trait Lex {
1400    /// Appends this value's token trees to `output`.
1401    fn to_tokens(&self, output: &mut TokenStream);
1402
1403    /// Emits this value into a fresh token stream.
1404    fn to_token_stream(&self) -> TokenStream {
1405        let mut output = TokenStream::new();
1406        self.to_tokens(&mut output);
1407        output
1408    }
1409
1410    /// Renders this value as normalized Macaulay2 source.
1411    fn to_m2(&self) -> String {
1412        self.to_token_stream().to_source()
1413    }
1414}
1415
1416impl<T: Lex + ?Sized> Lex for &T {
1417    fn to_tokens(&self, output: &mut TokenStream) {
1418        (*self).to_tokens(output);
1419    }
1420}
1421
1422impl<T: Lex + ?Sized> Lex for Box<T> {
1423    fn to_tokens(&self, output: &mut TokenStream) {
1424        self.as_ref().to_tokens(output);
1425    }
1426}
1427
1428impl<T: Lex> Lex for Option<T> {
1429    fn to_tokens(&self, output: &mut TokenStream) {
1430        if let Some(value) = self {
1431            value.to_tokens(output);
1432        }
1433    }
1434}
1435
1436impl<T: Lex> Lex for [T] {
1437    fn to_tokens(&self, output: &mut TokenStream) {
1438        for token in self {
1439            token.to_tokens(output);
1440        }
1441    }
1442}
1443
1444impl<T: Lex> Lex for Vec<T> {
1445    fn to_tokens(&self, output: &mut TokenStream) {
1446        self.as_slice().to_tokens(output);
1447    }
1448}
1449
1450#[cfg(test)]
1451mod tests {
1452    use crate::lex_str;
1453
1454    #[test]
1455    fn fork_shares_tokens_until_the_first_mutation() {
1456        let original = lex_str("left + right").unwrap();
1457        let mut fork = original.fork();
1458
1459        assert!(original.shares_storage(&fork));
1460        assert_eq!((&original).into_iter().count(), original.len());
1461
1462        fork.pop();
1463
1464        assert!(!original.shares_storage(&fork));
1465        assert_eq!(original.to_string(), "left + right");
1466        assert_eq!(fork.to_string(), "left +");
1467    }
1468}