badness_parser/bib/
core.rs1use rowan::GreenNode;
8
9use crate::bib::grammar;
10use crate::bib::lexer::lex;
11use crate::bib::syntax::SyntaxNode;
12use crate::bib::tree_builder::build_tree;
13
14#[derive(Debug, Clone)]
17pub struct Parse {
18 pub green: GreenNode,
19 pub errors: Vec<SyntaxError>,
20}
21
22impl Parse {
23 pub fn syntax(&self) -> SyntaxNode {
26 SyntaxNode::new_root(self.green.clone())
27 }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct SyntaxError {
33 pub message: String,
34 pub start: usize,
35 pub end: usize,
36}
37
38pub fn parse(input: &str) -> Parse {
40 let tokens = lex(input);
41 let (events, errors) = grammar::parse(&tokens);
42 let green = build_tree(&tokens, &events);
43 Parse { green, errors }
44}
45
46pub fn reconstruct(input: &str) -> String {
49 parse(input).syntax().to_string()
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::bib::syntax::SyntaxKind;
56
57 #[test]
58 fn reconstruct_is_identity() {
59 let input = "@article{key,\n title = {Hi},\n year = 2020,\n}\n";
60 assert_eq!(reconstruct(input), input);
61 }
62
63 #[test]
64 fn entry_has_key_and_fields() {
65 let parse = parse("@article{key, title = {Hi}}");
66 let entry = parse
67 .syntax()
68 .descendants()
69 .find(|n| n.kind() == SyntaxKind::ENTRY)
70 .expect("an ENTRY node");
71 assert!(
72 entry.children().any(|n| n.kind() == SyntaxKind::KEY),
73 "the entry should have a KEY node"
74 );
75 assert!(
76 entry.children().any(|n| n.kind() == SyntaxKind::FIELD),
77 "the entry should have a FIELD node"
78 );
79 assert!(parse.errors.is_empty());
80 }
81}