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