Generate binding.gyp, binding.cc, and index.js

This commit is contained in:
Max Brunsfeld 2019-01-16 13:53:01 -08:00
parent 564c5e39b6
commit a0a3903f76
6 changed files with 96 additions and 8 deletions

View file

@ -12,6 +12,7 @@ use std::process::{Command, Stdio};
mod build_tables;
mod grammars;
mod nfa;
mod npm_files;
mod parse_grammar;
mod prepare_grammar;
mod properties;
@ -36,17 +37,30 @@ pub fn generate_parser_in_directory(
if !properties_only {
let grammar_path = grammar_path.map_or(repo_path.join("grammar.js"), |s| s.into());
let grammar_json = load_grammar_file(&grammar_path);
let c_code =
let (language_name, c_code) =
generate_parser_for_grammar_with_opts(&grammar_json, minimize, state_ids_to_log)?;
fs::create_dir_all("src")?;
fs::write(repo_path.join("src").join("parser.c"), c_code)?;
let repo_src_path = repo_path.join("src");
fs::create_dir_all(&repo_src_path)?;
fs::write(&repo_src_path.join("parser.c"), c_code)?;
let binding_cc_path = repo_src_path.join("binding.cc");
if !binding_cc_path.exists() {
fs::write(&binding_cc_path, npm_files::binding_cc(&language_name))?;
}
let binding_gyp_path = repo_path.join("binding.gyp");
if !binding_gyp_path.exists() {
fs::write(&binding_gyp_path, npm_files::binding_gyp(&language_name))?;
}
let index_js_path = repo_path.join("index.js");
if !index_js_path.exists() {
fs::write(&index_js_path, npm_files::index_js(&language_name))?;
}
}
properties::generate_property_sheets(repo_path)?;
Ok(())
}
#[cfg(test)]
pub fn generate_parser_for_grammar(grammar_json: &String) -> Result<String> {
pub fn generate_parser_for_grammar(grammar_json: &String) -> Result<(String, String)> {
let grammar_json = JSON_COMMENT_REGEX.replace_all(grammar_json, "\n");
generate_parser_for_grammar_with_opts(&grammar_json, true, Vec::new())
}
@ -55,7 +69,7 @@ fn generate_parser_for_grammar_with_opts(
grammar_json: &str,
minimize: bool,
state_ids_to_log: Vec<usize>,
) -> Result<String> {
) -> Result<(String, String)> {
let input_grammar = parse_grammar(grammar_json)?;
let (syntax_grammar, lexical_grammar, inlines, simple_aliases) =
prepare_grammar(&input_grammar)?;
@ -67,7 +81,7 @@ fn generate_parser_for_grammar_with_opts(
minimize,
state_ids_to_log,
)?;
Ok(render_c_code(
let c_code = render_c_code(
&input_grammar.name,
parse_table,
main_lex_table,
@ -76,7 +90,8 @@ fn generate_parser_for_grammar_with_opts(
syntax_grammar,
lexical_grammar,
simple_aliases,
))
);
Ok((input_grammar.name, c_code))
}
fn load_grammar_file(grammar_path: &PathBuf) -> String {

View file

@ -0,0 +1,18 @@
use std::str;
const BINDING_CC_TEMPLATE: &'static str = include_str!("./templates/binding.cc");
const BINDING_GYP_TEMPLATE: &'static str = include_str!("./templates/binding.gyp");
const INDEX_JS_TEMPLATE: &'static str = include_str!("./templates/index.js");
const PARSER_NAME_PLACEHOLDER: &'static str = "PARSER_NAME";
pub fn binding_cc(parser_name: &str) -> String {
BINDING_CC_TEMPLATE.replace(PARSER_NAME_PLACEHOLDER, parser_name)
}
pub fn binding_gyp(parser_name: &str) -> String {
BINDING_GYP_TEMPLATE.replace(PARSER_NAME_PLACEHOLDER, parser_name)
}
pub fn index_js(parser_name: &str) -> String {
INDEX_JS_TEMPLATE.replace(PARSER_NAME_PLACEHOLDER, parser_name)
}

View file

@ -0,0 +1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_PARSER_NAME();
namespace {
NAN_METHOD(New) {}
void Init(Handle<Object> exports, Handle<Object> module) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Local<Function> constructor = tpl->GetFunction();
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_PARSER_NAME());
instance->Set(Nan::New("name").ToLocalChecked(), Nan::New("PARSER_NAME").ToLocalChecked());
module->Set(Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_PARSER_NAME_binding, Init)
} // namespace

View file

@ -0,0 +1,18 @@
{
"targets": [
{
"target_name": "tree_sitter_PARSER_NAME_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"src/parser.c",
"src/binding.cc"
],
"cflags_c": [
"-std=c99",
]
}
]
}

View file

@ -0,0 +1,9 @@
try {
module.exports = require("./build/Release/tree_sitter_PARSER_NAME_binding");
} catch (error) {
try {
module.exports = require("./build/Debug/tree_sitter_PARSER_NAME_binding");
} catch (_) {
throw error
}
}

View file

@ -126,7 +126,7 @@ fn test_feature_corpus_files() {
}
} else {
let corpus_path = test_path.join("corpus.txt");
let c_code = generate_result.unwrap();
let c_code = generate_result.unwrap().1;
let language = get_test_language(language_name, c_code, &test_path);
let test = parse_tests(&corpus_path).unwrap();
parser.set_language(language).unwrap();