Extract content parser state to its own module

This commit is contained in:
Juno Takano 2026-01-05 11:29:24 -03:00
commit de5b3dd377
8 changed files with 112 additions and 99 deletions

View file

@ -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![]);
}

View file

@ -1,5 +1,5 @@
use crate::syntax::content::parser::{
State,
state::State,
token::{Token, paragraph::Paragraph, preformat::PreFormat},
};

View file

@ -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,

View 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(),
},
},
}
}
}

View file

@ -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();

View file

@ -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!(

View file

@ -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}]")
}

View file

@ -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}]")
}