1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! This crate provides OCaml language support for the [tree-sitter][] parsing
//! library. There are separate languages for implementation, (`.ml`),
//! interfaces (`.mli`) and types.
//!
//! Typically, you will use [`LANGUAGE_OCAML`][LANGUAGE_OCAML] to add this language
//! to a tree-sitter [`Parser`][Parser], and then use the parser to parse some code:
//!
//! ```
//! let code = r#"
//!   module M = struct
//!     let x = 0
//!   end
//! "#;
//! let mut parser = tree_sitter::Parser::new();
//! let language = tree_sitter_ocaml::LANGUAGE_OCAML;
//! parser
//!     .set_language(&language.into())
//!     .expect("Error loading OCaml language");
//! let tree = parser.parse(code, None).unwrap();
//! assert!(!tree.root_node().has_error());
//! ```
//!
//! Use [`LANGUAGE_OCAML_INTERFACE`][LANGUAGE_OCAML_INTERFACE] to parse interface
//! files (with `.mli` extension) and [`LANGUAGE_OCAML_TYPE`][LANGUAGE_OCAML_TYPE]
//! to parse type signatures.
//!
//! [LANGUAGE_OCAML]: constant.LANGUAGE_OCAML.html
//! [LANGUAGE_OCAML_INTERFACE]: constant.LANGUAGE_OCAML_INTERFACE.html
//! [LANGUAGE_OCAML_TYPE]: constant.LANGUAGE_OCAML_TYPE.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/

use tree_sitter_language::LanguageFn;

extern "C" {
    fn tree_sitter_ocaml() -> *const ();
    fn tree_sitter_ocaml_interface() -> *const ();
    fn tree_sitter_ocaml_type() -> *const ();
}

/// The tree-sitter [`LanguageFn`][LanguageFn] for OCaml.
///
/// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html
pub const LANGUAGE_OCAML: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_ocaml) };

/// The tree-sitter [`LanguageFn`] for OCaml interfaces.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub const LANGUAGE_OCAML_INTERFACE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_ocaml_interface) };

/// The tree-sitter [`LanguageFn`] for OCaml types.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub const LANGUAGE_OCAML_TYPE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_ocaml_type) };

/// The content of the [`node-types.json`][] file for OCaml.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const OCAML_NODE_TYPES: &str = include_str!("../../grammars/ocaml/src/node-types.json");

/// The content of the [`node-types.json`][] file for OCaml interfaces.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const INTERFACE_NODE_TYPES: &str = include_str!("../../grammars/interface/src/node-types.json");

/// The content of the [`node-types.json`][] file for OCaml types.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const TYPE_NODE_TYPES: &str = include_str!("../../grammars/type/src/node-types.json");

/// The syntax highlighting query for OCaml.
pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm");

/// The local-variable syntax highlighting query for OCaml.
pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm");

/// The symbol tagging query for OCaml.
pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");

#[cfg(test)]
mod tests {
    #[test]
    fn test_ocaml() {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(&super::LANGUAGE_OCAML.into())
            .expect("Error loading OCaml parser");

        let code = r#"
            module M = struct
              let x = 0
            end
        "#;

        let tree = parser.parse(code, None).unwrap();
        let root = tree.root_node();
        assert!(!root.has_error());
    }

    #[test]
    fn test_ocaml_interface() {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(&super::LANGUAGE_OCAML_INTERFACE.into())
            .expect("Error loading OCaml interface parser");

        let code = r#"
            module M : sig
              val x : int
            end
        "#;

        let tree = parser.parse(code, None).unwrap();
        let root = tree.root_node();
        assert!(!root.has_error());
    }

    #[test]
    fn test_ocaml_type() {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(&super::LANGUAGE_OCAML_TYPE.into())
            .expect("Error loading OCaml type parser");

        let code = r#"int list"#;

        let tree = parser.parse(code, None).unwrap();
        let root = tree.root_node();
        assert!(!root.has_error());
    }
}