use tree_sitter::{Parser, Tree};
use super::Grammar;
use super::errors::CjkfmtParseError;
use super::ffi::{tree_sitter_json, tree_sitter_markdown, tree_sitter_markdown_inline};
pub fn parse(grammar: Grammar, content: &str) -> Result<Tree, CjkfmtParseError> {
let language = unsafe {
match grammar {
Grammar::Json => tree_sitter_json(),
Grammar::Markdown => tree_sitter_markdown(),
Grammar::MarkdownInline => tree_sitter_markdown_inline(),
}
};
let mut parser = Parser::new();
parser.set_language(&language)?;
let tree = parser
.parse(content, None)
.ok_or_else(|| CjkfmtParseError::ParseError("failed to parse".to_string()))?;
Ok(tree)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn markdown_inline_grammar_parses_plain_text() {
let tree = parse(Grammar::MarkdownInline, "漢A").unwrap();
assert_eq!(tree.root_node().kind(), "inline");
assert!(!tree.root_node().has_error());
}
#[test]
fn markdown_inline_grammar_exposes_code_span() {
let tree = parse(Grammar::MarkdownInline, "`漢A`").unwrap();
let root = tree.root_node();
let code_span = root.named_child(0).expect("code span should be named");
assert_eq!(code_span.kind(), "code_span");
assert_eq!(code_span.byte_range(), 0..6);
}
#[test]
fn markdown_inline_grammar_exposes_link_text_and_destination() {
let source = "[漢A](https://example.test/漢A)";
let tree = parse(Grammar::MarkdownInline, source).unwrap();
let link = tree
.root_node()
.named_child(0)
.expect("link should be named");
assert_eq!(link.kind(), "inline_link");
let child_kinds: Vec<_> = (0..link.named_child_count() as u32)
.map(|index| link.named_child(index).unwrap().kind())
.collect();
assert_eq!(child_kinds, ["link_text", "link_destination"]);
assert_eq!(link.named_child(0).unwrap().byte_range(), 1..5);
assert_eq!(link.named_child(1).unwrap().byte_range(), 7..32);
}
}