From 3d49dad921b8ef694dbdd63bc375736354764021 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 28 Jul 2024 21:47:00 -0400 Subject: [PATCH] super simple includes using a pest parser --- .gitignore | 1 + Cargo.lock | 212 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 8 ++ LICENSE | 21 +++++ shaders/base.wgsl | 6 ++ shaders/out.wgsl | 10 +++ shaders/simple.wgsl | 3 + src/main.rs | 74 ++++++++++++++++ src/wgsl.pest | 16 ++++ 9 files changed, 351 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 shaders/base.wgsl create mode 100644 shaders/out.wgsl create mode 100644 shaders/simple.wgsl create mode 100644 src/main.rs create mode 100644 src/wgsl.pest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..4c13558 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,212 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pest" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shader_prepoc" +version = "0.1.0" +dependencies = [ + "pest", + "pest_derive", +] + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7493878 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "shader_prepoc" +version = "0.1.0" +edition = "2021" + +[dependencies] +pest = "2.7.11" +pest_derive = "2.7.11" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5696651 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 SeanOMik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/shaders/base.wgsl b/shaders/base.wgsl new file mode 100644 index 0000000..55ca48c --- /dev/null +++ b/shaders/base.wgsl @@ -0,0 +1,6 @@ +#import "simple.wgsl" + +fn main() -> vec4 { + let a = do_something_cool(10.0); + return vec4(vec3(a), 1.0); +} \ No newline at end of file diff --git a/shaders/out.wgsl b/shaders/out.wgsl new file mode 100644 index 0000000..e7a47cf --- /dev/null +++ b/shaders/out.wgsl @@ -0,0 +1,10 @@ +// ==== START OF INCLUDE OF 'shaders/simple.wgsl' ==== +fn do_something_cool(in: f32) -> f32 { + return in * 2.0; +} +// ==== END OF INCLUDE OF 'shaders/simple.wgsl' ==== + +fn main() -> vec4 { + let a = do_something_cool(10.0); + return vec4(vec3(a), 1.0); +} diff --git a/shaders/simple.wgsl b/shaders/simple.wgsl new file mode 100644 index 0000000..5570102 --- /dev/null +++ b/shaders/simple.wgsl @@ -0,0 +1,3 @@ +fn do_something_cool(in: f32) -> f32 { + return in * 2.0; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..dbf0efd --- /dev/null +++ b/src/main.rs @@ -0,0 +1,74 @@ +use std::{fs, io::Write}; + +use pest::Parser; +use pest_derive::Parser; + +#[derive(Parser)] +#[grammar = "wgsl.pest"] +pub struct WgslParser; + +fn main() { + /* let unparsed_file = fs::read_to_string("shaders/base.wgsl") + .expect("cannot read file"); + let mut successful_parse = WgslParser::parse(Rule::file, &unparsed_file).unwrap(); + + let a = successful_parse.next().unwrap(); + println!("got {}", a.as_str()); */ + + let unparsed_file = fs::read_to_string("shaders/base.wgsl") + .expect("cannot read file"); + // add a new line to the end of the input to make the grammar happy + let unparsed_file = format!("{unparsed_file}\n"); + + let mut out_file = fs::File::create("shaders/out.wgsl").unwrap(); + + let file = WgslParser::parse(Rule::file, &unparsed_file) + .expect("unsuccessful parse") // unwrap the parse result + .next().unwrap(); // get and unwrap the `file` rule; never fails + + for record in file.into_inner() { + match record.as_rule() { + Rule::command_line => { + + for command_line in record.into_inner() { + match command_line.as_rule() { + Rule::preproc_command => {}, + Rule::import_command => { + let mut shader_file_pairs = command_line.into_inner(); + let shader_file = shader_file_pairs.next().unwrap(); + let shader_file = shader_file.as_str(); + // remove surrounding quotes + let shader_file = &shader_file[1..shader_file.len() - 1]; + + println!("found include for file: {}", shader_file); + + let path = format!("shaders/{}", shader_file); + let included_file = fs::read(&path) + .expect("cannot read file"); + + let start_header = format!("// ==== START OF INCLUDE OF '{}' ====\n", path); + let end_header = format!("\n// ==== END OF INCLUDE OF '{}' ====\n", path); + + out_file.write(start_header.as_bytes()).unwrap(); + out_file.write(&included_file).unwrap(); + out_file.write(end_header.as_bytes()).unwrap(); + + }, + _ => unreachable!() + } + } + println!("found line"); + }, + Rule::shader_code_line => { + let input = record.as_str(); + println!("in: {}", input); + + let input = format!("{input}\n"); + out_file.write(input.as_bytes()).unwrap(); + }, + Rule::EOI => (), + Rule::eol => (), + _ => unreachable!(), + } + } +} \ No newline at end of file diff --git a/src/wgsl.pest b/src/wgsl.pest new file mode 100644 index 0000000..4632071 --- /dev/null +++ b/src/wgsl.pest @@ -0,0 +1,16 @@ +shader_file = { "\"" ~ ASCII_ALPHA* ~ "." ~ ASCII_ALPHA* ~ "\"" } +import_command = { "import" ~ ws ~ shader_file } +preproc_prefix = { "#" } + +// a line of preprocessor commands +command_line = { preproc_prefix ~ import_command } + +// all characters used by wgsl +shader_code = { ASCII_ALPHANUMERIC | "{" | "}" | "@" | "-" | "+" | "=" | "(" | ")" | ">" | "<" | ";" | "." | "_" | "," } +// a line of shader code, including white space +shader_code_line = { (ws* ~ shader_code ~ ws*)* } + +file = { SOI ~ ( (command_line | shader_code_line) ~ NEWLINE)* ~ EOI } + +// whitespace +ws = _{ " " | "\t" } \ No newline at end of file