Start work on a WASM binding
This commit is contained in:
parent
82ccc0e56d
commit
1fc0525940
11 changed files with 737 additions and 4 deletions
|
|
@ -15,7 +15,7 @@ mod grammars;
|
|||
mod nfa;
|
||||
mod node_types;
|
||||
mod npm_files;
|
||||
mod parse_grammar;
|
||||
pub mod parse_grammar;
|
||||
mod prepare_grammar;
|
||||
mod render;
|
||||
mod rules;
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ enum RuleJSON {
|
|||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct GrammarJSON {
|
||||
name: String,
|
||||
pub(crate) struct GrammarJSON {
|
||||
pub(crate) name: String,
|
||||
rules: Map<String, Value>,
|
||||
conflicts: Option<Vec<Vec<String>>>,
|
||||
externals: Option<Vec<RuleJSON>>,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ pub mod parse;
|
|||
pub mod properties;
|
||||
pub mod test;
|
||||
pub mod util;
|
||||
pub mod wasm;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
|||
use std::process::exit;
|
||||
use std::{u64, usize};
|
||||
use tree_sitter_cli::{
|
||||
config, error, generate, highlight, loader, logger, parse, properties, test,
|
||||
config, error, generate, highlight, loader, logger, parse, properties, test, wasm,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
|
|
@ -90,6 +90,11 @@ fn run() -> error::Result<()> {
|
|||
.arg(Arg::with_name("html").long("html").short("h"))
|
||||
.arg(Arg::with_name("time").long("time").short("t")),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("build-wasm")
|
||||
.about("Compile a parser to WASM")
|
||||
.arg(Arg::with_name("path").index(1).multiple(true)),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let home_dir = dirs::home_dir().expect("Failed to read home directory");
|
||||
|
|
@ -237,6 +242,9 @@ fn run() -> error::Result<()> {
|
|||
)));
|
||||
}
|
||||
}
|
||||
} else if let Some(matches) = matches.subcommand_matches("build-wasm") {
|
||||
let grammar_path = current_dir.join(matches.value_of("path").unwrap_or(""));
|
||||
wasm::compile_language_to_wasm(&grammar_path)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
72
cli/src/wasm.rs
Normal file
72
cli/src/wasm.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use super::error::{Error, Result};
|
||||
use super::generate::parse_grammar::GrammarJSON;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn compile_language_to_wasm(language_dir: &Path) -> Result<()> {
|
||||
let src_dir = language_dir.join("src");
|
||||
let grammar_json_path = src_dir.join("grammar.json");
|
||||
let grammar_json = fs::read_to_string(&grammar_json_path).map_err(|e| {
|
||||
format!(
|
||||
"Failed to read grammar file {:?} - {}",
|
||||
grammar_json_path, e
|
||||
)
|
||||
})?;
|
||||
let grammar: GrammarJSON = serde_json::from_str(&grammar_json).map_err(|e| {
|
||||
format!(
|
||||
"Failed to parse grammar file {:?} - {}",
|
||||
grammar_json_path, e
|
||||
)
|
||||
})?;
|
||||
|
||||
let mut command = Command::new("emcc");
|
||||
command.args(&[
|
||||
"-o",
|
||||
&format!("tree-sitter-{}.wasm", grammar.name),
|
||||
"-Os",
|
||||
"-s",
|
||||
"WASM=1",
|
||||
"-s",
|
||||
"SIDE_MODULE=1",
|
||||
"-s",
|
||||
&format!("EXPORTED_FUNCTIONS=[\"_tree_sitter_{}\"]", grammar.name),
|
||||
]);
|
||||
command.arg("-I").arg(&src_dir);
|
||||
|
||||
// Find source files to compile
|
||||
let entries = fs::read_dir(&src_dir)
|
||||
.map_err(|e| format!("Failed to read source directory {:?} - {}", src_dir, e))?;
|
||||
|
||||
for entry in entries {
|
||||
let entry = entry?;
|
||||
let file_name = entry.file_name();
|
||||
|
||||
// Do not compile the node.js binding file.
|
||||
if file_name
|
||||
.to_str()
|
||||
.map_or(false, |s| s.starts_with("binding"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compile any .c, .cc, or .cpp files
|
||||
if let Some(extension) = Path::new(&file_name).extension().and_then(|s| s.to_str()) {
|
||||
if extension == "c" || extension == "cc" || extension == "cpp" {
|
||||
command.arg(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let output = command
|
||||
.output()
|
||||
.map_err(|e| format!("Failed to run emcc command - {}", e))?;
|
||||
if output.status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::from(format!(
|
||||
"emcc command failed - {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue