inline: replace Delim by Opener
no need to have a delimiter for closer, only opener needs to be stored in stack
This commit is contained in:
		
					parent
					
						
							
								ed5aed3759
							
						
					
				
			
			
				commit
				
					
						66d821f03e
					
				
			
		
					 1 changed files with 89 additions and 78 deletions
				
			
		
							
								
								
									
										167
									
								
								src/inline.rs
									
										
									
									
									
								
							
							
						
						
									
										167
									
								
								src/inline.rs
									
										
									
									
									
								
							| 
						 | 
					@ -176,7 +176,7 @@ pub struct VerbatimState {
 | 
				
			||||||
pub struct Parser<I: Iterator + Clone> {
 | 
					pub struct Parser<I: Iterator + Clone> {
 | 
				
			||||||
    input: Input<I>,
 | 
					    input: Input<I>,
 | 
				
			||||||
    /// Stack with kind and index of _potential_ openers for containers.
 | 
					    /// Stack with kind and index of _potential_ openers for containers.
 | 
				
			||||||
    openers: Vec<(Delim, usize)>,
 | 
					    openers: Vec<(Opener, usize)>,
 | 
				
			||||||
    /// Buffer queue for next events. Events are buffered until no modifications due to future
 | 
					    /// Buffer queue for next events. Events are buffered until no modifications due to future
 | 
				
			||||||
    /// characters are needed.
 | 
					    /// characters are needed.
 | 
				
			||||||
    events: std::collections::VecDeque<Event>,
 | 
					    events: std::collections::VecDeque<Event>,
 | 
				
			||||||
| 
						 | 
					@ -468,33 +468,28 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn parse_container(&mut self, first: &lex::Token) -> Option<()> {
 | 
					    fn parse_container(&mut self, first: &lex::Token) -> Option<()> {
 | 
				
			||||||
        let (delim, dir) = Delim::from_token(first)?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.openers
 | 
					        self.openers
 | 
				
			||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
            .rposition(|(d, _)| delim.closes(*d))
 | 
					            .rposition(|(o, _)| o.closed_by(first.kind))
 | 
				
			||||||
            .and_then(|o| {
 | 
					            .and_then(|o| {
 | 
				
			||||||
                if matches!(dir, Dir::Open) {
 | 
					                let (opener, e) = self.openers[o];
 | 
				
			||||||
 | 
					                let e_attr = e;
 | 
				
			||||||
 | 
					                let e_opener = e + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if e_opener == self.events.len() - 1 {
 | 
				
			||||||
 | 
					                    // empty container
 | 
				
			||||||
                    return None;
 | 
					                    return None;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                let whitespace_after = self.events.back().map_or(false, |ev| {
 | 
					                let whitespace_after = self.events.back().map_or(false, |ev| {
 | 
				
			||||||
                    matches!(ev.kind, EventKind::Whitespace | EventKind::Atom(Softbreak))
 | 
					                    matches!(ev.kind, EventKind::Whitespace | EventKind::Atom(Softbreak))
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                if matches!(dir, Dir::Both) && whitespace_after {
 | 
					                if opener.bidirectional() && whitespace_after {
 | 
				
			||||||
                    return None;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let (d, e) = self.openers[o];
 | 
					 | 
				
			||||||
                let e_attr = e;
 | 
					 | 
				
			||||||
                let e_opener = e + 1;
 | 
					 | 
				
			||||||
                if e_opener == self.events.len() - 1 {
 | 
					 | 
				
			||||||
                    // empty container
 | 
					 | 
				
			||||||
                    return None;
 | 
					                    return None;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let inner_span = self.events[e_opener].span.between(self.input.span);
 | 
					                let inner_span = self.events[e_opener].span.between(self.input.span);
 | 
				
			||||||
                self.openers.drain(o..);
 | 
					                self.openers.drain(o..);
 | 
				
			||||||
                let mut closed = match DelimEventKind::from(d) {
 | 
					                let mut closed = match DelimEventKind::from(opener) {
 | 
				
			||||||
                    DelimEventKind::Container(cont) => {
 | 
					                    DelimEventKind::Container(cont) => {
 | 
				
			||||||
                        self.events[e_opener].kind = EventKind::Enter(cont);
 | 
					                        self.events[e_opener].kind = EventKind::Enter(cont);
 | 
				
			||||||
                        self.push(EventKind::Exit(cont))
 | 
					                        self.push(EventKind::Exit(cont))
 | 
				
			||||||
| 
						 | 
					@ -538,10 +533,8 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
				
			||||||
                closed
 | 
					                closed
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .or_else(|| {
 | 
					            .or_else(|| {
 | 
				
			||||||
                if matches!(dir, Dir::Close) {
 | 
					                let opener = Opener::from_token(first.kind)?;
 | 
				
			||||||
                    return None;
 | 
					                if opener.bidirectional()
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if matches!(dir, Dir::Both)
 | 
					 | 
				
			||||||
                    && self
 | 
					                    && self
 | 
				
			||||||
                        .input
 | 
					                        .input
 | 
				
			||||||
                        .peek()
 | 
					                        .peek()
 | 
				
			||||||
| 
						 | 
					@ -549,7 +542,7 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return None;
 | 
					                    return None;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if matches!(delim, Delim::SingleQuoted | Delim::DoubleQuoted)
 | 
					                if matches!(opener, Opener::SingleQuoted | Opener::DoubleQuoted)
 | 
				
			||||||
                    && self
 | 
					                    && self
 | 
				
			||||||
                        .events
 | 
					                        .events
 | 
				
			||||||
                        .back()
 | 
					                        .back()
 | 
				
			||||||
| 
						 | 
					@ -557,19 +550,19 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return None;
 | 
					                    return None;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                self.openers.push((delim, self.events.len()));
 | 
					                self.openers.push((opener, self.events.len()));
 | 
				
			||||||
                // push dummy event in case attributes are encountered after closing delimiter
 | 
					                // push dummy event in case attributes are encountered after closing delimiter
 | 
				
			||||||
                self.push_sp(
 | 
					                self.push_sp(
 | 
				
			||||||
                    EventKind::Placeholder,
 | 
					                    EventKind::Placeholder,
 | 
				
			||||||
                    Span::empty_at(self.input.span.start()),
 | 
					                    Span::empty_at(self.input.span.start()),
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
                // use non-opener for now, replace if closed later
 | 
					                // use non-opener for now, replace if closed later
 | 
				
			||||||
                self.push(match delim {
 | 
					                self.push(match opener {
 | 
				
			||||||
                    Delim::SingleQuoted => EventKind::Atom(Quote {
 | 
					                    Opener::SingleQuoted => EventKind::Atom(Quote {
 | 
				
			||||||
                        ty: QuoteType::Single,
 | 
					                        ty: QuoteType::Single,
 | 
				
			||||||
                        left: false,
 | 
					                        left: false,
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
                    Delim::DoubleQuoted => EventKind::Atom(Quote {
 | 
					                    Opener::DoubleQuoted => EventKind::Atom(Quote {
 | 
				
			||||||
                        ty: QuoteType::Double,
 | 
					                        ty: QuoteType::Double,
 | 
				
			||||||
                        left: true,
 | 
					                        left: true,
 | 
				
			||||||
                    }),
 | 
					                    }),
 | 
				
			||||||
| 
						 | 
					@ -691,7 +684,7 @@ enum SpanType {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
					#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
				
			||||||
enum Delim {
 | 
					enum Opener {
 | 
				
			||||||
    Span(SpanType),
 | 
					    Span(SpanType),
 | 
				
			||||||
    Strong(Directionality),
 | 
					    Strong(Directionality),
 | 
				
			||||||
    Emphasis(Directionality),
 | 
					    Emphasis(Directionality),
 | 
				
			||||||
| 
						 | 
					@ -704,54 +697,72 @@ enum Delim {
 | 
				
			||||||
    DoubleQuoted,
 | 
					    DoubleQuoted,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy)]
 | 
					impl Opener {
 | 
				
			||||||
enum Dir {
 | 
					    fn from_token(kind: lex::Kind) -> Option<Self> {
 | 
				
			||||||
    Open,
 | 
					 | 
				
			||||||
    Close,
 | 
					 | 
				
			||||||
    Both,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Delim {
 | 
					 | 
				
			||||||
    fn from_token(token: &lex::Token) -> Option<(Self, Dir)> {
 | 
					 | 
				
			||||||
        use Delim::*;
 | 
					 | 
				
			||||||
        use Dir::{Both, Close, Open};
 | 
					 | 
				
			||||||
        use Directionality::{Bi, Uni};
 | 
					        use Directionality::{Bi, Uni};
 | 
				
			||||||
 | 
					        use Opener::*;
 | 
				
			||||||
        use SpanType::{General, Image};
 | 
					        use SpanType::{General, Image};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match token.kind {
 | 
					        match kind {
 | 
				
			||||||
            lex::Kind::Sym(Symbol::Asterisk) => Some((Strong(Bi), Both)),
 | 
					            lex::Kind::Sym(Symbol::Asterisk) => Some(Strong(Bi)),
 | 
				
			||||||
            lex::Kind::Sym(Symbol::Underscore) => Some((Emphasis(Bi), Both)),
 | 
					            lex::Kind::Sym(Symbol::Underscore) => Some(Emphasis(Bi)),
 | 
				
			||||||
            lex::Kind::Sym(Symbol::Caret) => Some((Superscript(Bi), Both)),
 | 
					            lex::Kind::Sym(Symbol::Caret) => Some(Superscript(Bi)),
 | 
				
			||||||
            lex::Kind::Sym(Symbol::Tilde) => Some((Subscript(Bi), Both)),
 | 
					            lex::Kind::Sym(Symbol::Tilde) => Some(Subscript(Bi)),
 | 
				
			||||||
            lex::Kind::Sym(Symbol::Quote1) => Some((SingleQuoted, Both)),
 | 
					            lex::Kind::Sym(Symbol::Quote1) => Some(SingleQuoted),
 | 
				
			||||||
            lex::Kind::Sym(Symbol::Quote2) => Some((DoubleQuoted, Both)),
 | 
					            lex::Kind::Sym(Symbol::Quote2) => Some(DoubleQuoted),
 | 
				
			||||||
            lex::Kind::Sym(Symbol::ExclaimBracket) => Some((Span(Image), Open)),
 | 
					            lex::Kind::Sym(Symbol::ExclaimBracket) => Some(Span(Image)),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::Bracket) => Some((Span(General), Open)),
 | 
					            lex::Kind::Open(Delimiter::Bracket) => Some(Span(General)),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::Bracket) => Some((Span(General), Close)),
 | 
					            lex::Kind::Open(Delimiter::BraceAsterisk) => Some(Strong(Uni)),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceAsterisk) => Some((Strong(Uni), Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceUnderscore) => Some(Emphasis(Uni)),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceAsterisk) => Some((Strong(Uni), Close)),
 | 
					            lex::Kind::Open(Delimiter::BraceCaret) => Some(Superscript(Uni)),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceUnderscore) => Some((Emphasis(Uni), Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceTilde) => Some(Subscript(Uni)),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceUnderscore) => Some((Emphasis(Uni), Close)),
 | 
					            lex::Kind::Open(Delimiter::BraceEqual) => Some(Mark),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceCaret) => Some((Superscript(Uni), Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceHyphen) => Some(Delete),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceCaret) => Some((Superscript(Uni), Close)),
 | 
					            lex::Kind::Open(Delimiter::BracePlus) => Some(Insert),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceTilde) => Some((Subscript(Uni), Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceQuote1) => Some(SingleQuoted),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceTilde) => Some((Subscript(Uni), Close)),
 | 
					            lex::Kind::Open(Delimiter::BraceQuote2) => Some(DoubleQuoted),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceEqual) => Some((Mark, Open)),
 | 
					 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceEqual) => Some((Mark, Close)),
 | 
					 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceHyphen) => Some((Delete, Open)),
 | 
					 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceHyphen) => Some((Delete, Close)),
 | 
					 | 
				
			||||||
            lex::Kind::Open(Delimiter::BracePlus) => Some((Insert, Open)),
 | 
					 | 
				
			||||||
            lex::Kind::Close(Delimiter::BracePlus) => Some((Insert, Close)),
 | 
					 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceQuote1) => Some((SingleQuoted, Open)),
 | 
					 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceQuote1) => Some((SingleQuoted, Close)),
 | 
					 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceQuote2) => Some((DoubleQuoted, Open)),
 | 
					 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceQuote2) => Some((DoubleQuoted, Close)),
 | 
					 | 
				
			||||||
            _ => None,
 | 
					            _ => None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn closes(self, opener: Delim) -> bool {
 | 
					    fn closed_by(&self, kind: lex::Kind) -> bool {
 | 
				
			||||||
        self == opener || matches!((opener, self), (Delim::Span(..), Delim::Span(..)))
 | 
					        use Directionality::{Bi, Uni};
 | 
				
			||||||
 | 
					        use Opener::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Span(..) => matches!(kind, lex::Kind::Close(Delimiter::Bracket)),
 | 
				
			||||||
 | 
					            Strong(Bi) => matches!(kind, lex::Kind::Sym(Symbol::Asterisk)),
 | 
				
			||||||
 | 
					            Strong(Uni) => matches!(kind, lex::Kind::Close(Delimiter::BraceAsterisk)),
 | 
				
			||||||
 | 
					            Emphasis(Bi) => matches!(kind, lex::Kind::Sym(Symbol::Underscore)),
 | 
				
			||||||
 | 
					            Emphasis(Uni) => matches!(kind, lex::Kind::Close(Delimiter::BraceUnderscore)),
 | 
				
			||||||
 | 
					            Superscript(Bi) => matches!(kind, lex::Kind::Sym(Symbol::Caret)),
 | 
				
			||||||
 | 
					            Superscript(Uni) => matches!(kind, lex::Kind::Close(Delimiter::BraceCaret)),
 | 
				
			||||||
 | 
					            Subscript(Bi) => matches!(kind, lex::Kind::Sym(Symbol::Tilde)),
 | 
				
			||||||
 | 
					            Subscript(Uni) => matches!(kind, lex::Kind::Close(Delimiter::BraceTilde)),
 | 
				
			||||||
 | 
					            Mark => matches!(kind, lex::Kind::Close(Delimiter::BraceEqual)),
 | 
				
			||||||
 | 
					            Delete => matches!(kind, lex::Kind::Close(Delimiter::BraceHyphen)),
 | 
				
			||||||
 | 
					            Insert => matches!(kind, lex::Kind::Close(Delimiter::BracePlus)),
 | 
				
			||||||
 | 
					            SingleQuoted => matches!(
 | 
				
			||||||
 | 
					                kind,
 | 
				
			||||||
 | 
					                lex::Kind::Sym(Symbol::Quote1) | lex::Kind::Close(Delimiter::BraceQuote1)
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            DoubleQuoted => matches!(
 | 
				
			||||||
 | 
					                kind,
 | 
				
			||||||
 | 
					                lex::Kind::Sym(Symbol::Quote2) | lex::Kind::Close(Delimiter::BraceQuote2)
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn bidirectional(&self) -> bool {
 | 
				
			||||||
 | 
					        matches!(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            Opener::Strong(Directionality::Bi)
 | 
				
			||||||
 | 
					                | Opener::Emphasis(Directionality::Bi)
 | 
				
			||||||
 | 
					                | Opener::Superscript(Directionality::Bi)
 | 
				
			||||||
 | 
					                | Opener::Subscript(Directionality::Bi)
 | 
				
			||||||
 | 
					                | Opener::SingleQuoted
 | 
				
			||||||
 | 
					                | Opener::DoubleQuoted
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -761,19 +772,19 @@ enum DelimEventKind {
 | 
				
			||||||
    Quote(QuoteType),
 | 
					    Quote(QuoteType),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<Delim> for DelimEventKind {
 | 
					impl From<Opener> for DelimEventKind {
 | 
				
			||||||
    fn from(d: Delim) -> Self {
 | 
					    fn from(d: Opener) -> Self {
 | 
				
			||||||
        match d {
 | 
					        match d {
 | 
				
			||||||
            Delim::Span(ty) => Self::Span(ty),
 | 
					            Opener::Span(ty) => Self::Span(ty),
 | 
				
			||||||
            Delim::Strong(..) => Self::Container(Strong),
 | 
					            Opener::Strong(..) => Self::Container(Strong),
 | 
				
			||||||
            Delim::Emphasis(..) => Self::Container(Emphasis),
 | 
					            Opener::Emphasis(..) => Self::Container(Emphasis),
 | 
				
			||||||
            Delim::Superscript(..) => Self::Container(Superscript),
 | 
					            Opener::Superscript(..) => Self::Container(Superscript),
 | 
				
			||||||
            Delim::Subscript(..) => Self::Container(Subscript),
 | 
					            Opener::Subscript(..) => Self::Container(Subscript),
 | 
				
			||||||
            Delim::Mark => Self::Container(Mark),
 | 
					            Opener::Mark => Self::Container(Mark),
 | 
				
			||||||
            Delim::Delete => Self::Container(Delete),
 | 
					            Opener::Delete => Self::Container(Delete),
 | 
				
			||||||
            Delim::Insert => Self::Container(Insert),
 | 
					            Opener::Insert => Self::Container(Insert),
 | 
				
			||||||
            Delim::SingleQuoted => Self::Quote(QuoteType::Single),
 | 
					            Opener::SingleQuoted => Self::Quote(QuoteType::Single),
 | 
				
			||||||
            Delim::DoubleQuoted => Self::Quote(QuoteType::Double),
 | 
					            Opener::DoubleQuoted => Self::Quote(QuoteType::Double),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue