1use serde::Serialize;
2use wasm_bindgen::prelude::*;
3
4#[derive(Serialize)]
5struct WasmError {
6 message: String,
7 start: u32,
8 end: u32,
9}
10
11#[derive(Serialize)]
12struct ParseOutput {
13 ast: serde_json::Value,
14 errors: Vec<WasmError>,
15 formatted: String,
16}
17
18fn php_version_from_str(s: &str) -> Option<php_rs_parser::PhpVersion> {
19 match s {
20 "7.4" => Some(php_rs_parser::PhpVersion::Php74),
21 "8.0" => Some(php_rs_parser::PhpVersion::Php80),
22 "8.1" => Some(php_rs_parser::PhpVersion::Php81),
23 "8.2" => Some(php_rs_parser::PhpVersion::Php82),
24 "8.3" => Some(php_rs_parser::PhpVersion::Php83),
25 "8.4" => Some(php_rs_parser::PhpVersion::Php84),
26 "8.5" => Some(php_rs_parser::PhpVersion::Php85),
27 _ => None,
28 }
29}
30
31#[wasm_bindgen]
36pub fn parse(source: &str, version: Option<String>) -> Result<JsValue, JsError> {
37 let php_version = version
38 .as_deref()
39 .and_then(php_version_from_str)
40 .unwrap_or(php_rs_parser::PhpVersion::Php85);
41
42 let arena = bumpalo::Bump::new();
43 let result = php_rs_parser::parse_versioned(&arena, source, php_version);
44
45 let errors: Vec<WasmError> = result
46 .errors
47 .iter()
48 .map(|e| {
49 let span = e.span();
50 WasmError {
51 message: e.to_string(),
52 start: span.start,
53 end: span.end,
54 }
55 })
56 .collect();
57
58 let ast = serde_json::to_value(&result.program).unwrap_or(serde_json::Value::Null);
59 let formatted = php_printer::pretty_print(&result.program);
60
61 let output = ParseOutput {
62 ast,
63 errors,
64 formatted,
65 };
66 let serializer = serde_wasm_bindgen::Serializer::json_compatible();
67 Ok(output.serialize(&serializer)?)
68}
69
70#[wasm_bindgen]
72pub fn format(source: &str) -> String {
73 let arena = bumpalo::Bump::new();
74 let result = php_rs_parser::parse(&arena, source);
75 php_printer::pretty_print(&result.program)
76}
77
78#[wasm_bindgen]
80pub fn parser_version() -> String {
81 env!("CARGO_PKG_VERSION").to_string()
82}
83
84#[wasm_bindgen]
86pub fn build_commit() -> String {
87 option_env!("BUILD_COMMIT").unwrap_or("unknown").to_string()
88}