Extract content parser state to its own module
This commit is contained in:
parent
3571e8d355
commit
de5b3dd377
8 changed files with 112 additions and 99 deletions
|
|
@ -1,5 +1,3 @@
|
|||
use std::collections::{HashMap};
|
||||
|
||||
use crate::{prelude::*, types::Config};
|
||||
use super::{Parseable as _, Token, LexMap};
|
||||
use token::{
|
||||
|
|
@ -7,12 +5,13 @@ use token::{
|
|||
preformat::PreFormat, literal::Literal, code::Code, oblique::Oblique,
|
||||
};
|
||||
use lexeme::Lexeme;
|
||||
use context::{Context, Block, Inline};
|
||||
use context::{Block, Inline};
|
||||
|
||||
pub mod token;
|
||||
pub mod lexeme;
|
||||
pub mod segment;
|
||||
pub mod context;
|
||||
pub mod state;
|
||||
|
||||
const LEXMAP: LexMap = &[
|
||||
(LineBreak::probe, |lexeme| {
|
||||
|
|
@ -25,7 +24,7 @@ const LEXMAP: LexMap = &[
|
|||
|
||||
fn lex(text: &str, map: LexMap, config: &Config) -> Vec<Token> {
|
||||
let mut tokens: Vec<Token> = Vec::new();
|
||||
let mut state = State::new();
|
||||
let mut state = state::State::new();
|
||||
|
||||
let segments = segment::segment(text);
|
||||
let lexemes = Lexeme::collect(&segments);
|
||||
|
|
@ -142,76 +141,6 @@ fn lex(text: &str, map: LexMap, config: &Config) -> Vec<Token> {
|
|||
tokens
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct State {
|
||||
context: Context,
|
||||
dom_ids: HashMap<String, Vec<String>>,
|
||||
buffers: Buffers,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Buffers {
|
||||
anchor: AnchorBuffer,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct AnchorBuffer {
|
||||
candidate: Anchor,
|
||||
text: String,
|
||||
destination: String,
|
||||
}
|
||||
|
||||
impl AnchorBuffer {
|
||||
fn clear(&mut self) {
|
||||
self.candidate = Anchor::default();
|
||||
self.text = String::new();
|
||||
self.destination = String::new();
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AnchorBuffer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let display_text = if self.text.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("text: {:?}", self.text)
|
||||
};
|
||||
let display_destination = if self.destination.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!(", dest: {:?}", self.destination)
|
||||
};
|
||||
|
||||
let display_text_and_destination =
|
||||
format!("{display_text}{display_destination}");
|
||||
|
||||
write!(
|
||||
f,
|
||||
"AnchorBuffer [{display_text_and_destination}] >> {}",
|
||||
self.candidate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new() -> State {
|
||||
State {
|
||||
context: Context {
|
||||
inline: Inline::None,
|
||||
block: Block::None,
|
||||
},
|
||||
dom_ids: HashMap::new(),
|
||||
buffers: Buffers {
|
||||
anchor: AnchorBuffer {
|
||||
candidate: Anchor::default(),
|
||||
text: String::new(),
|
||||
destination: String::new(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(tokens: &[Token]) -> String {
|
||||
tokens.iter().map(Token::render).collect::<String>()
|
||||
}
|
||||
|
|
@ -222,7 +151,10 @@ pub(super) fn read(text: &str, config: &Config) -> String {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{types::Graph, syntax::content::parser::token::header::Level};
|
||||
use crate::{
|
||||
types::Graph,
|
||||
syntax::content::parser::{state::State, token::header::Level},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
@ -458,14 +390,8 @@ mod tests {
|
|||
#[test]
|
||||
#[should_panic(expected = "End of input with open header")]
|
||||
fn end_with_open_header() {
|
||||
let default_state = State::new();
|
||||
let state = State {
|
||||
context: Context {
|
||||
block: Block::Header(1),
|
||||
..default_state.context
|
||||
},
|
||||
..default_state
|
||||
};
|
||||
let mut state = State::new();
|
||||
state.context.block = Block::Header(1);
|
||||
|
||||
context::close(&state, &mut vec![]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::syntax::content::parser::{
|
||||
State,
|
||||
state::State,
|
||||
token::{Token, paragraph::Paragraph, preformat::PreFormat},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
use crate::{
|
||||
prelude::*,
|
||||
syntax::content::parser::{
|
||||
State, context::Inline, lexeme::Lexeme, token::Token,
|
||||
state::State, context::Inline, lexeme::Lexeme, token::Token,
|
||||
},
|
||||
};
|
||||
|
||||
/// Handles open anchor contexts until an anchor token is fully parsed.
|
||||
///
|
||||
/// This function is only called if the current inline context is Anchor.
|
||||
///
|
||||
/// A return of `true` will trigger a continue in the outer parser,
|
||||
/// skipping any further parsing of the current lexeme.
|
||||
///
|
||||
/// # Panics
|
||||
/// This function will panic if can't determine the destination of an anchor.
|
||||
/// If it can't determine the destination of an anchor.
|
||||
pub fn parse(
|
||||
lexeme: &Lexeme,
|
||||
state: &mut State,
|
||||
|
|
|
|||
76
src/syntax/content/parser/state.rs
Normal file
76
src/syntax/content/parser/state.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use std::collections::{HashMap};
|
||||
|
||||
use crate::syntax::content::parser::{
|
||||
token::{anchor::Anchor},
|
||||
context::{Context, Block, Inline},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct State {
|
||||
pub context: Context,
|
||||
pub dom_ids: HashMap<String, Vec<String>>,
|
||||
pub buffers: Buffers,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Buffers {
|
||||
pub anchor: AnchorBuffer,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AnchorBuffer {
|
||||
pub candidate: Anchor,
|
||||
pub text: String,
|
||||
pub destination: String,
|
||||
}
|
||||
|
||||
impl AnchorBuffer {
|
||||
pub fn clear(&mut self) {
|
||||
self.candidate = Anchor::default();
|
||||
self.text = String::new();
|
||||
self.destination = String::new();
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AnchorBuffer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let display_text = if self.text.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("text: {:?}", self.text)
|
||||
};
|
||||
let display_destination = if self.destination.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!(", dest: {:?}", self.destination)
|
||||
};
|
||||
|
||||
let display_text_and_destination =
|
||||
format!("{display_text}{display_destination}");
|
||||
|
||||
write!(
|
||||
f,
|
||||
"AnchorBuffer [{display_text_and_destination}] >> {}",
|
||||
self.candidate,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> State {
|
||||
State {
|
||||
context: Context {
|
||||
inline: Inline::None,
|
||||
block: Block::None,
|
||||
},
|
||||
dom_ids: HashMap::new(),
|
||||
buffers: Buffers {
|
||||
anchor: AnchorBuffer {
|
||||
candidate: Anchor::default(),
|
||||
text: String::new(),
|
||||
destination: String::new(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,12 +45,14 @@ impl std::fmt::Display for Anchor {
|
|||
use crate::dev::wrap;
|
||||
|
||||
let display_destination = match self.destination {
|
||||
Some(ref destination) => { if destination.is_empty() {
|
||||
"<empty>"
|
||||
} else {
|
||||
destination
|
||||
}},
|
||||
None => "<unknown>"
|
||||
Some(ref destination) => {
|
||||
if destination.is_empty() {
|
||||
"<empty>"
|
||||
} else {
|
||||
destination
|
||||
}
|
||||
},
|
||||
None => "<unknown>",
|
||||
};
|
||||
|
||||
let mut tail = String::new();
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ impl std::fmt::Display for Header {
|
|||
|
||||
let display_dom_id = match self.dom_id {
|
||||
Some(ref dom_id) => format!(" DOM ID {dom_id}"),
|
||||
None => String::new()
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
write!(
|
||||
|
|
|
|||
|
|
@ -43,8 +43,14 @@ impl Parseable for Paragraph {
|
|||
impl std::fmt::Display for Paragraph {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let display_open_state = match self.open {
|
||||
Some(open_state) => { if open_state { "open" } else { "closed" } },
|
||||
None => "unknown"
|
||||
Some(open_state) => {
|
||||
if open_state {
|
||||
"open"
|
||||
} else {
|
||||
"closed"
|
||||
}
|
||||
},
|
||||
None => "unknown",
|
||||
};
|
||||
write!(f, "Paragraph [{display_open_state}]")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,8 +38,13 @@ impl std::fmt::Display for Span {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let display_open_state = match self.open {
|
||||
Some(ref open_state) => {
|
||||
if *open_state { "open" } else { "closed" }},
|
||||
None => "unknown"
|
||||
if *open_state {
|
||||
"open"
|
||||
} else {
|
||||
"closed"
|
||||
}
|
||||
},
|
||||
None => "unknown",
|
||||
};
|
||||
write!(f, "Span [{display_open_state}]")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue