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    /// Collects the comments a token projection carries, without detaching
473    /// them from the tokens that own them.
474    ///
475    /// Complete-line `--` blocks leading the first token are outer comments;
476    /// every other comment, in source order, is inner.
477    pub fn of(tokens: &TokenStream) -> Self {
478        let mut comments = Self::default();
479        let data = tokens.data();
480        comments
481            .inner
482            .extend(data.prefix.as_slice().iter().cloned());
483        for (index, token) in data.trees.iter().enumerate() {
484            for trivia in token.leading_trivia().as_slice() {
485                if index == 0 && trivia.kind() == TriviaKind::LineComment {
486                    comments.outer.push(trivia.clone());
487                } else {
488                    comments.inner.push(trivia.clone());
489                }
490            }
491            if let TokenTree::Group(group) = token {
492                comments
493                    .inner
494                    .extend(Self::of(group.stream()).into_trivia());
495            }
496            comments
497                .inner
498                .extend(token.trailing_trivia().as_slice().iter().cloned());
499        }
500        comments
501            .inner
502            .extend(data.suffix.as_slice().iter().cloned());
503        comments
504    }
505
506    /// Consumes the collection and returns its comments in source order.
507    pub(crate) fn into_trivia(self) -> impl Iterator<Item = Trivia> {
508        self.outer.into_iter().chain(self.inner)
509    }
510}
511
512/// A typed terminal together with its adjacent comments.
513pub trait Terminal: Spanned {
514    /// Borrows the comments preceding this terminal.
515    fn leading_trivia(&self) -> &LeadingTrivia;
516
517    /// Mutably borrows the comments preceding this terminal.
518    fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia;
519
520    /// Borrows the comments following this terminal.
521    fn trailing_trivia(&self) -> &TrailingTrivia;
522
523    /// Mutably borrows the comments following this terminal.
524    fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia;
525
526    /// Replaces the comments preceding this terminal.
527    fn set_leading_trivia(&mut self, trivia: impl IntoIterator<Item = Trivia>)
528    where
529        Self: Sized,
530    {
531        *self.leading_trivia_mut() = LeadingTrivia::new(trivia);
532    }
533
534    /// Replaces the comments and layout characters following this terminal.
535    fn set_trailing_trivia(&mut self, trivia: impl IntoIterator<Item = Trivia>)
536    where
537        Self: Sized,
538    {
539        *self.trailing_trivia_mut() = TrailingTrivia::new(trivia);
540    }
541}
542
543/// Handles identifier qualifier spans.
544fn identifier_qualifier_spans(spelling: &str, span: &Span) -> (Option<Span>, Option<Span>) {
545    let separators = spelling
546        .match_indices('$')
547        .map(|(index, _)| index)
548        .collect::<Vec<_>>();
549    let source = separators.first().and_then(|separator| {
550        let name = &spelling[..*separator];
551        (!name.is_empty() && name.bytes().all(is_identifier_byte))
552            .then(|| span.subspan(0, separator + 1))
553    });
554    let index = separators.last().and_then(|separator| {
555        let digits = &spelling[separator + 1..];
556        (!digits.is_empty() && digits.bytes().all(|byte| byte.is_ascii_digit()))
557            .then(|| span.subspan(*separator, spelling.len()))
558    });
559    (source, index)
560}
561
562/// Returns whether the value is identifier byte.
563fn is_identifier_byte(byte: u8) -> bool {
564    byte == b'_' || byte.is_ascii_alphanumeric()
565}
566
567/// Handles span for spelling.
568fn span_for_spelling(text: Arc<str>, span: Span) -> Span {
569    if span.text() == Some(text.as_ref()) {
570        span
571    } else {
572        let source = Source::with_file(span.file(), text);
573        let len = source.text().len();
574        Span::ranged(source, 0..len)
575    }
576}
577
578#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
579/// One raw M2 token tree.
580pub enum TokenTree {
581    /// A delimited group.
582    Group(TokenGroup),
583    /// A literal.
584    Literal(LiteralToken),
585    /// Punctuation.
586    Punct(Punct),
587    /// An identifier or keyword spelling.
588    Ident(IdentToken),
589}
590
591impl TokenTree {
592    /// Returns the token's source spelling when it is a flat lexical atom.
593    pub fn spelling(&self) -> Option<&str> {
594        match self {
595            Self::Literal(token) => Some(token.text()),
596            Self::Punct(token) => Some(token.text()),
597            Self::Ident(token) => Some(token.text()),
598            Self::Group(_) => None,
599        }
600    }
601
602    /// Handles description.
603    pub(crate) fn description(&self) -> String {
604        match self {
605            Self::Group(group) => group.delim_kind().to_string(),
606            token => token.spelling().unwrap_or("").to_owned(),
607        }
608    }
609
610    /// Borrows the comments attached before this atom.
611    pub fn leading_trivia(&self) -> &LeadingTrivia {
612        match self {
613            Self::Group(token) => token.leading_trivia(),
614            Self::Literal(token) => token.leading_trivia(),
615            Self::Punct(token) => token.leading_trivia(),
616            Self::Ident(token) => token.leading_trivia(),
617        }
618    }
619
620    /// Mutably borrows the comments attached before this atom.
621    pub fn leading_trivia_mut(&mut self) -> &mut LeadingTrivia {
622        match self {
623            Self::Group(token) => token.leading_trivia_mut(),
624            Self::Literal(token) => token.leading_trivia_mut(),
625            Self::Punct(token) => token.leading_trivia_mut(),
626            Self::Ident(token) => token.leading_trivia_mut(),
627        }
628    }
629
630    /// Borrows the comments attached after this atom.
631    pub fn trailing_trivia(&self) -> &TrailingTrivia {
632        match self {
633            Self::Group(token) => token.trailing_trivia(),
634            Self::Literal(token) => token.trailing_trivia(),
635            Self::Punct(token) => token.trailing_trivia(),
636            Self::Ident(token) => token.trailing_trivia(),
637        }
638    }
639
640    /// Mutably borrows the comments attached after this atom.
641    pub fn trailing_trivia_mut(&mut self) -> &mut TrailingTrivia {
642        match self {
643            Self::Group(token) => token.trailing_trivia_mut(),
644            Self::Literal(token) => token.trailing_trivia_mut(),
645            Self::Punct(token) => token.trailing_trivia_mut(),
646            Self::Ident(token) => token.trailing_trivia_mut(),
647        }
648    }
649}
650
651impl Lex for TokenTree {
652    fn to_tokens(&self, output: &mut TokenStream) {
653        output.push(self.clone());
654    }
655}
656
657#[derive(Debug, Clone, Default)]
658/// Internal state for TokenStreamData.
659struct TokenStreamData {
660    /// The trees.
661    trees: Vec<TokenTree>,
662    /// The prefix.
663    prefix: TrailingTrivia,
664    /// The suffix.
665    suffix: LeadingTrivia,
666    /// The source.
667    source: Option<Arc<Source>>,
668}
669
670/// Internal state for TokenStreamParts.
671pub(crate) struct TokenStreamParts {
672    /// The trees.
673    pub(crate) trees: Vec<TokenTree>,
674    /// The prefix.
675    pub(crate) prefix: TrailingTrivia,
676    /// The suffix.
677    pub(crate) suffix: LeadingTrivia,
678    /// The source.
679    pub(crate) source: Option<Arc<Source>>,
680}
681
682impl PartialEq for TokenStreamData {
683    fn eq(&self, other: &Self) -> bool {
684        self.trees == other.trees
685            && self.prefix == other.prefix
686            && self.suffix == other.suffix
687            && match (&self.source, &other.source) {
688                (Some(left), Some(right)) => Arc::ptr_eq(left, right),
689                (None, None) => true,
690                _ => false,
691            }
692    }
693}
694
695impl Eq for TokenStreamData {}
696
697#[derive(Debug, Clone, Default, PartialEq, Eq)]
698/// A persistent sequence of raw M2 token trees.
699///
700/// Clones and [`Self::fork`] share immutable backing storage. The first
701/// mutation of either value detaches that value through copy-on-write, so
702/// speculative consumers can retain the original stream without cloning its
703/// token trees eagerly.
704pub struct TokenStream(Arc<TokenStreamData>);
705
706impl Spanned for TokenStream {
707    fn try_span(&self) -> Option<Span> {
708        Span::join_all(
709            self.data()
710                .prefix
711                .try_span()
712                .into_iter()
713                .chain(self.iter().filter_map(Spanned::try_span))
714                .chain(self.data().suffix.try_span()),
715        )
716    }
717}
718
719impl Deref for TokenStream {
720    type Target = [TokenTree];
721
722    fn deref(&self) -> &Self::Target {
723        &self.data().trees
724    }
725}
726
727impl AsRef<[TokenTree]> for TokenStream {
728    fn as_ref(&self) -> &[TokenTree] {
729        self
730    }
731}
732
733impl TokenStream {
734    /// Creates an empty token stream.
735    pub fn new() -> Self {
736        Self::default()
737    }
738
739    /// Creates an independently mutable view over the same token storage.
740    ///
741    /// This operation is constant time. Mutating either stream preserves the
742    /// other stream and copies only the backing structures on the modified
743    /// path.
744    pub fn fork(&self) -> Self {
745        self.clone()
746    }
747
748    /// Borrows the shared backing data.
749    fn data(&self) -> &TokenStreamData {
750        &self.0
751    }
752
753    /// Borrows the shared backing data mutably.
754    fn data_mut(&mut self) -> &mut TokenStreamData {
755        Arc::make_mut(&mut self.0)
756    }
757
758    /// Converts the value into data.
759    fn into_data(self) -> TokenStreamData {
760        Arc::try_unwrap(self.0).unwrap_or_else(|data| (*data).clone())
761    }
762
763    /// Converts the value into parts.
764    pub(crate) fn into_parts(self) -> TokenStreamParts {
765        let TokenStreamData {
766            trees,
767            prefix,
768            suffix,
769            source,
770        } = self.into_data();
771        TokenStreamParts {
772            trees,
773            prefix,
774            suffix,
775            source,
776        }
777    }
778
779    /// Creates the value from parts.
780    pub(crate) fn from_parts(parts: TokenStreamParts) -> Self {
781        Self(Arc::new(TokenStreamData {
782            trees: parts.trees,
783            prefix: parts.prefix,
784            suffix: parts.suffix,
785            source: parts.source,
786        }))
787    }
788
789    /// Handles shares storage.
790    pub(crate) fn shares_storage(&self, other: &Self) -> bool {
791        Arc::ptr_eq(&self.0, &other.0)
792    }
793
794    /// Returns whether the value has trivia.
795    pub(crate) fn has_trivia(&self) -> bool {
796        !self.data().prefix.is_empty() || !self.data().suffix.is_empty()
797    }
798
799    /// Handles prefix trivia.
800    pub(crate) fn prefix_trivia(&self) -> &[Trivia] {
801        self.data().prefix.as_slice()
802    }
803
804    /// Handles suffix trivia.
805    pub(crate) fn suffix_trivia(&self) -> &[Trivia] {
806        self.data().suffix.as_slice()
807    }
808
809    /// Returns the associated source snapshot.
810    pub(crate) fn source(&self) -> Option<Arc<Source>> {
811        let mut source = self.data().source.clone();
812        coherent_stream_source(self, &mut source)
813            .then_some(source)
814            .flatten()
815    }
816
817    /// Handles set source.
818    pub(crate) fn set_source(&mut self, source: Arc<Source>) {
819        self.data_mut().source = Some(source);
820    }
821
822    /// Takes final punctuation.
823    pub(crate) fn take_final_punctuation(
824        &mut self,
825        spelling: &str,
826    ) -> Option<(Punct, TrailingTrivia)> {
827        let position = self.data().trees.len().checked_sub(1)?;
828        let TokenTree::Punct(punctuation) = self.data().trees.get(position)? else {
829            return None;
830        };
831        if punctuation.text() != spelling {
832            return None;
833        }
834        let TokenTree::Punct(mut punctuation) = self.data_mut().trees.remove(position) else {
835            unreachable!("the final significant token was punctuation")
836        };
837        let trailing_trivia = take(punctuation.trailing_trivia_mut());
838        Some((punctuation, trailing_trivia))
839    }
840
841    /// Takes leading trivia.
842    pub(crate) fn take_leading_trivia(&mut self) -> TrailingTrivia {
843        let data = self.data_mut();
844        let mut trivia = take(&mut data.prefix).into_vec();
845        trivia.extend(take(&mut data.suffix).into_vec());
846        TrailingTrivia::new(trivia)
847    }
848
849    /// Takes prefix trivia.
850    pub(crate) fn take_prefix_trivia(&mut self) -> TrailingTrivia {
851        take(&mut self.data_mut().prefix)
852    }
853
854    /// Takes suffix trivia.
855    pub(crate) fn take_suffix_trivia(&mut self) -> LeadingTrivia {
856        take(&mut self.data_mut().suffix)
857    }
858
859    /// Moves every comment onto the trailing trivia of the token it follows.
860    ///
861    /// Afterwards no token has leading trivia and the suffix is empty: comments
862    /// before the first token remain in the prefix, which a delimiter or cell
863    /// owns, and the emitted order of tokens and comments is unchanged.
864    pub(crate) fn settle_trivia(&mut self) {
865        let data = self.data_mut();
866        let mut previous: Option<&mut TokenTree> = None;
867        for token in &mut data.trees {
868            let leading = take(token.leading_trivia_mut()).into_vec();
869            match previous {
870                Some(previous) => previous.trailing_trivia_mut().as_mut_vec().extend(leading),
871                None => data.prefix.as_mut_vec().extend(leading),
872            }
873            if let TokenTree::Group(group) = token {
874                group.stream_mut().settle_trivia();
875            }
876            previous = Some(token);
877        }
878        let suffix = take(&mut data.suffix).into_vec();
879        match previous {
880            Some(last) => last.trailing_trivia_mut().as_mut_vec().extend(suffix),
881            None => data.prefix.as_mut_vec().extend(suffix),
882        }
883    }
884
885    /// Handles push.
886    pub(crate) fn push(&mut self, mut token: TokenTree) {
887        let data = self.data_mut();
888        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
889            && !group.delimiter().is_closed()
890        {
891            group.stream_mut().push(token);
892        } else {
893            token
894                .leading_trivia_mut()
895                .as_mut_vec()
896                .splice(..0, take(&mut data.suffix).into_vec());
897            data.trees.push(token);
898        }
899    }
900
901    /// Pushes line comment.
902    pub(crate) fn push_line_comment(&mut self, comment: Trivia) {
903        let data = self.data_mut();
904        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
905            && !group.delimiter().is_closed()
906        {
907            group.stream_mut().push_line_comment(comment);
908        } else if let Some(comment) = complete_line_comment(&comment) {
909            push_line_comment_block(data.suffix.as_mut_vec(), comment);
910        } else if let Some(token) = data.trees.last_mut() {
911            token.trailing_trivia_mut().as_mut_vec().push(comment);
912        } else {
913            data.prefix.as_mut_vec().push(comment);
914        }
915    }
916
917    #[doc(hidden)]
918    pub fn push_leading_trivia(&mut self, trivia: Trivia) {
919        let data = self.data_mut();
920        if let Some(TokenTree::Group(group)) = data.trees.last_mut()
921            && !group.delimiter().is_closed()
922        {
923            group.stream_mut().push_leading_trivia(trivia);
924        } else {
925            data.suffix.as_mut_vec().push(trivia);
926        }
927    }
928
929    /// Pushes block comment.
930    pub(crate) fn push_block_comment(&mut self, comment: 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_block_comment(comment);
936        } else if let Some(token) = data.trees.last_mut() {
937            token.trailing_trivia_mut().as_mut_vec().push(comment);
938        } else if !data.suffix.is_empty() {
939            data.suffix.as_mut_vec().push(comment);
940        } else {
941            data.prefix.as_mut_vec().push(comment);
942        }
943    }
944
945    /// Pushes trailing trivia.
946    pub(crate) fn push_trailing_trivia(&mut self, trivia: Trivia) {
947        let data = self.data_mut();
948        if let Some(token) = data.trees.last_mut() {
949            token.trailing_trivia_mut().as_mut_vec().push(trivia);
950        } else {
951            data.prefix.as_mut_vec().push(trivia);
952        }
953    }
954
955    /// Handles complete last group.
956    pub(crate) fn complete_last_group(&mut self, kind: DelimiterKind, close: Span) -> bool {
957        let Some(TokenTree::Group(group)) = self.data_mut().trees.last_mut() else {
958            return false;
959        };
960        if group.stream.complete_last_group(kind, close.clone()) {
961            return true;
962        }
963        if group.delim_kind() != kind || group.delimiter().is_closed() {
964            return false;
965        }
966        group.delimiter.spans.complete(close);
967        true
968    }
969
970    /// Handles last innermost.
971    pub(crate) fn last_innermost(&self) -> Option<&TokenTree> {
972        let last = self.last()?;
973        match last {
974            TokenTree::Group(group) if !group.delimiter().is_closed() => {
975                group.stream().last_innermost().or(Some(last))
976            }
977            _ => Some(last),
978        }
979    }
980
981    #[doc(hidden)]
982    pub fn starts_with_whitespace(&self) -> bool {
983        false
984    }
985
986    #[doc(hidden)]
987    pub fn ends_with_whitespace(&self) -> bool {
988        false
989    }
990
991    #[doc(hidden)]
992    pub fn ends_with_line_break(&self) -> bool {
993        self.data()
994            .trees
995            .last()
996            .is_some_and(|token| gap_after_contains(token, '\n'))
997    }
998
999    #[doc(hidden)]
1000    pub fn ends_with_semicolon(&self) -> bool {
1001        matches!(self.data().trees.last(), Some(TokenTree::Punct(token)) if token.text() == ";")
1002    }
1003
1004    /// Appends one emitted syntax fragment with any separator required to keep
1005    /// adjacent word-like fragments lexically distinct.
1006    ///
1007    /// This is the composition operation used by [`crate::quote_m2!`]. The
1008    /// fragment retains all of its internal token structure and comments.
1009    /// Rendering inserts a conventional space when independently sourced atoms
1010    /// would otherwise merge into one lexical token.
1011    #[doc(hidden)]
1012    pub fn append_fragment<T: Lex + ?Sized>(&mut self, fragment: &T) {
1013        let fragment = fragment.to_token_stream();
1014        self.extend([fragment]);
1015    }
1016
1017    /// Removes and returns the final token tree, if any.
1018    pub fn pop(&mut self) -> Option<TokenTree> {
1019        self.data_mut().trees.pop()
1020    }
1021
1022    /// Migrates source text from the shared sources retained by its spans.
1023    pub fn to_source(&self) -> String {
1024        self.to_string()
1025    }
1026}
1027
1028/// Handles complete line comment.
1029fn complete_line_comment(comment: &Trivia) -> Option<Trivia> {
1030    let span = comment.span();
1031    let (Some(start), Some(end)) = (span.start(), span.end()) else {
1032        return None;
1033    };
1034    let source = span.source();
1035    let line_start = source.text()[..start]
1036        .rfind('\n')
1037        .map_or(0, |newline| newline + 1);
1038    source.text()[line_start..start]
1039        .bytes()
1040        .all(|byte| matches!(byte, b' ' | b'\t' | b'\r'))
1041        .then(|| {
1042            Trivia::from_span(
1043                TriviaKind::LineComment,
1044                Span::ranged(Arc::clone(source), line_start..end),
1045            )
1046        })
1047}
1048
1049/// Pushes line comment block.
1050fn push_line_comment_block(comments: &mut Vec<Trivia>, comment: Trivia) {
1051    let Some(previous) = comments.last_mut() else {
1052        comments.push(comment);
1053        return;
1054    };
1055    if previous.kind() != TriviaKind::LineComment || !previous.span().shares_source(&comment.span())
1056    {
1057        comments.push(comment);
1058        return;
1059    }
1060    let (Some(previous_start), Some(previous_end), Some(comment_start), Some(comment_end)) = (
1061        previous.span().start(),
1062        previous.span().end(),
1063        comment.span().start(),
1064        comment.span().end(),
1065    ) else {
1066        comments.push(comment);
1067        return;
1068    };
1069    let previous_span = previous.span();
1070    let gap = &previous_span.source().text()[previous_end..comment_start];
1071    let same_block = gap
1072        .strip_prefix("\r\n")
1073        .or_else(|| gap.strip_prefix('\n'))
1074        .is_some_and(|indent| indent.bytes().all(|byte| matches!(byte, b' ' | b'\t')));
1075    if same_block {
1076        *previous = Trivia::from_span(
1077            TriviaKind::LineComment,
1078            Span::ranged(
1079                Arc::clone(previous.span().source()),
1080                previous_start..comment_end,
1081            ),
1082        );
1083    } else {
1084        comments.push(comment);
1085    }
1086}
1087
1088/// Handles coherent stream source.
1089fn coherent_stream_source(stream: &TokenStream, source: &mut Option<Arc<Source>>) -> bool {
1090    for trivia in stream.prefix_trivia().iter().chain(stream.suffix_trivia()) {
1091        if !record_source(trivia.span(), source) {
1092            return false;
1093        }
1094    }
1095    for token in stream.iter() {
1096        if !record_source(token.span(), source)
1097            || !token
1098                .leading_trivia()
1099                .as_slice()
1100                .iter()
1101                .chain(token.trailing_trivia().as_slice())
1102                .all(|trivia| record_source(trivia.span(), source))
1103        {
1104            return false;
1105        }
1106        if let TokenTree::Group(group) = token
1107            && !coherent_stream_source(group.stream(), source)
1108        {
1109            return false;
1110        }
1111    }
1112    true
1113}
1114
1115/// Handles record source.
1116fn record_source(span: Span, source: &mut Option<Arc<Source>>) -> bool {
1117    match source {
1118        Some(expected) => Arc::ptr_eq(expected, span.source()),
1119        None => {
1120            *source = Some(Arc::clone(span.source()));
1121            true
1122        }
1123    }
1124}
1125
1126impl Display for TokenStream {
1127    fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
1128        write_stream(formatter, self, None).map(drop)
1129    }
1130}
1131/// Handles needs separator.
1132fn needs_separator(left: &TokenTree, right: &TokenTree) -> bool {
1133    let left_span = left.span();
1134    let right_span = right.span();
1135    if left_span.shares_source(&right_span) && left_span.end() == right_span.start() {
1136        return false;
1137    }
1138    let wordlike = |tree: &TokenTree| {
1139        matches!(
1140            tree,
1141            TokenTree::Ident(_) | TokenTree::Literal(_) | TokenTree::Group(_)
1142        )
1143    };
1144    (wordlike(left) && wordlike(right))
1145        || matches!((left, right), (TokenTree::Punct(left), TokenTree::Punct(right))
1146            if punctuation_would_merge(left.text(), right.text()))
1147}
1148
1149/// Writes stream.
1150///
1151/// `previous` is the span written just before the stream, such as its opening
1152/// delimiter, so the layout following it is recovered too. Returns the span
1153/// written last.
1154fn write_stream(
1155    formatter: &mut Formatter<'_>,
1156    stream: &TokenStream,
1157    previous: Option<Span>,
1158) -> std::result::Result<Option<Span>, std::fmt::Error> {
1159    let mut previous_span = write_trivia(formatter, previous, stream.data().prefix.as_slice())?;
1160    let mut previous_atom = None::<&TokenTree>;
1161    for tree in stream {
1162        if !tree.leading_trivia().is_empty() {
1163            previous_span =
1164                write_trivia(formatter, previous_span, tree.leading_trivia().as_slice())?;
1165            previous_atom = None;
1166        }
1167        if let Some(left) = previous_span {
1168            let recovered_space = write_source_spaces(formatter, left, tree.span())?;
1169            if !recovered_space && previous_atom.is_some_and(|left| needs_separator(left, tree)) {
1170                formatter.write_str(" ")?;
1171            }
1172        }
1173        write_tree(formatter, tree)?;
1174        previous_span = Some(tree.span());
1175        previous_atom = Some(tree);
1176        if !tree.trailing_trivia().is_empty() {
1177            previous_span =
1178                write_trivia(formatter, previous_span, tree.trailing_trivia().as_slice())?;
1179            previous_atom = None;
1180        }
1181    }
1182    write_trivia(formatter, previous_span, stream.data().suffix.as_slice())
1183}
1184
1185/// Writes trivia.
1186fn write_trivia(
1187    formatter: &mut Formatter<'_>,
1188    mut previous: Option<Span>,
1189    trivia: &[Trivia],
1190) -> std::result::Result<Option<Span>, std::fmt::Error> {
1191    for item in trivia {
1192        if let Some(left) = previous {
1193            write_source_spaces(formatter, left, item.span())?;
1194        }
1195        formatter.write_str(item.text())?;
1196        previous = Some(item.span());
1197    }
1198    Ok(previous)
1199}
1200
1201/// Writes source spaces.
1202fn write_source_spaces(
1203    formatter: &mut Formatter<'_>,
1204    left: Span,
1205    right: Span,
1206) -> std::result::Result<bool, std::fmt::Error> {
1207    if !left.shares_source(&right) {
1208        return Ok(false);
1209    }
1210    let (Some(end), Some(start)) = (left.end(), right.start()) else {
1211        return Ok(false);
1212    };
1213    if end > start {
1214        return Ok(false);
1215    }
1216    let gap = &left.source().text()[end..start];
1217    if gap.bytes().all(|byte| byte.is_ascii_whitespace()) {
1218        formatter.write_str(gap)?;
1219        Ok(true)
1220    } else {
1221        Ok(false)
1222    }
1223}
1224
1225/// Writes tree.
1226fn write_tree(formatter: &mut Formatter<'_>, tree: &TokenTree) -> Result {
1227    match tree {
1228        TokenTree::Group(group) => {
1229            formatter.write_str(group.delim_kind().opening())?;
1230            let opening = group.delimiter().opening_span();
1231            let last = write_stream(formatter, &group.stream, Some(opening.clone()))?;
1232            if let Some(closing) = group.delimiter().closing_span() {
1233                write_source_spaces(formatter, last.unwrap_or(opening), closing)?;
1234                formatter.write_str(group.delim_kind().closing())?;
1235            }
1236            Ok(())
1237        }
1238        TokenTree::Literal(literal) => formatter.write_str(literal.text()),
1239        TokenTree::Punct(punct) => formatter.write_str(punct.text()),
1240        TokenTree::Ident(ident) => formatter.write_str(ident.text()),
1241    }
1242}
1243
1244/// Handles gap after contains.
1245fn gap_after_contains(token: &TokenTree, character: char) -> bool {
1246    let span = token
1247        .trailing_trivia()
1248        .as_slice()
1249        .last()
1250        .map_or_else(|| token.span(), Spanned::span);
1251    let Some(end) = span.end() else {
1252        return false;
1253    };
1254    span.source().text()[end..].contains(character)
1255}
1256
1257/// Appends anything that can emit tokens, one item at a time.
1258///
1259/// `Lex` already states which types produce tokens; this states how a
1260/// `TokenStream` accepts them, by forwarding to `Lex::to_tokens`. It
1261/// subsumes the two concrete impls this replaced (`TokenTree` and
1262/// `TokenStream` itself both implement `Lex`), and works for any other `Lex`
1263/// type without a bespoke impl.
1264impl<T: Lex> Extend<T> for TokenStream {
1265    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1266        for item in iter {
1267            item.to_tokens(self);
1268        }
1269    }
1270}
1271
1272impl FromIterator<TokenTree> for TokenStream {
1273    fn from_iter<T: IntoIterator<Item = TokenTree>>(iter: T) -> Self {
1274        Self(Arc::new(TokenStreamData {
1275            trees: iter.into_iter().collect(),
1276            prefix: TrailingTrivia::default(),
1277            suffix: LeadingTrivia::default(),
1278            source: None,
1279        }))
1280    }
1281}
1282
1283impl IntoIterator for TokenStream {
1284    type Item = TokenTree;
1285    type IntoIter = IntoIter<TokenTree>;
1286    fn into_iter(self) -> Self::IntoIter {
1287        self.into_data().trees.into_iter()
1288    }
1289}
1290
1291impl<'syntax> IntoIterator for &'syntax TokenStream {
1292    type Item = &'syntax TokenTree;
1293    type IntoIter = std::slice::Iter<'syntax, TokenTree>;
1294
1295    fn into_iter(self) -> Self::IntoIter {
1296        self.iter()
1297    }
1298}
1299
1300impl Lex for TokenStream {
1301    fn to_tokens(&self, output: &mut TokenStream) {
1302        let preserve_source =
1303            output.is_empty() && output.data().prefix.is_empty() && output.data().suffix.is_empty();
1304        for trivia in self.data().prefix.as_slice().iter().cloned() {
1305            output.push_trailing_trivia(trivia);
1306        }
1307        for token in self.iter().cloned() {
1308            output.push(token);
1309        }
1310        output
1311            .data_mut()
1312            .suffix
1313            .as_mut_vec()
1314            .extend(self.data().suffix.as_slice().iter().cloned());
1315        output.data_mut().source = preserve_source.then(|| self.source()).flatten();
1316    }
1317}
1318
1319/// Emits a typed or raw syntax value into the shared token representation.
1320pub trait Lex {
1321    /// Appends this value's token trees to `output`.
1322    fn to_tokens(&self, output: &mut TokenStream);
1323
1324    /// Emits this value into a fresh token stream.
1325    fn to_token_stream(&self) -> TokenStream {
1326        let mut output = TokenStream::new();
1327        self.to_tokens(&mut output);
1328        output
1329    }
1330
1331    /// Renders this value as normalized Macaulay2 source.
1332    fn to_m2(&self) -> String {
1333        self.to_token_stream().to_source()
1334    }
1335}
1336
1337impl<T: Lex + ?Sized> Lex for &T {
1338    fn to_tokens(&self, output: &mut TokenStream) {
1339        (*self).to_tokens(output);
1340    }
1341}
1342
1343impl<T: Lex + ?Sized> Lex for Box<T> {
1344    fn to_tokens(&self, output: &mut TokenStream) {
1345        self.as_ref().to_tokens(output);
1346    }
1347}
1348
1349impl<T: Lex> Lex for Option<T> {
1350    fn to_tokens(&self, output: &mut TokenStream) {
1351        if let Some(value) = self {
1352            value.to_tokens(output);
1353        }
1354    }
1355}
1356
1357impl<T: Lex> Lex for [T] {
1358    fn to_tokens(&self, output: &mut TokenStream) {
1359        for token in self {
1360            token.to_tokens(output);
1361        }
1362    }
1363}
1364
1365impl<T: Lex> Lex for Vec<T> {
1366    fn to_tokens(&self, output: &mut TokenStream) {
1367        self.as_slice().to_tokens(output);
1368    }
1369}
1370
1371#[cfg(test)]
1372mod tests {
1373    use crate::lex_str;
1374
1375    #[test]
1376    fn fork_shares_tokens_until_the_first_mutation() {
1377        let original = lex_str("left + right").unwrap();
1378        let mut fork = original.fork();
1379
1380        assert!(original.shares_storage(&fork));
1381        assert_eq!((&original).into_iter().count(), original.len());
1382
1383        fork.pop();
1384
1385        assert!(!original.shares_storage(&fork));
1386        assert_eq!(original.to_string(), "left + right");
1387        assert_eq!(fork.to_string(), "left +");
1388    }
1389}