use super::helpers::{collect_line_tokens, extract_annotation_header_tokens, extract_line_token};
use crate::lex::parsing::ir::{NodeType, ParseNode, ParseNodePayload};
use crate::lex::token::{LineContainer, LineType, Token};
use std::ops::Range;
pub(in crate::lex::parsing::parser::builder) fn build_verbatim_block(
tokens: &[LineContainer],
subject_idx: usize,
content_range: Range<usize>,
closing_idx: usize,
) -> Result<ParseNode, String> {
let subject_token = extract_line_token(&tokens[subject_idx])?.clone();
let mut content_lines = Vec::new();
for idx in content_range {
if let Some(container) = tokens.get(idx) {
collect_line_tokens(container, &mut content_lines);
}
}
let closing_token = extract_line_token(&tokens[closing_idx])?;
if !matches!(closing_token.line_type, LineType::DataMarkerLine) {
return Err("Verbatim blocks must end with a closing annotation (:: label ::)".to_string());
}
let header_tokens = extract_annotation_header_tokens(closing_token)?;
let is_table = header_tokens.iter().find_map(|(token, _)| match token {
Token::Text(text) => Some(text.as_str()),
_ => None,
}) == Some("table");
let (node_type, payload) = if is_table {
(
NodeType::Table,
ParseNodePayload::Table {
subject: subject_token,
content_lines,
config_annotation_tokens: Some(header_tokens),
},
)
} else {
(
NodeType::VerbatimBlock,
ParseNodePayload::VerbatimBlock {
subject: subject_token,
content_lines,
closing_data_tokens: header_tokens,
},
)
};
Ok(ParseNode::new(node_type, vec![], vec![]).with_payload(payload))
}