From 0e689657b744d03a735a43cfa53121a6a172064a Mon Sep 17 00:00:00 2001 From: Alyssa Verkade Date: Tue, 18 Feb 2020 19:18:19 -0800 Subject: [PATCH] Add a language linkage declaration to parsers Previously, in order to compile a `tree-sitter` grammar that contained c++ source in the parser (ie the `scanner.cc` file), you would have to compile the `parser.c` file separately from the c++ files. For example, in rust this would result in a `build.rs` close to the following: ``` extern crate cc; fn main() { let dir: PathBuf = ["tree-sitter-ruby", "src"].iter().collect(); cc::Build::new() .include(&dir) .cpp(true) .file(dir.join("scanner.cc")) // NOTE: must have a name that differs from the c static lib .compile("tree-sitter-ruby-scanner"); cc::Build::new() .include(&dir) .file(dir.join("parser.c")) // NOTE: must have a name that differs from the c++ static lib .compile("tree-sitter-ruby-parser"); } ``` This was necessary at the time for the following grammars: `ruby`, `php`, `python`, `embedded-template`, `html`, `cpp`, `ocaml`, `bash`, `agda`, and `haskell`. To solve this, we specify an `extern "C"` language linkage declaration to the functions that must be linked against to compile a parser with the scanner, making parsers linkable against c++ source. On all major compilers (gcc, clang, and msvc) this should be the only change needed due to the combination of clang and gcc both supporting designated initialization for years and msvc 2019 adopting designated initializers as a part of the C++20 conformance push. Subsequently, for rust projects, the necessary `build.rs` would become (which also brings these parsers into sync with the current docs): ``` extern crate cc; fn main() { let dir: PathBuf = ["tree-sitter-ruby", "src"].iter().collect(); cc::Build::new() .include(&dir) .cpp(true) .file(dir.join("scanner.cc")) .file(dir.join("parser.c")) .compile("tree-sitter-ruby"); } ``` --- cli/src/generate/render.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cli/src/generate/render.rs b/cli/src/generate/render.rs index 08803b1f..824c3bcf 100644 --- a/cli/src/generate/render.rs +++ b/cli/src/generate/render.rs @@ -1058,6 +1058,10 @@ impl Generator { let language_function_name = format!("tree_sitter_{}", self.language_name); let external_scanner_name = format!("{}_external_scanner", language_function_name); + add_line!(self, "#ifdef __cplusplus"); + add_line!(self, r#"extern "C" {{"#); + add_line!(self, "#endif"); + if !self.syntax_grammar.external_tokens.is_empty() { add_line!(self, "void *{}_create(void);", external_scanner_name); add_line!(self, "void {}_destroy(void *);", external_scanner_name); @@ -1183,6 +1187,9 @@ impl Generator { add_line!(self, "return &language;"); dedent!(self); add_line!(self, "}}"); + add_line!(self, "#ifdef __cplusplus"); + add_line!(self, "}}"); + add_line!(self, "#endif"); } fn get_parse_action_list_id(