Skip to main content

xidl_parser/
parser.rs

1use crate::error::ParserResult;
2use std::collections::HashMap;
3use tree_sitter::Node;
4
5pub struct ParseContext<'a> {
6    pub source: &'a [u8],
7    pub symbols: HashMap<String, String>,
8}
9
10impl<'a> ParseContext<'a> {
11    pub fn new(source: &'a [u8]) -> Self {
12        Self {
13            source,
14            symbols: HashMap::new(),
15        }
16    }
17
18    pub fn node_text(&self, node: &Node) -> ParserResult<&str> {
19        Ok(node.utf8_text(self.source)?)
20    }
21}
22
23pub trait FromTreeSitter<'a>: Sized {
24    fn from_node(node: Node<'a>, context: &mut ParseContext<'a>) -> ParserResult<Self>;
25}
26
27impl<'a> FromTreeSitter<'a> for String {
28    fn from_node(node: Node<'a>, context: &mut ParseContext<'a>) -> ParserResult<Self> {
29        Ok(context.node_text(&node)?.to_string())
30    }
31}
32
33impl<'a, T> FromTreeSitter<'a> for Box<T>
34where
35    T: FromTreeSitter<'a>,
36{
37    fn from_node(node: Node<'a>, context: &mut ParseContext<'a>) -> ParserResult<Self> {
38        Ok(Box::new(T::from_node(node, context)?))
39    }
40}
41
42pub fn parser_text(text: &str) -> ParserResult<crate::typed_ast::Specification> {
43    use crate::typed_ast::Specification;
44
45    let mut parser = tree_sitter::Parser::new();
46    parser.set_language(&tree_sitter_idl::language()).unwrap();
47
48    let tree = parser.parse(text, None).ok_or_else(|| {
49        crate::error::ParseError::TreeSitterError("Failed to parse text".to_string())
50    })?;
51
52    let root_node = tree.root_node();
53    if root_node.has_error() {
54        return Err(crate::error::ParseError::TreeSitterError(
55            "Failed to parse text".to_string(),
56        ));
57    }
58    let mut context = ParseContext::new(text.as_bytes());
59
60    Specification::from_node(root_node, &mut context)
61}
62
63#[cfg(test)]
64mod tests {
65    use super::parser_text;
66    use crate::typed_ast::{
67        Definition, TemplateTypeSpec, TypeDclInner, TypeDeclaratorInner, TypeSpec,
68    };
69
70    #[test]
71    fn parse_template_type_spec() {
72        let typed = parser_text(
73            r#"
74            module m {
75                typedef Vec<long> MyVec;
76            };
77            "#,
78        )
79        .expect("parse should succeed");
80
81        let module = match &typed.0[0] {
82            Definition::ModuleDcl(module) => module,
83            other => panic!("expected module, got {other:?}"),
84        };
85        let type_dcl = match &module.definition[0] {
86            Definition::TypeDcl(type_dcl) => type_dcl,
87            other => panic!("expected type declaration, got {other:?}"),
88        };
89        let typedef = match &type_dcl.decl {
90            TypeDclInner::TypedefDcl(typedef) => typedef,
91            other => panic!("expected typedef, got {other:?}"),
92        };
93        let template = match &typedef.decl.ty {
94            TypeDeclaratorInner::TemplateTypeSpec(TemplateTypeSpec::TemplateType(template)) => {
95                template
96            }
97            other => panic!("expected template_type, got {other:?}"),
98        };
99        assert_eq!(template.ident.0, "Vec");
100        assert_eq!(template.args.len(), 1);
101        assert!(matches!(
102            template.args[0],
103            TypeSpec::SimpleTypeSpec(crate::typed_ast::SimpleTypeSpec::BaseTypeSpec(
104                crate::typed_ast::BaseTypeSpec::IntegerType(_)
105            ))
106        ));
107    }
108}