feat(dsl)!: support other JS runtimes
This commit is contained in:
parent
d77279d2e3
commit
055d0cbd34
7 changed files with 72 additions and 31 deletions
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
|
|
@ -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
1
Cargo.lock
generated
|
|
@ -1432,6 +1432,7 @@ dependencies = [
|
|||
"tree-sitter-tags",
|
||||
"tree-sitter-tests-proc-macro",
|
||||
"unindent",
|
||||
"url",
|
||||
"walkdir",
|
||||
"wasmparser 0.206.0",
|
||||
"webbrowser",
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 .",
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue