feat(dsl)!: support other JS runtimes

This commit is contained in:
ObserverOfTime 2024-05-24 23:53:33 +03:00 committed by GitHub
parent d77279d2e3
commit 055d0cbd34
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 72 additions and 31 deletions

View file

@ -101,9 +101,9 @@ jobs:
echo "image = \"$image\"" >> Cross.toml
echo "CROSS_CONFIG=$PWD/Cross.toml" >> $GITHUB_ENV
echo "FROM ghcr.io/cross-rs/$target:edge" >> Dockerfile
echo "ENV DEBIAN_FRONTEND=noninteractive" >> Dockerfile
echo "RUN apt-get update && apt-get install -y nodejs" >> Dockerfile
echo "FROM ghcr.io/cross-rs/$target:edge" >> Dockerfile
echo "RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash -" >> Dockerfile
echo "RUN apt-get update && apt-get -y install nodejs" >> Dockerfile
docker build -t $image .
- name: Setup env extras

1
Cargo.lock generated
View file

@ -1432,6 +1432,7 @@ dependencies = [
"tree-sitter-tags",
"tree-sitter-tests-proc-macro",
"unindent",
"url",
"walkdir",
"wasmparser 0.206.0",
"webbrowser",

View file

@ -60,6 +60,9 @@ tree-sitter-highlight.workspace = true
tree-sitter-loader.workspace = true
tree-sitter-tags.workspace = true
[target."cfg(windows)".dependencies]
url = "2.5.0"
[dev-dependencies]
tree_sitter_proc_macro = { path = "src/tests/proc_macro", package = "tree-sitter-tests-proc-macro" }

View file

@ -13,6 +13,9 @@
"lexer"
],
"main": "lib/api/index.js",
"engines": {
"node": ">=12.0.0"
},
"scripts": {
"install": "node install.js",
"prepack": "cp ../../LICENSE ../README.md .",

View file

@ -223,7 +223,7 @@ function RuleBuilder(ruleMap) {
}
function grammar(baseGrammar, options) {
let inherits = null;
let inherits = undefined;
if (!options) {
options = baseGrammar;
@ -421,7 +421,7 @@ function grammar(baseGrammar, options) {
return {
grammar: {
name,
...(inherits ? ( inherits ) : {}),
inherits,
word,
rules,
extras,
@ -456,18 +456,32 @@ function checkPrecedence(value) {
}
}
global.alias = alias;
global.blank = blank;
global.choice = choice;
global.optional = optional;
global.prec = prec;
global.repeat = repeat;
global.repeat1 = repeat1;
global.seq = seq;
global.sym = sym;
global.token = token;
global.grammar = grammar;
global.field = field;
function getEnv(name) {
if (globalThis.process) return process.env[name]; // Node/Bun
if (globalThis.Deno) return Deno.env.get(name); // Deno
throw Error("Unsupported JS runtime");
}
const result = require(process.env.TREE_SITTER_GRAMMAR_PATH);
process.stdout.write(JSON.stringify(result.grammar, null, null));
globalThis.alias = alias;
globalThis.blank = blank;
globalThis.choice = choice;
globalThis.optional = optional;
globalThis.prec = prec;
globalThis.repeat = repeat;
globalThis.repeat1 = repeat1;
globalThis.seq = seq;
globalThis.sym = sym;
globalThis.token = token;
globalThis.grammar = grammar;
globalThis.field = field;
const result = await import(getEnv("TREE_SITTER_GRAMMAR_PATH"));
const output = JSON.stringify(result.default?.grammar ?? result.grammar);
if (globalThis.process) { // Node/Bun
process.stdout.write(output);
} else if (globalThis.Deno) { // Deno
Deno.stdout.writeSync(new TextEncoder().encode(output));
} else {
throw Error("Unsupported JS runtime");
}

View file

@ -189,35 +189,54 @@ pub fn load_grammar_file(grammar_path: &Path, js_runtime: Option<&str>) -> Resul
fn load_js_grammar_file(grammar_path: &Path, js_runtime: Option<&str>) -> Result<String> {
let grammar_path = fs::canonicalize(grammar_path)?;
#[cfg(windows)]
let grammar_path = url::Url::from_file_path(grammar_path)
.expect("Failed to convert path to URL")
.to_string();
let js_runtime = js_runtime.unwrap_or("node");
let mut node_process = Command::new(js_runtime)
let mut js_command = Command::new(js_runtime);
match js_runtime {
"node" => {
js_command.args(["--input-type=module", "-"]);
}
"bun" => {
js_command.arg("-");
}
"deno" => {
js_command.args(["run", "--allow-all", "-"]);
}
_ => {}
}
let mut js_process = js_command
.env("TREE_SITTER_GRAMMAR_PATH", grammar_path)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.with_context(|| format!("Failed to run `{js_runtime}`"))?;
let mut node_stdin = node_process
let mut js_stdin = js_process
.stdin
.take()
.with_context(|| format!("Failed to open stdin for {js_runtime}"))?;
let cli_version = Version::parse(env!("CARGO_PKG_VERSION"))
.with_context(|| "Could not parse this package's version as semver.")?;
write!(
node_stdin,
"global.TREE_SITTER_CLI_VERSION_MAJOR = {};
global.TREE_SITTER_CLI_VERSION_MINOR = {};
global.TREE_SITTER_CLI_VERSION_PATCH = {};",
js_stdin,
"globalThis.TREE_SITTER_CLI_VERSION_MAJOR = {};
globalThis.TREE_SITTER_CLI_VERSION_MINOR = {};
globalThis.TREE_SITTER_CLI_VERSION_PATCH = {};",
cli_version.major, cli_version.minor, cli_version.patch,
)
.with_context(|| format!("Failed to write tree-sitter version to {js_runtime}'s stdin"))?;
let javascript_code = include_bytes!("./dsl.js");
node_stdin
.write(javascript_code)
js_stdin
.write(include_bytes!("./dsl.js"))
.with_context(|| format!("Failed to write grammar dsl to {js_runtime}'s stdin"))?;
drop(node_stdin);
let output = node_process
drop(js_stdin);
let output = js_process
.wait_with_output()
.with_context(|| format!("Failed to read output from {js_runtime}"))?;
match output.status.code() {

View file

@ -92,7 +92,8 @@ struct Generate {
long,
value_name = "EXECUTABLE",
env = "TREE_SITTER_JS_RUNTIME",
help = "The path to the JavaScript runtime to use for generating parsers"
default_value = "node",
help = "The name or path of the JavaScript runtime to use for generating parsers"
)]
pub js_runtime: Option<String>,
}