inline cont
This commit is contained in:
		
					parent
					
						
							
								b2bc575e27
							
						
					
				
			
			
				commit
				
					
						eaea5cf95c
					
				
			
		
					 2 changed files with 61 additions and 69 deletions
				
			
		
							
								
								
									
										123
									
								
								src/inline.rs
									
										
									
									
									
								
							
							
						
						
									
										123
									
								
								src/inline.rs
									
										
									
									
									
								
							| 
						 | 
					@ -57,7 +57,7 @@ pub enum Container {
 | 
				
			||||||
    Delete,
 | 
					    Delete,
 | 
				
			||||||
    Emphasis,
 | 
					    Emphasis,
 | 
				
			||||||
    Strong,
 | 
					    Strong,
 | 
				
			||||||
    //Mark,
 | 
					    Mark,
 | 
				
			||||||
    // smart quoting
 | 
					    // smart quoting
 | 
				
			||||||
    SingleQuoted,
 | 
					    SingleQuoted,
 | 
				
			||||||
    DoubleQuoted,
 | 
					    DoubleQuoted,
 | 
				
			||||||
| 
						 | 
					@ -65,12 +65,18 @@ pub enum Container {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, PartialEq, Eq)]
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
pub enum Event {
 | 
					pub enum Event {
 | 
				
			||||||
    Enter(Container),
 | 
					    Enter(Container, OpenerState),
 | 
				
			||||||
    Exit(Container),
 | 
					    Exit(Container),
 | 
				
			||||||
    Atom(Atom),
 | 
					    Atom(Atom),
 | 
				
			||||||
    Node(Node),
 | 
					    Node(Node),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub enum OpenerState {
 | 
				
			||||||
 | 
					    Unclosed,
 | 
				
			||||||
 | 
					    Closed,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy)]
 | 
					#[derive(Debug, Clone, Copy)]
 | 
				
			||||||
pub enum Dir {
 | 
					pub enum Dir {
 | 
				
			||||||
    Open,
 | 
					    Open,
 | 
				
			||||||
| 
						 | 
					@ -79,9 +85,8 @@ pub enum Dir {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Parser<'s> {
 | 
					pub struct Parser<'s> {
 | 
				
			||||||
    openers: Vec<Container>,
 | 
					    openers: Vec<(Container, usize)>,
 | 
				
			||||||
    close_containers: Option<usize>,
 | 
					    events: std::collections::VecDeque<Event>,
 | 
				
			||||||
    next: Option<Event>,
 | 
					 | 
				
			||||||
    span: Span,
 | 
					    span: Span,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    lexer: std::iter::Peekable<lex::Lexer<'s>>,
 | 
					    lexer: std::iter::Peekable<lex::Lexer<'s>>,
 | 
				
			||||||
| 
						 | 
					@ -91,8 +96,7 @@ impl<'s> Parser<'s> {
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            openers: Vec::new(),
 | 
					            openers: Vec::new(),
 | 
				
			||||||
            close_containers: None,
 | 
					            events: std::collections::VecDeque::new(),
 | 
				
			||||||
            next: None,
 | 
					 | 
				
			||||||
            span: Span::new(0, 0),
 | 
					            span: Span::new(0, 0),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lexer: lex::Lexer::new("").peekable(),
 | 
					            lexer: lex::Lexer::new("").peekable(),
 | 
				
			||||||
| 
						 | 
					@ -206,8 +210,8 @@ impl<'s> Parser<'s> {
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceAsterisk) => Some((Strong, Dir::Close)),
 | 
					            lex::Kind::Close(Delimiter::BraceAsterisk) => Some((Strong, Dir::Close)),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceCaret) => Some((Superscript, Dir::Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceCaret) => Some((Superscript, Dir::Open)),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceCaret) => Some((Superscript, Dir::Close)),
 | 
					            lex::Kind::Close(Delimiter::BraceCaret) => Some((Superscript, Dir::Close)),
 | 
				
			||||||
            //lex::Kind::Open(Delimiter::BraceEqual) => Some((Mark, Dir::Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceEqual) => Some((Mark, Dir::Open)),
 | 
				
			||||||
            //lex::Kind::Close(Delimiter::BraceEqual) => Some((Mark, Dir::Close)),
 | 
					            lex::Kind::Close(Delimiter::BraceEqual) => Some((Mark, Dir::Close)),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BraceHyphen) => Some((Delete, Dir::Open)),
 | 
					            lex::Kind::Open(Delimiter::BraceHyphen) => Some((Delete, Dir::Open)),
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceHyphen) => Some((Delete, Dir::Close)),
 | 
					            lex::Kind::Close(Delimiter::BraceHyphen) => Some((Delete, Dir::Close)),
 | 
				
			||||||
            lex::Kind::Open(Delimiter::BracePlus) => Some((Insert, Dir::Open)),
 | 
					            lex::Kind::Open(Delimiter::BracePlus) => Some((Insert, Dir::Open)),
 | 
				
			||||||
| 
						 | 
					@ -218,16 +222,28 @@ impl<'s> Parser<'s> {
 | 
				
			||||||
            lex::Kind::Close(Delimiter::BraceUnderscore) => Some((Emphasis, Dir::Close)),
 | 
					            lex::Kind::Close(Delimiter::BraceUnderscore) => Some((Emphasis, Dir::Close)),
 | 
				
			||||||
            _ => None,
 | 
					            _ => None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        .and_then(|(cont, dir)| {
 | 
					        .map(|(cont_new, dir)| {
 | 
				
			||||||
            if matches!(dir, Dir::Close | Dir::Both) && self.openers.contains(&cont) {
 | 
					            self.openers
 | 
				
			||||||
                self.close_containers = self.openers.iter().rposition(|o| *o == cont);
 | 
					                .iter()
 | 
				
			||||||
                Some(Event::Exit(self.openers.pop().unwrap()))
 | 
					                .rposition(|(c, _)| *c == cont_new)
 | 
				
			||||||
            } else if matches!(dir, Dir::Open | Dir::Both) {
 | 
					                .and_then(|o| {
 | 
				
			||||||
                self.openers.push(cont);
 | 
					                    matches!(dir, Dir::Close | Dir::Both).then(|| {
 | 
				
			||||||
                Some(Event::Enter(cont))
 | 
					                        let (cont_open, e) = &mut self.openers[o];
 | 
				
			||||||
            } else {
 | 
					                        assert_eq!(*cont_open, cont_new);
 | 
				
			||||||
                None
 | 
					                        if let Event::Enter(cont_ev, state_ev) = &mut self.events[*e] {
 | 
				
			||||||
            }
 | 
					                            assert_eq!(*cont_ev, cont_new);
 | 
				
			||||||
 | 
					                            *state_ev = OpenerState::Closed;
 | 
				
			||||||
 | 
					                            self.openers.drain(o..);
 | 
				
			||||||
 | 
					                            Event::Exit(cont_new)
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            panic!()
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .unwrap_or_else(|| {
 | 
				
			||||||
 | 
					                    self.openers.push((cont_new, self.events.len()));
 | 
				
			||||||
 | 
					                    Event::Enter(cont_new, OpenerState::Unclosed)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -236,31 +252,16 @@ impl<'s> Iterator for Parser<'s> {
 | 
				
			||||||
    type Item = Event;
 | 
					    type Item = Event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
					    fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
        self.next.take().or_else(|| {
 | 
					        while self.events.is_empty() || !self.openers.is_empty() {
 | 
				
			||||||
            self.close_containers
 | 
					            if let Some(ev) = self.parse_event() {
 | 
				
			||||||
                .and_then(|i| {
 | 
					                self.events.push_back(ev);
 | 
				
			||||||
                    if i < self.openers.len() {
 | 
					            } else {
 | 
				
			||||||
                        Some(Event::Exit(self.openers.pop().unwrap()))
 | 
					                break;
 | 
				
			||||||
                    } else {
 | 
					            }
 | 
				
			||||||
                        self.close_containers = None;
 | 
					        }
 | 
				
			||||||
                        None
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                .or_else(|| {
 | 
					 | 
				
			||||||
                    let mut current = self.parse_event();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if let Some(Event::Node(Node { kind: Str, span })) = &mut current {
 | 
					        // TODO merge str/unclosed enters
 | 
				
			||||||
                        self.next = self.parse_event();
 | 
					        self.events.pop_front()
 | 
				
			||||||
                        while let Some(Event::Node(Node { kind: Str, span: s })) = self.next {
 | 
					 | 
				
			||||||
                            *span = span.union(s);
 | 
					 | 
				
			||||||
                            self.next = self.parse_event();
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    current
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                .or_else(|| self.openers.pop().map(Event::Exit))
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -272,6 +273,7 @@ mod test {
 | 
				
			||||||
    use super::Container::*;
 | 
					    use super::Container::*;
 | 
				
			||||||
    use super::Event::*;
 | 
					    use super::Event::*;
 | 
				
			||||||
    use super::NodeKind::*;
 | 
					    use super::NodeKind::*;
 | 
				
			||||||
 | 
					    use super::OpenerState::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    macro_rules! test_parse {
 | 
					    macro_rules! test_parse {
 | 
				
			||||||
        ($($st:ident,)? $src:expr $(,$($token:expr),* $(,)?)?) => {
 | 
					        ($($st:ident,)? $src:expr $(,$($token:expr),* $(,)?)?) => {
 | 
				
			||||||
| 
						 | 
					@ -317,13 +319,13 @@ mod test {
 | 
				
			||||||
    fn container_basic() {
 | 
					    fn container_basic() {
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "_abc_",
 | 
					            "_abc_",
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Closed),
 | 
				
			||||||
            Node(Str.span(1, 4)),
 | 
					            Node(Str.span(1, 4)),
 | 
				
			||||||
            Exit(Emphasis)
 | 
					            Exit(Emphasis)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "{_abc_}",
 | 
					            "{_abc_}",
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Closed),
 | 
				
			||||||
            Node(Str.span(2, 5)),
 | 
					            Node(Str.span(2, 5)),
 | 
				
			||||||
            Exit(Emphasis)
 | 
					            Exit(Emphasis)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
| 
						 | 
					@ -333,16 +335,16 @@ mod test {
 | 
				
			||||||
    fn container_nest() {
 | 
					    fn container_nest() {
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "{_{_abc_}_}",
 | 
					            "{_{_abc_}_}",
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Closed),
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Closed),
 | 
				
			||||||
            Node(Str.span(4, 7)),
 | 
					            Node(Str.span(4, 7)),
 | 
				
			||||||
            Exit(Emphasis),
 | 
					            Exit(Emphasis),
 | 
				
			||||||
            Exit(Emphasis)
 | 
					            Exit(Emphasis)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "*_abc_*",
 | 
					            "*_abc_*",
 | 
				
			||||||
            Enter(Strong),
 | 
					            Enter(Strong, Closed),
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Closed),
 | 
				
			||||||
            Node(Str.span(2, 5)),
 | 
					            Node(Str.span(2, 5)),
 | 
				
			||||||
            Exit(Emphasis),
 | 
					            Exit(Emphasis),
 | 
				
			||||||
            Exit(Strong)
 | 
					            Exit(Strong)
 | 
				
			||||||
| 
						 | 
					@ -358,31 +360,22 @@ mod test {
 | 
				
			||||||
    fn container_close_parent() {
 | 
					    fn container_close_parent() {
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "{*{_abc*}",
 | 
					            "{*{_abc*}",
 | 
				
			||||||
            Enter(Strong),
 | 
					            Enter(Strong, Closed),
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Unclosed),
 | 
				
			||||||
            Node(Str.span(4, 7)),
 | 
					            Node(Str.span(4, 7)),
 | 
				
			||||||
            Exit(Emphasis),
 | 
					            Exit(Strong),
 | 
				
			||||||
            Exit(Strong)
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn container_close_block() {
 | 
					    fn container_close_block() {
 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!("{_abc", Enter(Emphasis, Unclosed), Node(Str.span(2, 5)));
 | 
				
			||||||
            "{_abc",
 | 
					 | 
				
			||||||
            Enter(Emphasis),
 | 
					 | 
				
			||||||
            Node(Str.span(2, 5)),
 | 
					 | 
				
			||||||
            Exit(Emphasis)
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        test_parse!(
 | 
					        test_parse!(
 | 
				
			||||||
            "{_{*{_abc",
 | 
					            "{_{*{_abc",
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Unclosed),
 | 
				
			||||||
            Enter(Strong),
 | 
					            Enter(Strong, Unclosed),
 | 
				
			||||||
            Enter(Emphasis),
 | 
					            Enter(Emphasis, Unclosed),
 | 
				
			||||||
            Node(Str.span(6, 9)),
 | 
					            Node(Str.span(6, 9)),
 | 
				
			||||||
            Exit(Emphasis),
 | 
					 | 
				
			||||||
            Exit(Strong),
 | 
					 | 
				
			||||||
            Exit(Emphasis),
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ pub enum Delimiter {
 | 
				
			||||||
    Brace,
 | 
					    Brace,
 | 
				
			||||||
    BraceAsterisk,
 | 
					    BraceAsterisk,
 | 
				
			||||||
    BraceCaret,
 | 
					    BraceCaret,
 | 
				
			||||||
    //BraceEqual,
 | 
					    BraceEqual,
 | 
				
			||||||
    BraceHyphen,
 | 
					    BraceHyphen,
 | 
				
			||||||
    BracePlus,
 | 
					    BracePlus,
 | 
				
			||||||
    BraceTilde,
 | 
					    BraceTilde,
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ impl<'s> Lexer<'s> {
 | 
				
			||||||
                let explicit = match self.peek() {
 | 
					                let explicit = match self.peek() {
 | 
				
			||||||
                    '*' => Some(Open(BraceAsterisk)),
 | 
					                    '*' => Some(Open(BraceAsterisk)),
 | 
				
			||||||
                    '^' => Some(Open(BraceCaret)),
 | 
					                    '^' => Some(Open(BraceCaret)),
 | 
				
			||||||
                    //'=' => Some(Open(BraceEqual)),
 | 
					                    '=' => Some(Open(BraceEqual)),
 | 
				
			||||||
                    '-' => Some(Open(BraceHyphen)),
 | 
					                    '-' => Some(Open(BraceHyphen)),
 | 
				
			||||||
                    '+' => Some(Open(BracePlus)),
 | 
					                    '+' => Some(Open(BracePlus)),
 | 
				
			||||||
                    '~' => Some(Open(BraceTilde)),
 | 
					                    '~' => Some(Open(BraceTilde)),
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,7 @@ impl<'s> Lexer<'s> {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            '*' => self.maybe_eat_close_brace(Asterisk, BraceAsterisk),
 | 
					            '*' => self.maybe_eat_close_brace(Asterisk, BraceAsterisk),
 | 
				
			||||||
            '^' => self.maybe_eat_close_brace(Caret, BraceCaret),
 | 
					            '^' => self.maybe_eat_close_brace(Caret, BraceCaret),
 | 
				
			||||||
            //'=' => self.maybe_eat_close_brace(Equal, BraceEqual),
 | 
					            '=' => self.maybe_eat_close_brace(Equal, BraceEqual),
 | 
				
			||||||
            '+' => self.maybe_eat_close_brace(Plus, BracePlus),
 | 
					            '+' => self.maybe_eat_close_brace(Plus, BracePlus),
 | 
				
			||||||
            '~' => self.maybe_eat_close_brace(Tilde, BraceTilde),
 | 
					            '~' => self.maybe_eat_close_brace(Tilde, BraceTilde),
 | 
				
			||||||
            '_' => self.maybe_eat_close_brace(Underscore, BraceUnderscore),
 | 
					            '_' => self.maybe_eat_close_brace(Underscore, BraceUnderscore),
 | 
				
			||||||
| 
						 | 
					@ -178,7 +178,6 @@ impl<'s> Lexer<'s> {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            '=' => Sym(Equal),
 | 
					 | 
				
			||||||
            '!' => Sym(Exclaim),
 | 
					            '!' => Sym(Exclaim),
 | 
				
			||||||
            '%' => Sym(Percentage),
 | 
					            '%' => Sym(Percentage),
 | 
				
			||||||
            '<' => Sym(Lt),
 | 
					            '<' => Sym(Lt),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue