diff --git a/Cargo.lock b/Cargo.lock index d6381ef..92dac97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -17,6 +17,21 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anyhow" version = "1.0.54" @@ -71,10 +86,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "cc" -version = "1.0.73" +name = "bitflags" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "cc" +version = "1.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -82,6 +106,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chumsky" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7314158bb843d046a78540774db3d78518f5150ea7109e9c8da864d45a738c" +dependencies = [ + "hashbrown 0.15.2", + "regex-automata", + "serde", + "stacker", + "unicode-ident", + "unicode-segmentation", +] + [[package]] name = "clap" version = "3.1.0" @@ -89,7 +133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5f1fea81f183005ced9e59cdb01737ef2423956dac5a6d731b06b2ecfaa3467" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "indexmap", "os_str_bytes", "strsim", @@ -97,6 +141,54 @@ dependencies = [ "textwrap", ] +[[package]] +name = "clipboard-win" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" +dependencies = [ + "error-code", +] + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "error-code" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" + +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "filedescriptor" version = "0.8.1" @@ -108,6 +200,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "gimli" version = "0.26.1" @@ -120,6 +218,17 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -129,6 +238,15 @@ dependencies = [ "libc", ] +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "indexmap" version = "1.8.0" @@ -136,20 +254,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] name = "libc" -version = "0.2.107" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "linux-raw-sys" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" -version = "2.4.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" @@ -161,6 +291,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "numtoa" version = "0.1.0" @@ -183,7 +334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -204,6 +355,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "psm" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" +dependencies = [ + "cc", +] + [[package]] name = "quote" version = "1.0.10" @@ -213,13 +373,23 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "redox_syscall" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -231,14 +401,33 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "regex-automata" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "rush" version = "0.1.0" dependencies = [ "anyhow", + "chumsky", "clap", "filedescriptor", "os_pipe", + "rustyline", "termion", "utf8-chars", ] @@ -249,6 +438,86 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustix" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +dependencies = [ + "bitflags 2.9.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustyline" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "windows-sys 0.59.0", +] + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" + +[[package]] +name = "stacker" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + [[package]] name = "strsim" version = "0.10.0" @@ -313,6 +582,24 @@ dependencies = [ "syn", ] +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -328,6 +615,12 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "winapi" version = "0.3.9" @@ -365,7 +658,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -374,13 +676,29 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -389,38 +707,86 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index e9f3263..6595b16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,8 @@ termion = "1.5.6" filedescriptor = "0.8.1" clap = "3.1.0" os_pipe = "1.1.4" +chumsky = "0.10.0" +rustyline = "15.0.0" [dependencies.anyhow] version = "1.0.54" diff --git a/README.md b/README.md index 83fdf2e..70aa94b 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ In case you're reading this: rush is in the works and not a priority. Features m ### Syntax ```sh -let thing = var -let thing = (echo test) +set thing = var +set thing = (echo test) echo test | cowsay parse file.csv parse file.csv | sort 2 asc @@ -42,25 +42,29 @@ while true { loop {} +fn test (arg) { + echo $arg +} + # do we error if array literal is used directly in exec call? # as that would likely be a mistake like $i [property] echo $i[property] $i[$dynamicproperty] # or another option - array constructor with a different syntax # like @[ ] [[ ]] -let array = [var] +set array = [var] # question here, do we allow multiline values? How? \ ? # or the more classic comma `,` for separating values and ignoring white space? # this is easier to write so might be preferred for very short scripting lang -let obj = ${ +set obj = ${ key: value $dynkey: $value2 } -let literal = "$var" +set literal = "$var" # or perhaps ` ? -let formatted = f"$var" +set formatted = f"$var" -# these are builtin commands rather than syntax structures (unlike let/while etc) +# these are builtin commands rather than syntax structures (unlike set/while etc) # they simply accept arguments and work with them as with any other # builtin commands accept structures rather than strings test 1 = 1 diff --git a/src/main.rs b/src/main.rs index 8a55e80..0650261 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,14 @@ +use std::io::Read; +use chumsky::Parser; + +mod parser; + fn main() { - + let mut file = std::fs::File::open("./test/parsetest.rush").expect("Unable to open file"); + let mut string = String::new(); + file.read_to_string(&mut string).unwrap(); + + dbg!(&string); + + println!("{:?}", parser::parse().parse(&string)); } \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..52be52b --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,191 @@ +use chumsky::{error::{EmptyErr, Rich, Simple}, prelude::{choice, just, none_of, one_of, recursive}, text, IterParser, Parser}; + + +#[derive(Debug, Clone)] +struct Index { + value: Box, + index: Box +} + +#[derive(Debug, Clone)] +enum Primitive { + Number(f64), + String(String), + Variable(String), + Index(Index) +} + +#[derive(Debug, Clone)] +enum Bindable { + Primitive(Primitive), +} + +#[derive(Debug, Clone)] +struct Command { + name: Box, + args: Vec +} + +#[derive(Debug, Clone)] +struct Set { + name: Box, + value: Box +} + +#[derive(Debug, Clone)] +struct If { + condition: Box, + body: Vec, + else_body: Option> +} + +#[derive(Debug, Clone)] +struct While { + condition: Box, + body: Vec, + else_body: Option> +} + +#[derive(Debug, Clone)] +struct For { + name: Box, + iterable: Box, + body: Vec, + else_body: Option> +} + +#[derive(Debug, Clone)] +struct Loop { + body: Vec +} + +#[derive(Debug, Clone)] +pub enum Statement { + Command(Command), + Set(Set), + For(For), + While(While), + If(If), + Loop(Loop), + Break +} + +#[derive(Debug, Clone)] +enum Value { + Primitive(Primitive), + Group(Vec) +} + +pub fn parse<'a>() -> impl Parser<'a, &'a str, Vec, chumsky::extra::Default> { + // let ident = text::ident::<&'a str, chumsky::extra::Default>(); + let digits = text::digits(10).to_slice(); + + let frac = just('.').then(digits); + + let exp = just('e') + .or(just('E')) + .then(one_of("+-").or_not()) + .then(digits); + + let number = just('-') + .or_not() + .then(text::int(10)) + .then(frac.or_not()) + .then(exp.or_not()) + .to_slice() + .map(|s: &str| s.parse().unwrap()) + .boxed(); + // let op = |c| just(c).padded(); + + let escape = just('\\') + .then(choice(( + just('\\'), + just('/'), + just('"'), + just('b').to('\x08'), + just('f').to('\x0C'), + just('n').to('\n'), + just('r').to('\r'), + just('t').to('\t'), + just('u').ignore_then(text::digits(16).exactly(4).to_slice().validate( + |digits, e, emitter| { + char::from_u32(u32::from_str_radix(digits, 16).unwrap()).unwrap_or_else( + || { + // emitter.emit(Rich::custom(e.span(), "invalid unicode character")); + '\u{FFFD}' // unicode replacement character + }, + ) + }, + )), + ))) + .ignored() + .boxed(); + + let direct_string = none_of("$()[]{}\\\"\n;") + .and_is(text::whitespace().at_least(1).not()) + .ignored() + .or(escape.clone()) + .repeated() + .at_least(1) + .to_slice() + .map(ToString::to_string) + .boxed(); + + let delimited_string = none_of("\\\"") + .ignored() + .or(escape) + .repeated() + .to_slice() + .map(ToString::to_string) + .delimited_by(just('"'), just('"')) + .boxed(); + + let string = choice(( + delimited_string.clone(), + direct_string.clone(), + )); + let eol = one_of("\n\r;"); + // let r#break = just("break").map(|_| Statement::Break); + + let variable = just('$').ignore_then(text::ident()); + + recursive(|expr| { + let primitive = choice(( + number.map(Primitive::Number), + variable.map(|s: &str| Primitive::Variable(s.to_string())), + string.map(Primitive::String), + )); + + let bindable = primitive.clone(); + + let group = just('(') + .ignore_then(expr.clone()) + .then_ignore(just(')')) + .map(|v| Value::Group(v)); + + let value = choice(( + group, + primitive.map(Value::Primitive), + )); + + let command = value + .separated_by(text::whitespace().at_least(1)) + .at_least(1) + .allow_trailing() + .allow_leading() + .collect() + .map(|args: Vec| { + let name = args[0].clone(); + let args = args[1..].to_vec(); + + Command { + name: Box::new(name), + args: args.into_iter().map(|v| v.clone()).collect() + } + }); + + let statement = command.map(Statement::Command); + + statement.separated_by(eol).at_least(1).collect() + }) +} \ No newline at end of file diff --git a/syntax.deg b/syntax.deg index f59db2e..8ed8a1e 100644 --- a/syntax.deg +++ b/syntax.deg @@ -17,16 +17,25 @@ BINDABLE = PRIMITIVE_VALUES VALUE = PRIMITIVE_VALUES | GROUP -GROUP = "(" COMMAND ")" +# statements are expressions, so it is possible to write `echo (if true { echo true } else { echo false })` +GROUP = "(" STATEMENT ")" -COMMAND = ( VALUE WHITESPACE ) + +# no padding can be here, must be TEXT=VALUE +ENV_VAR_SPECIFICATION = STRING = VALUE -LET = let BINDABLE = VALUE +COMMAND = ( ENV_VAR_SPECIFICATION WHITESPACE ) * ( VALUE WHITESPACE ) + -FOR = for BINDABLE in VALUE { STATEMENTS } +# in the future this could also support other ops like add+set +SET = set BINDABLE = VALUE + +FUNCTION = fn STRING "(" ( BINDABLE , )* BINDABLE ")" { STATEMENTS } + +FOR = for BINDABLE in VALUE { STATEMENTS } ( else { STATEMENTS } )? IF = if VALUE { STATEMENTS } ( else if VALUE { STATEMENTS } ) * ( else { STATEMENTS } )? WHILE = while VALUE { STATEMENTS } ( else { STATEMENTS } )? LOOP = loop { STATEMENTS } -STATEMENT = COMMAND | LET | FOR | IF | WHILE | LOOP +BREAK = break + +STATEMENT = COMMAND | SET | FOR | IF | WHILE | LOOP | FUNCTION | BREAK STATEMENTS = ( STATEMENT (; | EOL) )* STATEMENT? \ No newline at end of file diff --git a/test/parsetest.rush b/test/parsetest.rush new file mode 100644 index 0000000..2be6812 --- /dev/null +++ b/test/parsetest.rush @@ -0,0 +1 @@ + test ( test 2 ) \ No newline at end of file