| author | |
| committer | |
| log | 9153cb96ee98310426d7dab102d4564af52589bd |
| tree | 129a9dfd35962415998d30928c2b79c219d2d27a |
| parent | 30d91f57ad954a930871abb4d9bfe9028b66f0b9 |
38 files changed, 1758 insertions(+), 2192 deletions(-)
Cargo.lock+43-10| ... | ... | @@ -65,6 +65,16 @@ dependencies = [ |
| 65 | 65 | "windows-sys", |
| 66 | 66 | ] |
| 67 | 67 | |
| 68 | [[package]] | |
| 69 | name = "ast" | |
| 70 | version = "0.1.0" | |
| 71 | dependencies = [ | |
| 72 | "miette", | |
| 73 | "thiserror", | |
| 74 | "tokenizer", | |
| 75 | "util", | |
| 76 | ] | |
| 77 | ||
| 68 | 78 | [[package]] |
| 69 | 79 | name = "backtrace" |
| 70 | 80 | version = "0.3.69" |
| ... | ... | @@ -154,10 +164,12 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" |
| 154 | 164 | name = "cli" |
| 155 | 165 | version = "0.1.0" |
| 156 | 166 | dependencies = [ |
| 167 | "ast", | |
| 157 | 168 | "clap", |
| 158 | "compiler", | |
| 169 | "js_printer", | |
| 159 | 170 | "miette", |
| 160 | 171 | "thiserror", |
| 172 | "tokenizer", | |
| 161 | 173 | ] |
| 162 | 174 | |
| 163 | 175 | [[package]] |
| ... | ... | @@ -166,15 +178,6 @@ version = "1.0.0" |
| 166 | 178 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 167 | 179 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" |
| 168 | 180 | |
| 169 | [[package]] | |
| 170 | name = "compiler" | |
| 171 | version = "0.1.0" | |
| 172 | dependencies = [ | |
| 173 | "clap", | |
| 174 | "miette", | |
| 175 | "thiserror", | |
| 176 | ] | |
| 177 | ||
| 178 | 181 | [[package]] |
| 179 | 182 | name = "errno" |
| 180 | 183 | version = "0.3.8" |
| ... | ... | @@ -220,6 +223,23 @@ version = "1.1.1" |
| 220 | 223 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 221 | 224 | checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" |
| 222 | 225 | |
| 226 | [[package]] | |
| 227 | name = "js_ast" | |
| 228 | version = "0.1.0" | |
| 229 | dependencies = [ | |
| 230 | "miette", | |
| 231 | "thiserror", | |
| 232 | ] | |
| 233 | ||
| 234 | [[package]] | |
| 235 | name = "js_printer" | |
| 236 | version = "0.1.0" | |
| 237 | dependencies = [ | |
| 238 | "ast", | |
| 239 | "miette", | |
| 240 | "thiserror", | |
| 241 | ] | |
| 242 | ||
| 223 | 243 | [[package]] |
| 224 | 244 | name = "libc" |
| 225 | 245 | version = "0.2.152" |
| ... | ... | @@ -429,6 +449,15 @@ dependencies = [ |
| 429 | 449 | "syn", |
| 430 | 450 | ] |
| 431 | 451 | |
| 452 | [[package]] | |
| 453 | name = "tokenizer" | |
| 454 | version = "0.1.0" | |
| 455 | dependencies = [ | |
| 456 | "miette", | |
| 457 | "thiserror", | |
| 458 | "util", | |
| 459 | ] | |
| 460 | ||
| 432 | 461 | [[package]] |
| 433 | 462 | name = "unicode-ident" |
| 434 | 463 | version = "1.0.12" |
| ... | ... | @@ -453,6 +482,10 @@ version = "0.2.1" |
| 453 | 482 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 454 | 483 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" |
| 455 | 484 | |
| 485 | [[package]] | |
| 486 | name = "util" | |
| 487 | version = "0.1.0" | |
| 488 | ||
| 456 | 489 | [[package]] |
| 457 | 490 | name = "winapi" |
| 458 | 491 | version = "0.3.9" |
Cargo.toml+1-1| ... | ... | @@ -8,7 +8,7 @@ repository = "https://github.com/lino-levan/blight" |
| 8 | 8 | |
| 9 | 9 | [workspace] |
| 10 | 10 | resolver = "2" |
| 11 | members = ["cli", "compiler"] | |
| 11 | members = ["crates/cli", "crates/util", "crates/tokenizer", "crates/ast", "crates/js_ast", "crates/js_printer"] | |
| 12 | 12 | |
| 13 | 13 | [workspace.dependencies] |
| 14 | 14 | clap = { version = "4.4.12", features = ["derive"] } |
README.md+14| ... | ... | @@ -1,3 +1,17 @@ |
| 1 | 1 | # Blight |
| 2 | 2 | |
| 3 | 3 | Blight sure is a programming language. |
| 4 | ||
| 5 | ## Developing | |
| 6 | ||
| 7 | Compiling a file: | |
| 8 | ||
| 9 | ```bash | |
| 10 | cargo run compile --stdout ./examples/basics/fib.blight | |
| 11 | ``` | |
| 12 | ||
| 13 | Running the compiler on a file: | |
| 14 | ||
| 15 | ```bash | |
| 16 | cargo run run ./examples/basics/fib.blight | |
| 17 | ``` |
cli/Cargo.lock deleted-532| ... | ... | @@ -1,532 +0,0 @@ |
| 1 | # This file is automatically @generated by Cargo. | |
| 2 | # It is not intended for manual editing. | |
| 3 | version = 3 | |
| 4 | ||
| 5 | [[package]] | |
| 6 | name = "addr2line" | |
| 7 | version = "0.21.0" | |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" | |
| 10 | dependencies = [ | |
| 11 | "gimli", | |
| 12 | ] | |
| 13 | ||
| 14 | [[package]] | |
| 15 | name = "adler" | |
| 16 | version = "1.0.2" | |
| 17 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | |
| 19 | ||
| 20 | [[package]] | |
| 21 | name = "anstream" | |
| 22 | version = "0.6.5" | |
| 23 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 24 | checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" | |
| 25 | dependencies = [ | |
| 26 | "anstyle", | |
| 27 | "anstyle-parse", | |
| 28 | "anstyle-query", | |
| 29 | "anstyle-wincon", | |
| 30 | "colorchoice", | |
| 31 | "utf8parse", | |
| 32 | ] | |
| 33 | ||
| 34 | [[package]] | |
| 35 | name = "anstyle" | |
| 36 | version = "1.0.4" | |
| 37 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 38 | checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" | |
| 39 | ||
| 40 | [[package]] | |
| 41 | name = "anstyle-parse" | |
| 42 | version = "0.2.3" | |
| 43 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 44 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" | |
| 45 | dependencies = [ | |
| 46 | "utf8parse", | |
| 47 | ] | |
| 48 | ||
| 49 | [[package]] | |
| 50 | name = "anstyle-query" | |
| 51 | version = "1.0.2" | |
| 52 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 53 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" | |
| 54 | dependencies = [ | |
| 55 | "windows-sys", | |
| 56 | ] | |
| 57 | ||
| 58 | [[package]] | |
| 59 | name = "anstyle-wincon" | |
| 60 | version = "3.0.2" | |
| 61 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 62 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" | |
| 63 | dependencies = [ | |
| 64 | "anstyle", | |
| 65 | "windows-sys", | |
| 66 | ] | |
| 67 | ||
| 68 | [[package]] | |
| 69 | name = "backtrace" | |
| 70 | version = "0.3.69" | |
| 71 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 72 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" | |
| 73 | dependencies = [ | |
| 74 | "addr2line", | |
| 75 | "cc", | |
| 76 | "cfg-if", | |
| 77 | "libc", | |
| 78 | "miniz_oxide", | |
| 79 | "object", | |
| 80 | "rustc-demangle", | |
| 81 | ] | |
| 82 | ||
| 83 | [[package]] | |
| 84 | name = "backtrace-ext" | |
| 85 | version = "0.2.1" | |
| 86 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 87 | checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" | |
| 88 | dependencies = [ | |
| 89 | "backtrace", | |
| 90 | ] | |
| 91 | ||
| 92 | [[package]] | |
| 93 | name = "bitflags" | |
| 94 | version = "2.4.1" | |
| 95 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 96 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" | |
| 97 | ||
| 98 | [[package]] | |
| 99 | name = "blight" | |
| 100 | version = "0.1.0" | |
| 101 | dependencies = [ | |
| 102 | "clap", | |
| 103 | "miette", | |
| 104 | "thiserror", | |
| 105 | ] | |
| 106 | ||
| 107 | [[package]] | |
| 108 | name = "cc" | |
| 109 | version = "1.0.83" | |
| 110 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 111 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" | |
| 112 | dependencies = [ | |
| 113 | "libc", | |
| 114 | ] | |
| 115 | ||
| 116 | [[package]] | |
| 117 | name = "cfg-if" | |
| 118 | version = "1.0.0" | |
| 119 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 120 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |
| 121 | ||
| 122 | [[package]] | |
| 123 | name = "clap" | |
| 124 | version = "4.4.12" | |
| 125 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 126 | checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" | |
| 127 | dependencies = [ | |
| 128 | "clap_builder", | |
| 129 | "clap_derive", | |
| 130 | ] | |
| 131 | ||
| 132 | [[package]] | |
| 133 | name = "clap_builder" | |
| 134 | version = "4.4.12" | |
| 135 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 136 | checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" | |
| 137 | dependencies = [ | |
| 138 | "anstream", | |
| 139 | "anstyle", | |
| 140 | "clap_lex", | |
| 141 | "strsim", | |
| 142 | ] | |
| 143 | ||
| 144 | [[package]] | |
| 145 | name = "clap_derive" | |
| 146 | version = "4.4.7" | |
| 147 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 148 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" | |
| 149 | dependencies = [ | |
| 150 | "heck", | |
| 151 | "proc-macro2", | |
| 152 | "quote", | |
| 153 | "syn", | |
| 154 | ] | |
| 155 | ||
| 156 | [[package]] | |
| 157 | name = "clap_lex" | |
| 158 | version = "0.6.0" | |
| 159 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 160 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" | |
| 161 | ||
| 162 | [[package]] | |
| 163 | name = "colorchoice" | |
| 164 | version = "1.0.0" | |
| 165 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 166 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | |
| 167 | ||
| 168 | [[package]] | |
| 169 | name = "errno" | |
| 170 | version = "0.3.8" | |
| 171 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 172 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" | |
| 173 | dependencies = [ | |
| 174 | "libc", | |
| 175 | "windows-sys", | |
| 176 | ] | |
| 177 | ||
| 178 | [[package]] | |
| 179 | name = "gimli" | |
| 180 | version = "0.28.1" | |
| 181 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 182 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" | |
| 183 | ||
| 184 | [[package]] | |
| 185 | name = "heck" | |
| 186 | version = "0.4.1" | |
| 187 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 188 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" | |
| 189 | ||
| 190 | [[package]] | |
| 191 | name = "hermit-abi" | |
| 192 | version = "0.3.3" | |
| 193 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 194 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" | |
| 195 | ||
| 196 | [[package]] | |
| 197 | name = "is-terminal" | |
| 198 | version = "0.4.10" | |
| 199 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 200 | checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" | |
| 201 | dependencies = [ | |
| 202 | "hermit-abi", | |
| 203 | "rustix", | |
| 204 | "windows-sys", | |
| 205 | ] | |
| 206 | ||
| 207 | [[package]] | |
| 208 | name = "is_ci" | |
| 209 | version = "1.1.1" | |
| 210 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 211 | checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" | |
| 212 | ||
| 213 | [[package]] | |
| 214 | name = "libc" | |
| 215 | version = "0.2.151" | |
| 216 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 217 | checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" | |
| 218 | ||
| 219 | [[package]] | |
| 220 | name = "linux-raw-sys" | |
| 221 | version = "0.4.12" | |
| 222 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 223 | checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" | |
| 224 | ||
| 225 | [[package]] | |
| 226 | name = "memchr" | |
| 227 | version = "2.7.1" | |
| 228 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 229 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" | |
| 230 | ||
| 231 | [[package]] | |
| 232 | name = "miette" | |
| 233 | version = "5.10.0" | |
| 234 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 235 | checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" | |
| 236 | dependencies = [ | |
| 237 | "backtrace", | |
| 238 | "backtrace-ext", | |
| 239 | "is-terminal", | |
| 240 | "miette-derive", | |
| 241 | "once_cell", | |
| 242 | "owo-colors", | |
| 243 | "supports-color", | |
| 244 | "supports-hyperlinks", | |
| 245 | "supports-unicode", | |
| 246 | "terminal_size", | |
| 247 | "textwrap", | |
| 248 | "thiserror", | |
| 249 | "unicode-width", | |
| 250 | ] | |
| 251 | ||
| 252 | [[package]] | |
| 253 | name = "miette-derive" | |
| 254 | version = "5.10.0" | |
| 255 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 256 | checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" | |
| 257 | dependencies = [ | |
| 258 | "proc-macro2", | |
| 259 | "quote", | |
| 260 | "syn", | |
| 261 | ] | |
| 262 | ||
| 263 | [[package]] | |
| 264 | name = "miniz_oxide" | |
| 265 | version = "0.7.1" | |
| 266 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 267 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" | |
| 268 | dependencies = [ | |
| 269 | "adler", | |
| 270 | ] | |
| 271 | ||
| 272 | [[package]] | |
| 273 | name = "object" | |
| 274 | version = "0.32.2" | |
| 275 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 276 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" | |
| 277 | dependencies = [ | |
| 278 | "memchr", | |
| 279 | ] | |
| 280 | ||
| 281 | [[package]] | |
| 282 | name = "once_cell" | |
| 283 | version = "1.19.0" | |
| 284 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 285 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" | |
| 286 | ||
| 287 | [[package]] | |
| 288 | name = "owo-colors" | |
| 289 | version = "3.5.0" | |
| 290 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 291 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" | |
| 292 | ||
| 293 | [[package]] | |
| 294 | name = "proc-macro2" | |
| 295 | version = "1.0.73" | |
| 296 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 297 | checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1" | |
| 298 | dependencies = [ | |
| 299 | "unicode-ident", | |
| 300 | ] | |
| 301 | ||
| 302 | [[package]] | |
| 303 | name = "quote" | |
| 304 | version = "1.0.34" | |
| 305 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 306 | checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" | |
| 307 | dependencies = [ | |
| 308 | "proc-macro2", | |
| 309 | ] | |
| 310 | ||
| 311 | [[package]] | |
| 312 | name = "rustc-demangle" | |
| 313 | version = "0.1.23" | |
| 314 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 315 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" | |
| 316 | ||
| 317 | [[package]] | |
| 318 | name = "rustix" | |
| 319 | version = "0.38.28" | |
| 320 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 321 | checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" | |
| 322 | dependencies = [ | |
| 323 | "bitflags", | |
| 324 | "errno", | |
| 325 | "libc", | |
| 326 | "linux-raw-sys", | |
| 327 | "windows-sys", | |
| 328 | ] | |
| 329 | ||
| 330 | [[package]] | |
| 331 | name = "smawk" | |
| 332 | version = "0.3.2" | |
| 333 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 334 | checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" | |
| 335 | ||
| 336 | [[package]] | |
| 337 | name = "strsim" | |
| 338 | version = "0.10.0" | |
| 339 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 340 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | |
| 341 | ||
| 342 | [[package]] | |
| 343 | name = "supports-color" | |
| 344 | version = "2.1.0" | |
| 345 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 346 | checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" | |
| 347 | dependencies = [ | |
| 348 | "is-terminal", | |
| 349 | "is_ci", | |
| 350 | ] | |
| 351 | ||
| 352 | [[package]] | |
| 353 | name = "supports-hyperlinks" | |
| 354 | version = "2.1.0" | |
| 355 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 356 | checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" | |
| 357 | dependencies = [ | |
| 358 | "is-terminal", | |
| 359 | ] | |
| 360 | ||
| 361 | [[package]] | |
| 362 | name = "supports-unicode" | |
| 363 | version = "2.0.0" | |
| 364 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 365 | checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" | |
| 366 | dependencies = [ | |
| 367 | "is-terminal", | |
| 368 | ] | |
| 369 | ||
| 370 | [[package]] | |
| 371 | name = "syn" | |
| 372 | version = "2.0.44" | |
| 373 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 374 | checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d" | |
| 375 | dependencies = [ | |
| 376 | "proc-macro2", | |
| 377 | "quote", | |
| 378 | "unicode-ident", | |
| 379 | ] | |
| 380 | ||
| 381 | [[package]] | |
| 382 | name = "terminal_size" | |
| 383 | version = "0.1.17" | |
| 384 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 385 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" | |
| 386 | dependencies = [ | |
| 387 | "libc", | |
| 388 | "winapi", | |
| 389 | ] | |
| 390 | ||
| 391 | [[package]] | |
| 392 | name = "textwrap" | |
| 393 | version = "0.15.2" | |
| 394 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 395 | checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" | |
| 396 | dependencies = [ | |
| 397 | "smawk", | |
| 398 | "unicode-linebreak", | |
| 399 | "unicode-width", | |
| 400 | ] | |
| 401 | ||
| 402 | [[package]] | |
| 403 | name = "thiserror" | |
| 404 | version = "1.0.53" | |
| 405 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 406 | checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" | |
| 407 | dependencies = [ | |
| 408 | "thiserror-impl", | |
| 409 | ] | |
| 410 | ||
| 411 | [[package]] | |
| 412 | name = "thiserror-impl" | |
| 413 | version = "1.0.53" | |
| 414 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 415 | checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" | |
| 416 | dependencies = [ | |
| 417 | "proc-macro2", | |
| 418 | "quote", | |
| 419 | "syn", | |
| 420 | ] | |
| 421 | ||
| 422 | [[package]] | |
| 423 | name = "unicode-ident" | |
| 424 | version = "1.0.12" | |
| 425 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 426 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" | |
| 427 | ||
| 428 | [[package]] | |
| 429 | name = "unicode-linebreak" | |
| 430 | version = "0.1.5" | |
| 431 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 432 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" | |
| 433 | ||
| 434 | [[package]] | |
| 435 | name = "unicode-width" | |
| 436 | version = "0.1.11" | |
| 437 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 438 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" | |
| 439 | ||
| 440 | [[package]] | |
| 441 | name = "utf8parse" | |
| 442 | version = "0.2.1" | |
| 443 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 444 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | |
| 445 | ||
| 446 | [[package]] | |
| 447 | name = "winapi" | |
| 448 | version = "0.3.9" | |
| 449 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 450 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | |
| 451 | dependencies = [ | |
| 452 | "winapi-i686-pc-windows-gnu", | |
| 453 | "winapi-x86_64-pc-windows-gnu", | |
| 454 | ] | |
| 455 | ||
| 456 | [[package]] | |
| 457 | name = "winapi-i686-pc-windows-gnu" | |
| 458 | version = "0.4.0" | |
| 459 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 460 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | |
| 461 | ||
| 462 | [[package]] | |
| 463 | name = "winapi-x86_64-pc-windows-gnu" | |
| 464 | version = "0.4.0" | |
| 465 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 466 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |
| 467 | ||
| 468 | [[package]] | |
| 469 | name = "windows-sys" | |
| 470 | version = "0.52.0" | |
| 471 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 472 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | |
| 473 | dependencies = [ | |
| 474 | "windows-targets", | |
| 475 | ] | |
| 476 | ||
| 477 | [[package]] | |
| 478 | name = "windows-targets" | |
| 479 | version = "0.52.0" | |
| 480 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 481 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" | |
| 482 | dependencies = [ | |
| 483 | "windows_aarch64_gnullvm", | |
| 484 | "windows_aarch64_msvc", | |
| 485 | "windows_i686_gnu", | |
| 486 | "windows_i686_msvc", | |
| 487 | "windows_x86_64_gnu", | |
| 488 | "windows_x86_64_gnullvm", | |
| 489 | "windows_x86_64_msvc", | |
| 490 | ] | |
| 491 | ||
| 492 | [[package]] | |
| 493 | name = "windows_aarch64_gnullvm" | |
| 494 | version = "0.52.0" | |
| 495 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 496 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" | |
| 497 | ||
| 498 | [[package]] | |
| 499 | name = "windows_aarch64_msvc" | |
| 500 | version = "0.52.0" | |
| 501 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 502 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" | |
| 503 | ||
| 504 | [[package]] | |
| 505 | name = "windows_i686_gnu" | |
| 506 | version = "0.52.0" | |
| 507 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 508 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" | |
| 509 | ||
| 510 | [[package]] | |
| 511 | name = "windows_i686_msvc" | |
| 512 | version = "0.52.0" | |
| 513 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 514 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" | |
| 515 | ||
| 516 | [[package]] | |
| 517 | name = "windows_x86_64_gnu" | |
| 518 | version = "0.52.0" | |
| 519 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 520 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" | |
| 521 | ||
| 522 | [[package]] | |
| 523 | name = "windows_x86_64_gnullvm" | |
| 524 | version = "0.52.0" | |
| 525 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 526 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" | |
| 527 | ||
| 528 | [[package]] | |
| 529 | name = "windows_x86_64_msvc" | |
| 530 | version = "0.52.0" | |
| 531 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 532 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" |
cli/Cargo.toml deleted-15| ... | ... | @@ -1,15 +0,0 @@ |
| 1 | [package] | |
| 2 | name = "cli" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [[bin]] | |
| 7 | name = "blight" | |
| 8 | path = "./src/main.rs" | |
| 9 | ||
| 10 | [dependencies] | |
| 11 | clap.workspace = true | |
| 12 | miette.workspace = true | |
| 13 | thiserror.workspace = true | |
| 14 | ||
| 15 | compiler = { path = "../compiler" } |
cli/src/main.rs deleted-99| ... | ... | @@ -1,99 +0,0 @@ |
| 1 | use std::path::PathBuf; | |
| 2 | ||
| 3 | use clap::{Parser, Subcommand}; | |
| 4 | use miette::Result; | |
| 5 | ||
| 6 | use compiler::transpile; | |
| 7 | ||
| 8 | #[derive(Parser)] | |
| 9 | #[command(author, version, about, long_about = None)] | |
| 10 | struct Cli { | |
| 11 | /// Turn debugging information on | |
| 12 | #[arg(short, long, action = clap::ArgAction::Count)] | |
| 13 | debug: u8, | |
| 14 | ||
| 15 | #[command(subcommand)] | |
| 16 | command: Commands, | |
| 17 | } | |
| 18 | ||
| 19 | #[derive(Subcommand)] | |
| 20 | enum Commands { | |
| 21 | /// Compiles a file into javascript | |
| 22 | Compile { | |
| 23 | file: PathBuf, | |
| 24 | // Whether to output to stdout instead of a file | |
| 25 | #[arg(long, default_value_t = false)] | |
| 26 | stdout: bool, | |
| 27 | }, | |
| 28 | Run { | |
| 29 | file: PathBuf, | |
| 30 | /// What javascript runtime to use | |
| 31 | #[arg(short, long, default_value = "deno")] | |
| 32 | runtime: String, | |
| 33 | }, | |
| 34 | } | |
| 35 | ||
| 36 | fn get_runtime(runtime: &String) -> String { | |
| 37 | match std::env::var("USER") { | |
| 38 | Ok(user) if user == "dave" => String::from("bun"), | |
| 39 | _ => runtime.clone(), | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 43 | fn main() -> Result<()> { | |
| 44 | let cli = Cli::parse(); | |
| 45 | ||
| 46 | match cli.command { | |
| 47 | Commands::Compile { file, stdout } => { | |
| 48 | let contents = std::fs::read_to_string(file.clone()).unwrap(); | |
| 49 | let result = transpile(contents.clone())?; | |
| 50 | ||
| 51 | if stdout { | |
| 52 | println!("{}", result); | |
| 53 | } else { | |
| 54 | std::fs::write(file.with_extension("js"), result).unwrap(); | |
| 55 | } | |
| 56 | } | |
| 57 | Commands::Run { file, runtime } => { | |
| 58 | let contents = std::fs::read_to_string(file.clone()).unwrap(); | |
| 59 | let result = transpile(contents.clone())?; | |
| 60 | let mut temp_file = std::env::temp_dir(); | |
| 61 | temp_file.push("temp.js"); | |
| 62 | std::fs::write(temp_file.clone(), result).unwrap(); | |
| 63 | ||
| 64 | let rt = get_runtime(&runtime); | |
| 65 | ||
| 66 | match rt.as_str() { | |
| 67 | "deno" => { | |
| 68 | let output = std::process::Command::new("deno") | |
| 69 | .arg("run") | |
| 70 | .arg("-A") | |
| 71 | .arg(temp_file) | |
| 72 | .output() | |
| 73 | .expect("Failed to execute process"); | |
| 74 | println!("{}", String::from_utf8_lossy(&output.stdout)); | |
| 75 | } | |
| 76 | "node" => { | |
| 77 | let output = std::process::Command::new("node") | |
| 78 | .arg(temp_file) | |
| 79 | .output() | |
| 80 | .expect("Failed to execute process"); | |
| 81 | println!("{}", String::from_utf8_lossy(&output.stdout)); | |
| 82 | } | |
| 83 | "bun" => { | |
| 84 | let output = std::process::Command::new("bun") | |
| 85 | .arg("run") | |
| 86 | .arg(temp_file) | |
| 87 | .output() | |
| 88 | .expect("Failed to execute process"); | |
| 89 | println!("{}", String::from_utf8_lossy(&output.stdout)); | |
| 90 | } | |
| 91 | _ => { | |
| 92 | println!("Unknown runtime: {}", runtime); | |
| 93 | } | |
| 94 | } | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | Ok(()) | |
| 99 | } |
compiler/Cargo.lock deleted-532| ... | ... | @@ -1,532 +0,0 @@ |
| 1 | # This file is automatically @generated by Cargo. | |
| 2 | # It is not intended for manual editing. | |
| 3 | version = 3 | |
| 4 | ||
| 5 | [[package]] | |
| 6 | name = "addr2line" | |
| 7 | version = "0.21.0" | |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" | |
| 10 | dependencies = [ | |
| 11 | "gimli", | |
| 12 | ] | |
| 13 | ||
| 14 | [[package]] | |
| 15 | name = "adler" | |
| 16 | version = "1.0.2" | |
| 17 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | |
| 19 | ||
| 20 | [[package]] | |
| 21 | name = "anstream" | |
| 22 | version = "0.6.5" | |
| 23 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 24 | checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" | |
| 25 | dependencies = [ | |
| 26 | "anstyle", | |
| 27 | "anstyle-parse", | |
| 28 | "anstyle-query", | |
| 29 | "anstyle-wincon", | |
| 30 | "colorchoice", | |
| 31 | "utf8parse", | |
| 32 | ] | |
| 33 | ||
| 34 | [[package]] | |
| 35 | name = "anstyle" | |
| 36 | version = "1.0.4" | |
| 37 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 38 | checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" | |
| 39 | ||
| 40 | [[package]] | |
| 41 | name = "anstyle-parse" | |
| 42 | version = "0.2.3" | |
| 43 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 44 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" | |
| 45 | dependencies = [ | |
| 46 | "utf8parse", | |
| 47 | ] | |
| 48 | ||
| 49 | [[package]] | |
| 50 | name = "anstyle-query" | |
| 51 | version = "1.0.2" | |
| 52 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 53 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" | |
| 54 | dependencies = [ | |
| 55 | "windows-sys", | |
| 56 | ] | |
| 57 | ||
| 58 | [[package]] | |
| 59 | name = "anstyle-wincon" | |
| 60 | version = "3.0.2" | |
| 61 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 62 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" | |
| 63 | dependencies = [ | |
| 64 | "anstyle", | |
| 65 | "windows-sys", | |
| 66 | ] | |
| 67 | ||
| 68 | [[package]] | |
| 69 | name = "backtrace" | |
| 70 | version = "0.3.69" | |
| 71 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 72 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" | |
| 73 | dependencies = [ | |
| 74 | "addr2line", | |
| 75 | "cc", | |
| 76 | "cfg-if", | |
| 77 | "libc", | |
| 78 | "miniz_oxide", | |
| 79 | "object", | |
| 80 | "rustc-demangle", | |
| 81 | ] | |
| 82 | ||
| 83 | [[package]] | |
| 84 | name = "backtrace-ext" | |
| 85 | version = "0.2.1" | |
| 86 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 87 | checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" | |
| 88 | dependencies = [ | |
| 89 | "backtrace", | |
| 90 | ] | |
| 91 | ||
| 92 | [[package]] | |
| 93 | name = "bitflags" | |
| 94 | version = "2.4.1" | |
| 95 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 96 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" | |
| 97 | ||
| 98 | [[package]] | |
| 99 | name = "blight" | |
| 100 | version = "0.1.0" | |
| 101 | dependencies = [ | |
| 102 | "clap", | |
| 103 | "miette", | |
| 104 | "thiserror", | |
| 105 | ] | |
| 106 | ||
| 107 | [[package]] | |
| 108 | name = "cc" | |
| 109 | version = "1.0.83" | |
| 110 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 111 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" | |
| 112 | dependencies = [ | |
| 113 | "libc", | |
| 114 | ] | |
| 115 | ||
| 116 | [[package]] | |
| 117 | name = "cfg-if" | |
| 118 | version = "1.0.0" | |
| 119 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 120 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |
| 121 | ||
| 122 | [[package]] | |
| 123 | name = "clap" | |
| 124 | version = "4.4.12" | |
| 125 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 126 | checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" | |
| 127 | dependencies = [ | |
| 128 | "clap_builder", | |
| 129 | "clap_derive", | |
| 130 | ] | |
| 131 | ||
| 132 | [[package]] | |
| 133 | name = "clap_builder" | |
| 134 | version = "4.4.12" | |
| 135 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 136 | checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" | |
| 137 | dependencies = [ | |
| 138 | "anstream", | |
| 139 | "anstyle", | |
| 140 | "clap_lex", | |
| 141 | "strsim", | |
| 142 | ] | |
| 143 | ||
| 144 | [[package]] | |
| 145 | name = "clap_derive" | |
| 146 | version = "4.4.7" | |
| 147 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 148 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" | |
| 149 | dependencies = [ | |
| 150 | "heck", | |
| 151 | "proc-macro2", | |
| 152 | "quote", | |
| 153 | "syn", | |
| 154 | ] | |
| 155 | ||
| 156 | [[package]] | |
| 157 | name = "clap_lex" | |
| 158 | version = "0.6.0" | |
| 159 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 160 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" | |
| 161 | ||
| 162 | [[package]] | |
| 163 | name = "colorchoice" | |
| 164 | version = "1.0.0" | |
| 165 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 166 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | |
| 167 | ||
| 168 | [[package]] | |
| 169 | name = "errno" | |
| 170 | version = "0.3.8" | |
| 171 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 172 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" | |
| 173 | dependencies = [ | |
| 174 | "libc", | |
| 175 | "windows-sys", | |
| 176 | ] | |
| 177 | ||
| 178 | [[package]] | |
| 179 | name = "gimli" | |
| 180 | version = "0.28.1" | |
| 181 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 182 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" | |
| 183 | ||
| 184 | [[package]] | |
| 185 | name = "heck" | |
| 186 | version = "0.4.1" | |
| 187 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 188 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" | |
| 189 | ||
| 190 | [[package]] | |
| 191 | name = "hermit-abi" | |
| 192 | version = "0.3.3" | |
| 193 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 194 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" | |
| 195 | ||
| 196 | [[package]] | |
| 197 | name = "is-terminal" | |
| 198 | version = "0.4.10" | |
| 199 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 200 | checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" | |
| 201 | dependencies = [ | |
| 202 | "hermit-abi", | |
| 203 | "rustix", | |
| 204 | "windows-sys", | |
| 205 | ] | |
| 206 | ||
| 207 | [[package]] | |
| 208 | name = "is_ci" | |
| 209 | version = "1.1.1" | |
| 210 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 211 | checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" | |
| 212 | ||
| 213 | [[package]] | |
| 214 | name = "libc" | |
| 215 | version = "0.2.151" | |
| 216 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 217 | checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" | |
| 218 | ||
| 219 | [[package]] | |
| 220 | name = "linux-raw-sys" | |
| 221 | version = "0.4.12" | |
| 222 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 223 | checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" | |
| 224 | ||
| 225 | [[package]] | |
| 226 | name = "memchr" | |
| 227 | version = "2.7.1" | |
| 228 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 229 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" | |
| 230 | ||
| 231 | [[package]] | |
| 232 | name = "miette" | |
| 233 | version = "5.10.0" | |
| 234 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 235 | checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" | |
| 236 | dependencies = [ | |
| 237 | "backtrace", | |
| 238 | "backtrace-ext", | |
| 239 | "is-terminal", | |
| 240 | "miette-derive", | |
| 241 | "once_cell", | |
| 242 | "owo-colors", | |
| 243 | "supports-color", | |
| 244 | "supports-hyperlinks", | |
| 245 | "supports-unicode", | |
| 246 | "terminal_size", | |
| 247 | "textwrap", | |
| 248 | "thiserror", | |
| 249 | "unicode-width", | |
| 250 | ] | |
| 251 | ||
| 252 | [[package]] | |
| 253 | name = "miette-derive" | |
| 254 | version = "5.10.0" | |
| 255 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 256 | checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" | |
| 257 | dependencies = [ | |
| 258 | "proc-macro2", | |
| 259 | "quote", | |
| 260 | "syn", | |
| 261 | ] | |
| 262 | ||
| 263 | [[package]] | |
| 264 | name = "miniz_oxide" | |
| 265 | version = "0.7.1" | |
| 266 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 267 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" | |
| 268 | dependencies = [ | |
| 269 | "adler", | |
| 270 | ] | |
| 271 | ||
| 272 | [[package]] | |
| 273 | name = "object" | |
| 274 | version = "0.32.2" | |
| 275 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 276 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" | |
| 277 | dependencies = [ | |
| 278 | "memchr", | |
| 279 | ] | |
| 280 | ||
| 281 | [[package]] | |
| 282 | name = "once_cell" | |
| 283 | version = "1.19.0" | |
| 284 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 285 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" | |
| 286 | ||
| 287 | [[package]] | |
| 288 | name = "owo-colors" | |
| 289 | version = "3.5.0" | |
| 290 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 291 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" | |
| 292 | ||
| 293 | [[package]] | |
| 294 | name = "proc-macro2" | |
| 295 | version = "1.0.73" | |
| 296 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 297 | checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1" | |
| 298 | dependencies = [ | |
| 299 | "unicode-ident", | |
| 300 | ] | |
| 301 | ||
| 302 | [[package]] | |
| 303 | name = "quote" | |
| 304 | version = "1.0.34" | |
| 305 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 306 | checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" | |
| 307 | dependencies = [ | |
| 308 | "proc-macro2", | |
| 309 | ] | |
| 310 | ||
| 311 | [[package]] | |
| 312 | name = "rustc-demangle" | |
| 313 | version = "0.1.23" | |
| 314 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 315 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" | |
| 316 | ||
| 317 | [[package]] | |
| 318 | name = "rustix" | |
| 319 | version = "0.38.28" | |
| 320 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 321 | checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" | |
| 322 | dependencies = [ | |
| 323 | "bitflags", | |
| 324 | "errno", | |
| 325 | "libc", | |
| 326 | "linux-raw-sys", | |
| 327 | "windows-sys", | |
| 328 | ] | |
| 329 | ||
| 330 | [[package]] | |
| 331 | name = "smawk" | |
| 332 | version = "0.3.2" | |
| 333 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 334 | checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" | |
| 335 | ||
| 336 | [[package]] | |
| 337 | name = "strsim" | |
| 338 | version = "0.10.0" | |
| 339 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 340 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | |
| 341 | ||
| 342 | [[package]] | |
| 343 | name = "supports-color" | |
| 344 | version = "2.1.0" | |
| 345 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 346 | checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" | |
| 347 | dependencies = [ | |
| 348 | "is-terminal", | |
| 349 | "is_ci", | |
| 350 | ] | |
| 351 | ||
| 352 | [[package]] | |
| 353 | name = "supports-hyperlinks" | |
| 354 | version = "2.1.0" | |
| 355 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 356 | checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" | |
| 357 | dependencies = [ | |
| 358 | "is-terminal", | |
| 359 | ] | |
| 360 | ||
| 361 | [[package]] | |
| 362 | name = "supports-unicode" | |
| 363 | version = "2.0.0" | |
| 364 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 365 | checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" | |
| 366 | dependencies = [ | |
| 367 | "is-terminal", | |
| 368 | ] | |
| 369 | ||
| 370 | [[package]] | |
| 371 | name = "syn" | |
| 372 | version = "2.0.44" | |
| 373 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 374 | checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d" | |
| 375 | dependencies = [ | |
| 376 | "proc-macro2", | |
| 377 | "quote", | |
| 378 | "unicode-ident", | |
| 379 | ] | |
| 380 | ||
| 381 | [[package]] | |
| 382 | name = "terminal_size" | |
| 383 | version = "0.1.17" | |
| 384 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 385 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" | |
| 386 | dependencies = [ | |
| 387 | "libc", | |
| 388 | "winapi", | |
| 389 | ] | |
| 390 | ||
| 391 | [[package]] | |
| 392 | name = "textwrap" | |
| 393 | version = "0.15.2" | |
| 394 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 395 | checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" | |
| 396 | dependencies = [ | |
| 397 | "smawk", | |
| 398 | "unicode-linebreak", | |
| 399 | "unicode-width", | |
| 400 | ] | |
| 401 | ||
| 402 | [[package]] | |
| 403 | name = "thiserror" | |
| 404 | version = "1.0.53" | |
| 405 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 406 | checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" | |
| 407 | dependencies = [ | |
| 408 | "thiserror-impl", | |
| 409 | ] | |
| 410 | ||
| 411 | [[package]] | |
| 412 | name = "thiserror-impl" | |
| 413 | version = "1.0.53" | |
| 414 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 415 | checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" | |
| 416 | dependencies = [ | |
| 417 | "proc-macro2", | |
| 418 | "quote", | |
| 419 | "syn", | |
| 420 | ] | |
| 421 | ||
| 422 | [[package]] | |
| 423 | name = "unicode-ident" | |
| 424 | version = "1.0.12" | |
| 425 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 426 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" | |
| 427 | ||
| 428 | [[package]] | |
| 429 | name = "unicode-linebreak" | |
| 430 | version = "0.1.5" | |
| 431 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 432 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" | |
| 433 | ||
| 434 | [[package]] | |
| 435 | name = "unicode-width" | |
| 436 | version = "0.1.11" | |
| 437 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 438 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" | |
| 439 | ||
| 440 | [[package]] | |
| 441 | name = "utf8parse" | |
| 442 | version = "0.2.1" | |
| 443 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 444 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | |
| 445 | ||
| 446 | [[package]] | |
| 447 | name = "winapi" | |
| 448 | version = "0.3.9" | |
| 449 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 450 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | |
| 451 | dependencies = [ | |
| 452 | "winapi-i686-pc-windows-gnu", | |
| 453 | "winapi-x86_64-pc-windows-gnu", | |
| 454 | ] | |
| 455 | ||
| 456 | [[package]] | |
| 457 | name = "winapi-i686-pc-windows-gnu" | |
| 458 | version = "0.4.0" | |
| 459 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 460 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | |
| 461 | ||
| 462 | [[package]] | |
| 463 | name = "winapi-x86_64-pc-windows-gnu" | |
| 464 | version = "0.4.0" | |
| 465 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 466 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |
| 467 | ||
| 468 | [[package]] | |
| 469 | name = "windows-sys" | |
| 470 | version = "0.52.0" | |
| 471 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 472 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | |
| 473 | dependencies = [ | |
| 474 | "windows-targets", | |
| 475 | ] | |
| 476 | ||
| 477 | [[package]] | |
| 478 | name = "windows-targets" | |
| 479 | version = "0.52.0" | |
| 480 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 481 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" | |
| 482 | dependencies = [ | |
| 483 | "windows_aarch64_gnullvm", | |
| 484 | "windows_aarch64_msvc", | |
| 485 | "windows_i686_gnu", | |
| 486 | "windows_i686_msvc", | |
| 487 | "windows_x86_64_gnu", | |
| 488 | "windows_x86_64_gnullvm", | |
| 489 | "windows_x86_64_msvc", | |
| 490 | ] | |
| 491 | ||
| 492 | [[package]] | |
| 493 | name = "windows_aarch64_gnullvm" | |
| 494 | version = "0.52.0" | |
| 495 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 496 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" | |
| 497 | ||
| 498 | [[package]] | |
| 499 | name = "windows_aarch64_msvc" | |
| 500 | version = "0.52.0" | |
| 501 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 502 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" | |
| 503 | ||
| 504 | [[package]] | |
| 505 | name = "windows_i686_gnu" | |
| 506 | version = "0.52.0" | |
| 507 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 508 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" | |
| 509 | ||
| 510 | [[package]] | |
| 511 | name = "windows_i686_msvc" | |
| 512 | version = "0.52.0" | |
| 513 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 514 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" | |
| 515 | ||
| 516 | [[package]] | |
| 517 | name = "windows_x86_64_gnu" | |
| 518 | version = "0.52.0" | |
| 519 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 520 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" | |
| 521 | ||
| 522 | [[package]] | |
| 523 | name = "windows_x86_64_gnullvm" | |
| 524 | version = "0.52.0" | |
| 525 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 526 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" | |
| 527 | ||
| 528 | [[package]] | |
| 529 | name = "windows_x86_64_msvc" | |
| 530 | version = "0.52.0" | |
| 531 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 532 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" |
compiler/Cargo.toml deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | [package] | |
| 2 | name = "compiler" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [lib] | |
| 7 | ||
| 8 | [dependencies] | |
| 9 | clap.workspace = true | |
| 10 | miette.workspace = true | |
| 11 | thiserror.workspace = true |
compiler/src/ast/error.rs deleted-17| ... | ... | @@ -1,17 +0,0 @@ |
| 1 | use miette::Diagnostic; | |
| 2 | use thiserror::Error; | |
| 3 | ||
| 4 | #[derive(Error, Diagnostic, Debug)] | |
| 5 | #[error("AstError")] | |
| 6 | pub struct AstError { | |
| 7 | #[help] | |
| 8 | error: String, | |
| 9 | } | |
| 10 | ||
| 11 | impl AstError { | |
| 12 | pub fn new(error: &'static str) -> AstError { | |
| 13 | AstError { | |
| 14 | error: String::from(error), | |
| 15 | } | |
| 16 | } | |
| 17 | } |
compiler/src/ast/mod.rs deleted-26| ... | ... | @@ -1,26 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | mod error; | |
| 4 | mod parse_block; | |
| 5 | mod parse_expression; | |
| 6 | mod parse_statement; | |
| 7 | mod parse_type; | |
| 8 | mod types; | |
| 9 | ||
| 10 | pub use super::tokenizer::Token; | |
| 11 | ||
| 12 | use parse_statement::parse_statement; | |
| 13 | use types::ParserContext; | |
| 14 | ||
| 15 | pub use types::{Ast, Block, Type}; | |
| 16 | ||
| 17 | pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> { | |
| 18 | let mut ctx = ParserContext::new(tokens); | |
| 19 | let mut ast: Vec<Ast> = Vec::new(); | |
| 20 | ||
| 21 | while !ctx.empty() { | |
| 22 | ast.push(parse_statement(&mut ctx)?); | |
| 23 | } | |
| 24 | ||
| 25 | Ok(ast) | |
| 26 | } |
compiler/src/ast/parse_block.rs deleted-54| ... | ... | @@ -1,54 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use super::error::AstError; | |
| 4 | use super::parse_expression::parse_expression; | |
| 5 | use super::parse_statement::parse_statement; | |
| 6 | use super::types::Block; | |
| 7 | use super::types::ParserContext; | |
| 8 | use super::Token; | |
| 9 | ||
| 10 | pub fn parse_block(tokens: &mut ParserContext) -> Result<Block> { | |
| 11 | match tokens.next() { | |
| 12 | Some(Token::OpenBracket) => (), | |
| 13 | _ => return Err(AstError::new("Expected { when parsing block").into()), | |
| 14 | } | |
| 15 | ||
| 16 | let mut value = Vec::new(); | |
| 17 | let mut implicit_return = false; | |
| 18 | ||
| 19 | loop { | |
| 20 | match tokens.peek() { | |
| 21 | Some(Token::ClosedBracket) => { | |
| 22 | tokens.next(); | |
| 23 | break; | |
| 24 | } | |
| 25 | _ => (), | |
| 26 | } | |
| 27 | ||
| 28 | let current_cursor = tokens.cursor; | |
| 29 | let result = parse_statement(tokens); | |
| 30 | ||
| 31 | match result { | |
| 32 | Ok(ast) => value.push(ast), | |
| 33 | Err(_) => { | |
| 34 | tokens.cursor = current_cursor; | |
| 35 | value.push(parse_expression(tokens)?); | |
| 36 | implicit_return = true; | |
| 37 | match tokens.peek() { | |
| 38 | Some(Token::ClosedBracket) => (), | |
| 39 | _ => { | |
| 40 | return Err(AstError::new( | |
| 41 | "Expected closed bracket after expression in function body", | |
| 42 | ) | |
| 43 | .into()); | |
| 44 | } | |
| 45 | } | |
| 46 | } | |
| 47 | } | |
| 48 | } | |
| 49 | ||
| 50 | Ok(Block { | |
| 51 | value, | |
| 52 | implicit_return, | |
| 53 | }) | |
| 54 | } |
compiler/src/ast/parse_expression.rs deleted-116| ... | ... | @@ -1,116 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use super::error::AstError; | |
| 4 | use super::parse_block::parse_block; | |
| 5 | use super::types::{Ast, ParserContext}; | |
| 6 | use super::Token; | |
| 7 | ||
| 8 | pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> { | |
| 9 | let left = match tokens.next() { | |
| 10 | Some(token) => match token { | |
| 11 | Token::Number(number) => Ast::Number(number.clone()), | |
| 12 | Token::String(string) => Ast::String(string.clone()), | |
| 13 | Token::True => Ast::Bool(true), | |
| 14 | Token::False => Ast::Bool(false), | |
| 15 | Token::OpenBracket => { | |
| 16 | // FRICK we consumed the open bracket | |
| 17 | // we need to put the cursor back | |
| 18 | tokens.back(); | |
| 19 | Ast::Block(parse_block(tokens)?) | |
| 20 | } | |
| 21 | Token::If => { | |
| 22 | let condition = parse_expression(tokens)?; | |
| 23 | ||
| 24 | let value = parse_block(tokens)?; | |
| 25 | ||
| 26 | let mut else_value = None; | |
| 27 | ||
| 28 | match tokens.peek() { | |
| 29 | Some(Token::Else) => { | |
| 30 | tokens.next(); | |
| 31 | match tokens.peek() { | |
| 32 | Option::Some(Token::If) => { | |
| 33 | else_value = Some(Box::new(parse_expression(tokens)?)); | |
| 34 | } | |
| 35 | Option::Some(Token::OpenBracket) => { | |
| 36 | else_value = Some(Box::new(Ast::Block(parse_block(tokens)?))); | |
| 37 | } | |
| 38 | _ => { | |
| 39 | return Err(AstError::new( | |
| 40 | "Expected if or open bracket after else in if statement", | |
| 41 | ) | |
| 42 | .into()) | |
| 43 | } | |
| 44 | } | |
| 45 | } | |
| 46 | _ => (), | |
| 47 | } | |
| 48 | ||
| 49 | return Ok(Ast::If { | |
| 50 | condition: Box::new(condition), | |
| 51 | value, | |
| 52 | else_value, | |
| 53 | }); | |
| 54 | } | |
| 55 | Token::Identifier(name) => match tokens.peek() { | |
| 56 | Some(Token::OpenParanthesis) => { | |
| 57 | tokens.next(); | |
| 58 | ||
| 59 | let mut arguments = Vec::new(); | |
| 60 | ||
| 61 | loop { | |
| 62 | match tokens.peek() { | |
| 63 | Some(Token::ClosedParanthesis) => { | |
| 64 | tokens.next(); | |
| 65 | break; | |
| 66 | } | |
| 67 | _ => (), | |
| 68 | } | |
| 69 | arguments.push(parse_expression(tokens)?); | |
| 70 | ||
| 71 | match tokens.peek() { | |
| 72 | Some(Token::Comma) => { | |
| 73 | tokens.next(); | |
| 74 | } | |
| 75 | Some(Token::ClosedParanthesis) => (), | |
| 76 | _ => { | |
| 77 | return Err(AstError::new( | |
| 78 | "Expected ) or , but found something else instead.", | |
| 79 | ) | |
| 80 | .into()) | |
| 81 | } | |
| 82 | } | |
| 83 | } | |
| 84 | ||
| 85 | Ast::FunctionCall { | |
| 86 | name: name.clone(), | |
| 87 | arguments, | |
| 88 | } | |
| 89 | } | |
| 90 | _ => Ast::Identifier(name.clone()), | |
| 91 | }, | |
| 92 | _ => { | |
| 93 | println!("token: {:?}", token); | |
| 94 | return Err(AstError::new("Expected expression, but did not get it").into()); | |
| 95 | } | |
| 96 | }, | |
| 97 | None => return Err(AstError::new("Expected expression, but got nothing instead").into()), | |
| 98 | }; | |
| 99 | ||
| 100 | match tokens.peek() { | |
| 101 | Some(token) => match token { | |
| 102 | Token::Operator(operator) => { | |
| 103 | tokens.next(); | |
| 104 | return Ok(Ast::Operation { | |
| 105 | operator: operator.clone(), | |
| 106 | left: Box::new(left), | |
| 107 | right: Box::new(parse_expression(tokens)?), | |
| 108 | }); | |
| 109 | } | |
| 110 | _ => (), | |
| 111 | }, | |
| 112 | _ => (), | |
| 113 | } | |
| 114 | ||
| 115 | Ok(left) | |
| 116 | } |
compiler/src/ast/parse_statement.rs deleted-268| ... | ... | @@ -1,268 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use super::error::AstError; | |
| 4 | use super::parse_block::parse_block; | |
| 5 | use super::parse_expression::parse_expression; | |
| 6 | use super::parse_type::parse_type; | |
| 7 | use super::types::{Argument, Ast, ParserContext}; | |
| 8 | use super::Token; | |
| 9 | ||
| 10 | /// Precondition: There is at least one token in the iterator | |
| 11 | pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> { | |
| 12 | let token = tokens.next().unwrap(); | |
| 13 | match token { | |
| 14 | Token::Pub => { | |
| 15 | match tokens.peek() { | |
| 16 | Some(Token::Let) | Some(Token::Var) | Some(Token::Function) => (), | |
| 17 | _ => return Err(AstError::new("Expected let, var, or fn after pub").into()), | |
| 18 | } | |
| 19 | ||
| 20 | let inner = parse_statement(tokens)?; | |
| 21 | ||
| 22 | return Ok(Ast::Public { | |
| 23 | value: Box::new(inner), | |
| 24 | }); | |
| 25 | } | |
| 26 | Token::Let => { | |
| 27 | let name = match tokens.next() { | |
| 28 | Some(Token::Identifier(name)) => name, | |
| 29 | _ => return Err(AstError::new("Expected identifier after var").into()), | |
| 30 | }; | |
| 31 | let return_type = match tokens.next() { | |
| 32 | Some(Token::Colon) => parse_type(tokens)?, | |
| 33 | _ => return Err(AstError::new("Expected colon after identifier").into()), | |
| 34 | }; | |
| 35 | let value = match tokens.next() { | |
| 36 | Some(Token::Equals) => parse_expression(tokens)?, | |
| 37 | _ => return Err(AstError::new("Expected equals after identifier").into()), | |
| 38 | }; | |
| 39 | match tokens.next() { | |
| 40 | Some(Token::Semicolon) => (), | |
| 41 | _ => { | |
| 42 | return Err( | |
| 43 | AstError::new("Expected semicolon after variable declaration").into(), | |
| 44 | ) | |
| 45 | } | |
| 46 | }; | |
| 47 | Ok(Ast::ConstantDeclaration { | |
| 48 | name: name.clone(), | |
| 49 | return_type, | |
| 50 | value: Box::new(value), | |
| 51 | }) | |
| 52 | } | |
| 53 | Token::Var => { | |
| 54 | let name = match tokens.next() { | |
| 55 | Some(Token::Identifier(name)) => name, | |
| 56 | _ => return Err(AstError::new("Expected identifier after var").into()), | |
| 57 | }; | |
| 58 | let return_type = match tokens.next() { | |
| 59 | Some(Token::Colon) => parse_type(tokens)?, | |
| 60 | _ => return Err(AstError::new("Expected colon after identifier").into()), | |
| 61 | }; | |
| 62 | let value = match tokens.next() { | |
| 63 | Some(Token::Equals) => parse_expression(tokens)?, | |
| 64 | _ => return Err(AstError::new("Expected equals after identifier").into()), | |
| 65 | }; | |
| 66 | match tokens.next() { | |
| 67 | Some(Token::Semicolon) => (), | |
| 68 | _ => { | |
| 69 | return Err( | |
| 70 | AstError::new("Expected semicolon after variable declaration").into(), | |
| 71 | ) | |
| 72 | } | |
| 73 | }; | |
| 74 | Ok(Ast::VariableDeclaration { | |
| 75 | name: name.clone(), | |
| 76 | return_type, | |
| 77 | value: Box::new(value), | |
| 78 | }) | |
| 79 | } | |
| 80 | Token::Return => { | |
| 81 | let expression = parse_expression(tokens)?; | |
| 82 | ||
| 83 | match tokens.next() { | |
| 84 | Some(Token::Semicolon) => (), | |
| 85 | _ => return Err(AstError::new("Expected semicolon after return statement").into()), | |
| 86 | }; | |
| 87 | ||
| 88 | Ok(Ast::Return { | |
| 89 | return_value: Box::new(expression), | |
| 90 | }) | |
| 91 | } | |
| 92 | Token::Function => { | |
| 93 | let name = match tokens.next() { | |
| 94 | Some(Token::Identifier(name)) => name.clone(), | |
| 95 | _ => return Err(AstError::new("Expected identifier after fn").into()), | |
| 96 | }; | |
| 97 | ||
| 98 | match tokens.next() { | |
| 99 | Some(Token::OpenParanthesis) => (), | |
| 100 | _ => { | |
| 101 | return Err(AstError::new( | |
| 102 | "Expected open paranthesis after identifier in function", | |
| 103 | ) | |
| 104 | .into()) | |
| 105 | } | |
| 106 | }; | |
| 107 | ||
| 108 | let mut arguments = Vec::new(); | |
| 109 | ||
| 110 | loop { | |
| 111 | match tokens.peek() { | |
| 112 | Some(Token::ClosedParanthesis) => { | |
| 113 | tokens.next(); | |
| 114 | break; | |
| 115 | } | |
| 116 | _ => (), | |
| 117 | } | |
| 118 | ||
| 119 | let argument_name = match tokens.next() { | |
| 120 | Some(Token::Identifier(name)) => name, | |
| 121 | _ => { | |
| 122 | return Err(AstError::new( | |
| 123 | "Expected identifier for argument name in function", | |
| 124 | ) | |
| 125 | .into()) | |
| 126 | } | |
| 127 | }; | |
| 128 | ||
| 129 | let return_type = match tokens.next() { | |
| 130 | Some(Token::Colon) => parse_type(tokens)?, | |
| 131 | _ => return Err(AstError::new("Expected colon after identifier").into()), | |
| 132 | }; | |
| 133 | ||
| 134 | match tokens.peek() { | |
| 135 | Some(Token::Comma) => { | |
| 136 | tokens.next(); | |
| 137 | } | |
| 138 | _ => (), | |
| 139 | } | |
| 140 | ||
| 141 | arguments.push(Argument { | |
| 142 | name: argument_name.clone(), | |
| 143 | return_type, | |
| 144 | }) | |
| 145 | } | |
| 146 | ||
| 147 | let return_type = match tokens.next() { | |
| 148 | Some(Token::RightArrow) => parse_type(tokens)?, | |
| 149 | _ => { | |
| 150 | return Err(AstError::new( | |
| 151 | "Expected right arrow after argument list in function", | |
| 152 | ) | |
| 153 | .into()) | |
| 154 | } | |
| 155 | }; | |
| 156 | ||
| 157 | match tokens.peek() { | |
| 158 | Some(Token::OpenBracket) => (), | |
| 159 | _ => { | |
| 160 | return Err(AstError::new( | |
| 161 | "Expected open bracket after type in function declaration", | |
| 162 | ) | |
| 163 | .into()) | |
| 164 | } | |
| 165 | }; | |
| 166 | ||
| 167 | let block = parse_block(tokens)?; | |
| 168 | ||
| 169 | return Ok(Ast::Function { | |
| 170 | name, | |
| 171 | arguments, | |
| 172 | return_type, | |
| 173 | block, | |
| 174 | }); | |
| 175 | } | |
| 176 | Token::If => { | |
| 177 | let condition = parse_expression(tokens)?; | |
| 178 | ||
| 179 | let value = parse_block(tokens)?; | |
| 180 | ||
| 181 | let mut else_value = None; | |
| 182 | ||
| 183 | match tokens.peek() { | |
| 184 | Some(Token::Else) => { | |
| 185 | tokens.next(); | |
| 186 | match tokens.peek() { | |
| 187 | Option::Some(Token::If) => { | |
| 188 | else_value = Some(Box::new(parse_expression(tokens)?)); | |
| 189 | } | |
| 190 | Option::Some(Token::OpenBracket) => { | |
| 191 | else_value = Some(Box::new(Ast::Block(parse_block(tokens)?))); | |
| 192 | } | |
| 193 | _ => { | |
| 194 | return Err(AstError::new( | |
| 195 | "Expected if or open bracket after else in if statement", | |
| 196 | ) | |
| 197 | .into()) | |
| 198 | } | |
| 199 | } | |
| 200 | } | |
| 201 | _ => (), | |
| 202 | } | |
| 203 | ||
| 204 | return Ok(Ast::If { | |
| 205 | condition: Box::new(condition), | |
| 206 | value, | |
| 207 | else_value, | |
| 208 | }); | |
| 209 | } | |
| 210 | Token::Identifier(name) => match tokens.peek() { | |
| 211 | Some(Token::OpenParanthesis) => { | |
| 212 | tokens.next(); | |
| 213 | ||
| 214 | let mut arguments = Vec::new(); | |
| 215 | ||
| 216 | loop { | |
| 217 | match tokens.peek() { | |
| 218 | Some(Token::ClosedParanthesis) => { | |
| 219 | tokens.next(); | |
| 220 | break; | |
| 221 | } | |
| 222 | _ => (), | |
| 223 | } | |
| 224 | arguments.push(parse_expression(tokens)?); | |
| 225 | ||
| 226 | match tokens.peek() { | |
| 227 | Some(Token::Comma) => { | |
| 228 | tokens.next(); | |
| 229 | } | |
| 230 | Some(Token::ClosedParanthesis) => (), | |
| 231 | _ => { | |
| 232 | return Err(AstError::new( | |
| 233 | "Expected ) or , but found something else instead.", | |
| 234 | ) | |
| 235 | .into()) | |
| 236 | } | |
| 237 | } | |
| 238 | } | |
| 239 | ||
| 240 | match tokens.next() { | |
| 241 | Some(Token::Semicolon) => (), | |
| 242 | _ => return Err(AstError::new("Expected semicolon after function call").into()), | |
| 243 | }; | |
| 244 | ||
| 245 | Ok(Ast::FunctionCall { | |
| 246 | name: name.clone(), | |
| 247 | arguments, | |
| 248 | }) | |
| 249 | } | |
| 250 | _ => Err(AstError::new("Unexpected identifier").into()), | |
| 251 | }, | |
| 252 | Token::Comment(comment) => Ok(Ast::Comment(comment.clone())), | |
| 253 | Token::DocComment(comment) => { | |
| 254 | let mut concatted_comments = comment.clone(); | |
| 255 | loop { | |
| 256 | match tokens.peek() { | |
| 257 | Some(Token::DocComment(comment)) => { | |
| 258 | concatted_comments.push_str(format!("\n{}", comment).as_str()); | |
| 259 | tokens.next(); | |
| 260 | } | |
| 261 | _ => break, | |
| 262 | } | |
| 263 | } | |
| 264 | Ok(Ast::DocComment(concatted_comments)) | |
| 265 | } | |
| 266 | _ => return Err(AstError::new("Unexpected token").into()), | |
| 267 | } | |
| 268 | } |
compiler/src/ast/parse_type.rs deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use super::error::AstError; | |
| 4 | use super::types::{ParserContext, Type}; | |
| 5 | use super::Token; | |
| 6 | ||
| 7 | pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> { | |
| 8 | match tokens.next() { | |
| 9 | Some(Token::Identifier(typ)) => match typ.as_str() { | |
| 10 | "int" => Ok(Type::Int), | |
| 11 | "float" => Ok(Type::Float), | |
| 12 | "bigint" => Ok(Type::Bigint), | |
| 13 | "bool" => Ok(Type::Bool), | |
| 14 | "string" => Ok(Type::String), | |
| 15 | _ => return Err(AstError::new("Expected type").into()), | |
| 16 | }, | |
| 17 | _ => return Err(AstError::new("Expected type").into()), | |
| 18 | } | |
| 19 | } |
compiler/src/ast/types.rs deleted-110| ... | ... | @@ -1,110 +0,0 @@ |
| 1 | // TODO(lino-levan): Split up AST into expressions, statements, etc. | |
| 2 | ||
| 3 | use crate::tokenizer::Token; | |
| 4 | use crate::util::Operator; | |
| 5 | ||
| 6 | #[derive(Debug)] | |
| 7 | pub struct ParserContext { | |
| 8 | pub tokens: Vec<Token>, | |
| 9 | pub cursor: usize, | |
| 10 | } | |
| 11 | ||
| 12 | impl ParserContext { | |
| 13 | pub fn new(tokens: Vec<Token>) -> ParserContext { | |
| 14 | ParserContext { tokens, cursor: 0 } | |
| 15 | } | |
| 16 | ||
| 17 | pub fn empty(&self) -> bool { | |
| 18 | self.cursor == self.tokens.len() | |
| 19 | } | |
| 20 | ||
| 21 | pub fn back(&mut self) { | |
| 22 | self.cursor -= 1; | |
| 23 | } | |
| 24 | ||
| 25 | pub fn next(&mut self) -> Option<Token> { | |
| 26 | if self.cursor == self.tokens.len() { | |
| 27 | return None; | |
| 28 | } | |
| 29 | ||
| 30 | let token = self.tokens[self.cursor].clone(); | |
| 31 | self.cursor += 1; | |
| 32 | Some(token) | |
| 33 | } | |
| 34 | ||
| 35 | pub fn peek(&self) -> Option<Token> { | |
| 36 | if self.cursor == self.tokens.len() { | |
| 37 | return None; | |
| 38 | } | |
| 39 | ||
| 40 | Some(self.tokens[self.cursor].clone()) | |
| 41 | } | |
| 42 | } | |
| 43 | ||
| 44 | #[derive(Debug)] | |
| 45 | pub enum Type { | |
| 46 | Int, | |
| 47 | Float, | |
| 48 | Bigint, | |
| 49 | Bool, | |
| 50 | String, | |
| 51 | } | |
| 52 | ||
| 53 | #[derive(Debug)] | |
| 54 | pub struct Block { | |
| 55 | pub value: Vec<Ast>, | |
| 56 | pub implicit_return: bool, | |
| 57 | } | |
| 58 | ||
| 59 | #[derive(Debug)] | |
| 60 | pub struct Argument { | |
| 61 | pub name: String, | |
| 62 | pub return_type: Type, | |
| 63 | } | |
| 64 | ||
| 65 | #[derive(Debug)] | |
| 66 | pub enum Ast { | |
| 67 | Public { | |
| 68 | value: Box<Ast>, | |
| 69 | }, | |
| 70 | ConstantDeclaration { | |
| 71 | name: String, | |
| 72 | return_type: Type, | |
| 73 | value: Box<Ast>, | |
| 74 | }, | |
| 75 | VariableDeclaration { | |
| 76 | name: String, | |
| 77 | return_type: Type, | |
| 78 | value: Box<Ast>, | |
| 79 | }, | |
| 80 | Operation { | |
| 81 | operator: Operator, | |
| 82 | left: Box<Ast>, | |
| 83 | right: Box<Ast>, | |
| 84 | }, | |
| 85 | Return { | |
| 86 | return_value: Box<Ast>, | |
| 87 | }, | |
| 88 | Function { | |
| 89 | name: String, | |
| 90 | arguments: Vec<Argument>, | |
| 91 | return_type: Type, | |
| 92 | block: Block, | |
| 93 | }, | |
| 94 | FunctionCall { | |
| 95 | name: String, | |
| 96 | arguments: Vec<Ast>, | |
| 97 | }, | |
| 98 | If { | |
| 99 | condition: Box<Ast>, | |
| 100 | value: Block, | |
| 101 | else_value: Option<Box<Ast>>, | |
| 102 | }, | |
| 103 | Block(Block), | |
| 104 | Number(String), | |
| 105 | Bool(bool), | |
| 106 | String(String), | |
| 107 | Identifier(String), | |
| 108 | Comment(String), | |
| 109 | DocComment(String), | |
| 110 | } |
compiler/src/lib.rs deleted-20| ... | ... | @@ -1,20 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | pub mod ast; | |
| 4 | pub mod tokenizer; | |
| 5 | pub mod printer; | |
| 6 | ||
| 7 | pub mod util; | |
| 8 | ||
| 9 | pub fn transpile(content: String) -> Result<String> { | |
| 10 | // 1. Tokenize the input | |
| 11 | let tokens = tokenizer::tokenize(content)?; | |
| 12 | // 2. Parse the tokens into an AST | |
| 13 | let tree = ast::parse(tokens)?; | |
| 14 | // 3. Type check the AST | |
| 15 | // type_check(tree.clone())?; | |
| 16 | // 4. Transpile the AST into javascript | |
| 17 | let result = printer::transpile(tree)?; | |
| 18 | // 5. Return the javascript | |
| 19 | return Ok(result); | |
| 20 | } |
compiler/src/printer/mod.rs deleted-139| ... | ... | @@ -1,139 +0,0 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use super::ast::{Ast, Type}; | |
| 4 | ||
| 5 | fn transpile_helper(tree: &Ast) -> Result<String> { | |
| 6 | Ok(match tree { | |
| 7 | Ast::Number(number) => format!("{}", number), | |
| 8 | Ast::Identifier(name) => format!("{}", name), | |
| 9 | Ast::Bool(value) => format!("{}", value), | |
| 10 | Ast::String(value) => format!("\"{}\"", value), | |
| 11 | Ast::Comment(comment) => format!("// {}\n", comment), | |
| 12 | Ast::DocComment(comment) => format!("/** {} */\n", comment), | |
| 13 | Ast::Operation { | |
| 14 | operator, | |
| 15 | left, | |
| 16 | right, | |
| 17 | } => format!( | |
| 18 | "{} {} {}", | |
| 19 | transpile_helper(left)?, | |
| 20 | operator.clone().to_string(), | |
| 21 | transpile_helper(right)? | |
| 22 | ), | |
| 23 | Ast::Public { value } => format!("export {}", transpile_helper(value)?), | |
| 24 | Ast::VariableDeclaration { | |
| 25 | name, | |
| 26 | return_type, | |
| 27 | value, | |
| 28 | } => match return_type { | |
| 29 | Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(value)?), | |
| 30 | _ => format!("let {} = {};\n", name, transpile_helper(value)?), | |
| 31 | }, | |
| 32 | Ast::ConstantDeclaration { | |
| 33 | name, | |
| 34 | return_type, | |
| 35 | value, | |
| 36 | } => match return_type { | |
| 37 | Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(value)?), | |
| 38 | _ => format!("const {} = {};\n", name, transpile_helper(value)?), | |
| 39 | }, | |
| 40 | Ast::Return { return_value } => format!("return {};\n", transpile_helper(return_value)?), | |
| 41 | Ast::Function { | |
| 42 | name, | |
| 43 | arguments, | |
| 44 | return_type: _, | |
| 45 | block, | |
| 46 | } => { | |
| 47 | let mut result = format!("function {}(", name); | |
| 48 | ||
| 49 | for (i, argument) in arguments.iter().enumerate() { | |
| 50 | if i == 0 { | |
| 51 | result += argument.name.as_str(); | |
| 52 | } else { | |
| 53 | result += format!(", {}", argument.name).as_str(); | |
| 54 | } | |
| 55 | } | |
| 56 | ||
| 57 | result += ") {\n"; | |
| 58 | ||
| 59 | for (i, statement) in block.value.iter().enumerate() { | |
| 60 | if block.implicit_return && i == block.value.len() - 1 { | |
| 61 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 62 | break; | |
| 63 | } | |
| 64 | result += transpile_helper(statement)?.as_str(); | |
| 65 | } | |
| 66 | ||
| 67 | result += "}\n"; | |
| 68 | ||
| 69 | result | |
| 70 | } | |
| 71 | Ast::If { | |
| 72 | condition, | |
| 73 | value, | |
| 74 | else_value, | |
| 75 | } => { | |
| 76 | let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,); | |
| 77 | ||
| 78 | for (i, statement) in value.value.iter().enumerate() { | |
| 79 | if value.implicit_return && i == value.value.len() - 1 { | |
| 80 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 81 | break; | |
| 82 | } | |
| 83 | result += transpile_helper(statement)?.as_str(); | |
| 84 | } | |
| 85 | ||
| 86 | result += "}"; | |
| 87 | ||
| 88 | if let Some(val) = else_value { | |
| 89 | result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str(); | |
| 90 | } else { | |
| 91 | result += "\n"; | |
| 92 | } | |
| 93 | ||
| 94 | result | |
| 95 | } | |
| 96 | Ast::FunctionCall { name, arguments } => { | |
| 97 | let mut result = match name.as_str() { | |
| 98 | "print" => String::from("console.log("), | |
| 99 | _ => format!("{}(", name), | |
| 100 | }; | |
| 101 | ||
| 102 | for (i, argument) in arguments.iter().enumerate() { | |
| 103 | if i == 0 { | |
| 104 | result += transpile_helper(argument)?.as_str(); | |
| 105 | } else { | |
| 106 | result += format!(", {}", transpile_helper(argument)?).as_str(); | |
| 107 | } | |
| 108 | } | |
| 109 | ||
| 110 | result += ")"; | |
| 111 | ||
| 112 | result | |
| 113 | } | |
| 114 | Ast::Block(block) => { | |
| 115 | let mut result = String::from("(()=>{\n"); | |
| 116 | for (i, statement) in block.value.iter().enumerate() { | |
| 117 | if block.implicit_return && i == block.value.len() - 1 { | |
| 118 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 119 | break; | |
| 120 | } | |
| 121 | result += transpile_helper(statement)?.as_str(); | |
| 122 | } | |
| 123 | ||
| 124 | result += "})()\n"; | |
| 125 | ||
| 126 | result | |
| 127 | } | |
| 128 | }) | |
| 129 | } | |
| 130 | ||
| 131 | pub fn transpile(forest: Vec<Ast>) -> Result<String> { | |
| 132 | let mut result = String::new(); | |
| 133 | ||
| 134 | for tree in forest { | |
| 135 | result.push_str(&transpile_helper(&tree)?); | |
| 136 | } | |
| 137 | ||
| 138 | Ok(result) | |
| 139 | } |
compiler/src/tokenizer.rs deleted-199| ... | ... | @@ -1,199 +0,0 @@ |
| 1 | use miette::{Diagnostic, Result}; | |
| 2 | use thiserror::Error; | |
| 3 | ||
| 4 | use super::util::Operator; | |
| 5 | ||
| 6 | #[derive(Error, Diagnostic, Debug)] | |
| 7 | #[error("UnknownCharacter")] | |
| 8 | struct UnknownCharacter { | |
| 9 | #[help] | |
| 10 | error: String, | |
| 11 | } | |
| 12 | ||
| 13 | #[derive(Debug, Clone)] | |
| 14 | pub enum Token { | |
| 15 | // Literals | |
| 16 | Identifier(String), | |
| 17 | Number(String), | |
| 18 | String(String), | |
| 19 | // Comments | |
| 20 | Comment(String), | |
| 21 | DocComment(String), | |
| 22 | // Keywords | |
| 23 | True, | |
| 24 | False, | |
| 25 | Let, | |
| 26 | Var, | |
| 27 | If, | |
| 28 | Else, | |
| 29 | Return, | |
| 30 | Pub, | |
| 31 | Function, | |
| 32 | RightArrow, | |
| 33 | Comma, | |
| 34 | OpenParanthesis, | |
| 35 | ClosedParanthesis, | |
| 36 | OpenBracket, | |
| 37 | ClosedBracket, | |
| 38 | Colon, | |
| 39 | Equals, | |
| 40 | Semicolon, | |
| 41 | // Operators | |
| 42 | Operator(Operator), | |
| 43 | } | |
| 44 | ||
| 45 | pub fn tokenize(content: String) -> Result<Vec<Token>> { | |
| 46 | let mut tokens: Vec<Token> = Vec::new(); | |
| 47 | let mut chars = content.chars().enumerate().peekable(); | |
| 48 | ||
| 49 | loop { | |
| 50 | match chars.next() { | |
| 51 | Some((_, c)) => match c { | |
| 52 | 'a'..='z' | 'A'..='Z' | '_' => { | |
| 53 | let mut current_token = String::new(); | |
| 54 | current_token.push(c); | |
| 55 | loop { | |
| 56 | let c = chars.peek(); | |
| 57 | if c.is_none() { | |
| 58 | break; | |
| 59 | } | |
| 60 | let (_, c) = c.unwrap(); | |
| 61 | match c { | |
| 62 | 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => { | |
| 63 | current_token.push(*c); | |
| 64 | chars.next(); | |
| 65 | } | |
| 66 | _ => break, | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | match current_token.as_str() { | |
| 71 | "var" => tokens.push(Token::Var), | |
| 72 | "let" => tokens.push(Token::Let), | |
| 73 | "if" => tokens.push(Token::If), | |
| 74 | "else" => tokens.push(Token::Else), | |
| 75 | "pub" => tokens.push(Token::Pub), | |
| 76 | "fn" => tokens.push(Token::Function), | |
| 77 | "return" => tokens.push(Token::Return), | |
| 78 | "true" => tokens.push(Token::True), | |
| 79 | "false" => tokens.push(Token::False), | |
| 80 | _ => tokens.push(Token::Identifier(current_token)), | |
| 81 | } | |
| 82 | } | |
| 83 | '"' => { | |
| 84 | let mut current_token = String::new(); | |
| 85 | loop { | |
| 86 | let c = chars.next(); | |
| 87 | if c.is_none() { | |
| 88 | break; | |
| 89 | } | |
| 90 | let (_, c) = c.unwrap(); | |
| 91 | match c { | |
| 92 | '"' => break, | |
| 93 | _ => current_token.push(c), | |
| 94 | } | |
| 95 | } | |
| 96 | tokens.push(Token::String(current_token)); | |
| 97 | } | |
| 98 | '0'..='9' => { | |
| 99 | let mut current_token = String::new(); | |
| 100 | current_token.push(c); | |
| 101 | loop { | |
| 102 | let c = chars.peek(); | |
| 103 | if c.is_none() { | |
| 104 | break; | |
| 105 | } | |
| 106 | let (_, c) = c.unwrap(); | |
| 107 | match c { | |
| 108 | '0'..='9' => { | |
| 109 | current_token.push(*c); | |
| 110 | chars.next(); | |
| 111 | } | |
| 112 | _ => break, | |
| 113 | } | |
| 114 | } | |
| 115 | tokens.push(Token::Number(current_token)); | |
| 116 | } | |
| 117 | ':' => tokens.push(Token::Colon), | |
| 118 | '=' => match chars.peek() { | |
| 119 | Some((_, '=')) => { | |
| 120 | chars.next(); | |
| 121 | tokens.push(Token::Operator(Operator::Equals)); | |
| 122 | } | |
| 123 | _ => tokens.push(Token::Equals), | |
| 124 | }, | |
| 125 | ';' => tokens.push(Token::Semicolon), | |
| 126 | '>' => tokens.push(Token::Operator(Operator::GreaterThan)), | |
| 127 | '+' => tokens.push(Token::Operator(Operator::Add)), | |
| 128 | '-' => match chars.peek() { | |
| 129 | Some((_, '>')) => { | |
| 130 | chars.next(); | |
| 131 | tokens.push(Token::RightArrow); | |
| 132 | } | |
| 133 | _ => tokens.push(Token::Operator(Operator::Substract)), | |
| 134 | }, | |
| 135 | '*' => match chars.peek() { | |
| 136 | Some((_, '*')) => { | |
| 137 | chars.next(); | |
| 138 | tokens.push(Token::Operator(Operator::Power)); | |
| 139 | } | |
| 140 | _ => tokens.push(Token::Operator(Operator::Multiply)), | |
| 141 | }, | |
| 142 | '/' => { | |
| 143 | match chars.peek() { | |
| 144 | Some((_, '/')) => { | |
| 145 | chars.next(); // Consume the second slash | |
| 146 | ||
| 147 | let is_doc_comment = match chars.peek() { | |
| 148 | Some((_, '/')) => { | |
| 149 | chars.next(); // Consume the third slash | |
| 150 | true | |
| 151 | } | |
| 152 | _ => false, | |
| 153 | }; | |
| 154 | ||
| 155 | let mut comment = String::new(); | |
| 156 | loop { | |
| 157 | let c = chars.next(); | |
| 158 | if c.is_none() { | |
| 159 | break; | |
| 160 | } | |
| 161 | let (_, c) = c.unwrap(); | |
| 162 | match c { | |
| 163 | '\n' => break, | |
| 164 | _ => { | |
| 165 | comment.push(c.clone()); | |
| 166 | } | |
| 167 | } | |
| 168 | } | |
| 169 | ||
| 170 | comment = comment.trim().to_string(); | |
| 171 | ||
| 172 | if is_doc_comment { | |
| 173 | tokens.push(Token::DocComment(comment)); | |
| 174 | } else { | |
| 175 | tokens.push(Token::Comment(comment)); | |
| 176 | } | |
| 177 | } | |
| 178 | _ => tokens.push(Token::Operator(Operator::Divide)), | |
| 179 | } | |
| 180 | } | |
| 181 | ',' => tokens.push(Token::Comma), | |
| 182 | '(' => tokens.push(Token::OpenParanthesis), | |
| 183 | ')' => tokens.push(Token::ClosedParanthesis), | |
| 184 | '{' => tokens.push(Token::OpenBracket), | |
| 185 | '}' => tokens.push(Token::ClosedBracket), | |
| 186 | s if s.is_whitespace() => (), | |
| 187 | _ => { | |
| 188 | return Err(UnknownCharacter { | |
| 189 | error: format!("Unsupported character: {}", c), | |
| 190 | } | |
| 191 | .into()) | |
| 192 | } | |
| 193 | }, | |
| 194 | None => break, | |
| 195 | } | |
| 196 | } | |
| 197 | ||
| 198 | Ok(tokens) | |
| 199 | } |
compiler/src/util.rs deleted-24| ... | ... | @@ -1,24 +0,0 @@ |
| 1 | #[derive(Debug, Clone)] | |
| 2 | pub enum Operator { | |
| 3 | Add, | |
| 4 | Substract, | |
| 5 | Multiply, | |
| 6 | Divide, | |
| 7 | Power, | |
| 8 | Equals, | |
| 9 | GreaterThan, | |
| 10 | } | |
| 11 | ||
| 12 | impl Operator { | |
| 13 | pub fn to_string(self) -> String { | |
| 14 | String::from(match self { | |
| 15 | Self::Add => "+", | |
| 16 | Self::Substract => "-", | |
| 17 | Self::Divide => "/", | |
| 18 | Self::Multiply => "*", | |
| 19 | Self::Power => "**", | |
| 20 | Self::Equals => "===", | |
| 21 | Self::GreaterThan => ">", | |
| 22 | }) | |
| 23 | } | |
| 24 | } |
crates/ast/Cargo.toml created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | [package] | |
| 2 | name = "ast" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [lib] | |
| 7 | ||
| 8 | [dependencies] | |
| 9 | miette.workspace = true | |
| 10 | thiserror.workspace = true | |
| 11 | ||
| 12 | tokenizer = { path = "../tokenizer" } | |
| 13 | util = { path = "../util" } |
crates/ast/src/error.rs created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | use miette::Diagnostic; | |
| 2 | use thiserror::Error; | |
| 3 | ||
| 4 | #[derive(Error, Diagnostic, Debug)] | |
| 5 | #[error("AstError")] | |
| 6 | pub struct AstError { | |
| 7 | #[help] | |
| 8 | error: String, | |
| 9 | } | |
| 10 | ||
| 11 | impl AstError { | |
| 12 | pub fn new(error: &'static str) -> AstError { | |
| 13 | AstError { | |
| 14 | error: String::from(error), | |
| 15 | } | |
| 16 | } | |
| 17 | } |
crates/ast/src/lib.rs created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | mod error; | |
| 4 | mod parse_block; | |
| 5 | mod parse_expression; | |
| 6 | mod parse_statement; | |
| 7 | mod parse_type; | |
| 8 | mod types; | |
| 9 | ||
| 10 | use tokenizer::Token; | |
| 11 | ||
| 12 | use parse_statement::parse_statement; | |
| 13 | use types::ParserContext; | |
| 14 | ||
| 15 | pub use types::{Ast, Block, Type}; | |
| 16 | ||
| 17 | pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> { | |
| 18 | let mut ctx = ParserContext::new(tokens); | |
| 19 | let mut ast: Vec<Ast> = Vec::new(); | |
| 20 | ||
| 21 | while !ctx.empty() { | |
| 22 | ast.push(parse_statement(&mut ctx)?); | |
| 23 | } | |
| 24 | ||
| 25 | Ok(ast) | |
| 26 | } |
crates/ast/src/parse_block.rs created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use tokenizer::Token; | |
| 4 | ||
| 5 | use super::error::AstError; | |
| 6 | use super::parse_expression::parse_expression; | |
| 7 | use super::parse_statement::parse_statement; | |
| 8 | use super::types::Block; | |
| 9 | use super::types::ParserContext; | |
| 10 | ||
| 11 | pub fn parse_block(tokens: &mut ParserContext) -> Result<Block> { | |
| 12 | match tokens.next() { | |
| 13 | Some(Token::OpenBracket) => (), | |
| 14 | _ => return Err(AstError::new("Expected { when parsing block").into()), | |
| 15 | } | |
| 16 | ||
| 17 | let mut value = Vec::new(); | |
| 18 | let mut implicit_return = false; | |
| 19 | ||
| 20 | loop { | |
| 21 | match tokens.peek() { | |
| 22 | Some(Token::ClosedBracket) => { | |
| 23 | tokens.next(); | |
| 24 | break; | |
| 25 | } | |
| 26 | _ => (), | |
| 27 | } | |
| 28 | ||
| 29 | let current_cursor = tokens.cursor; | |
| 30 | let result = parse_statement(tokens); | |
| 31 | ||
| 32 | match result { | |
| 33 | Ok(ast) => value.push(ast), | |
| 34 | Err(_) => { | |
| 35 | tokens.cursor = current_cursor; | |
| 36 | value.push(parse_expression(tokens)?); | |
| 37 | implicit_return = true; | |
| 38 | match tokens.peek() { | |
| 39 | Some(Token::ClosedBracket) => (), | |
| 40 | _ => { | |
| 41 | return Err(AstError::new( | |
| 42 | "Expected closed bracket after expression in function body", | |
| 43 | ) | |
| 44 | .into()); | |
| 45 | } | |
| 46 | } | |
| 47 | } | |
| 48 | } | |
| 49 | } | |
| 50 | ||
| 51 | Ok(Block { | |
| 52 | value, | |
| 53 | implicit_return, | |
| 54 | }) | |
| 55 | } |
crates/ast/src/parse_expression.rs created+117| ... | ... | @@ -0,0 +1,117 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use tokenizer::Token; | |
| 4 | ||
| 5 | use super::error::AstError; | |
| 6 | use super::parse_block::parse_block; | |
| 7 | use super::types::{Ast, ParserContext}; | |
| 8 | ||
| 9 | pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> { | |
| 10 | let left = match tokens.next() { | |
| 11 | Some(token) => match token { | |
| 12 | Token::Number(number) => Ast::Number(number.clone()), | |
| 13 | Token::String(string) => Ast::String(string.clone()), | |
| 14 | Token::True => Ast::Bool(true), | |
| 15 | Token::False => Ast::Bool(false), | |
| 16 | Token::OpenBracket => { | |
| 17 | // FRICK we consumed the open bracket | |
| 18 | // we need to put the cursor back | |
| 19 | tokens.back(); | |
| 20 | Ast::Block(parse_block(tokens)?) | |
| 21 | } | |
| 22 | Token::If => { | |
| 23 | let condition = parse_expression(tokens)?; | |
| 24 | ||
| 25 | let value = parse_block(tokens)?; | |
| 26 | ||
| 27 | let mut else_value = None; | |
| 28 | ||
| 29 | match tokens.peek() { | |
| 30 | Some(Token::Else) => { | |
| 31 | tokens.next(); | |
| 32 | match tokens.peek() { | |
| 33 | Option::Some(Token::If) => { | |
| 34 | else_value = Some(Box::new(parse_expression(tokens)?)); | |
| 35 | } | |
| 36 | Option::Some(Token::OpenBracket) => { | |
| 37 | else_value = Some(Box::new(Ast::Block(parse_block(tokens)?))); | |
| 38 | } | |
| 39 | _ => { | |
| 40 | return Err(AstError::new( | |
| 41 | "Expected if or open bracket after else in if statement", | |
| 42 | ) | |
| 43 | .into()) | |
| 44 | } | |
| 45 | } | |
| 46 | } | |
| 47 | _ => (), | |
| 48 | } | |
| 49 | ||
| 50 | return Ok(Ast::If { | |
| 51 | condition: Box::new(condition), | |
| 52 | value, | |
| 53 | else_value, | |
| 54 | }); | |
| 55 | } | |
| 56 | Token::Identifier(name) => match tokens.peek() { | |
| 57 | Some(Token::OpenParanthesis) => { | |
| 58 | tokens.next(); | |
| 59 | ||
| 60 | let mut arguments = Vec::new(); | |
| 61 | ||
| 62 | loop { | |
| 63 | match tokens.peek() { | |
| 64 | Some(Token::ClosedParanthesis) => { | |
| 65 | tokens.next(); | |
| 66 | break; | |
| 67 | } | |
| 68 | _ => (), | |
| 69 | } | |
| 70 | arguments.push(parse_expression(tokens)?); | |
| 71 | ||
| 72 | match tokens.peek() { | |
| 73 | Some(Token::Comma) => { | |
| 74 | tokens.next(); | |
| 75 | } | |
| 76 | Some(Token::ClosedParanthesis) => (), | |
| 77 | _ => { | |
| 78 | return Err(AstError::new( | |
| 79 | "Expected ) or , but found something else instead.", | |
| 80 | ) | |
| 81 | .into()) | |
| 82 | } | |
| 83 | } | |
| 84 | } | |
| 85 | ||
| 86 | Ast::FunctionCall { | |
| 87 | name: name.clone(), | |
| 88 | arguments, | |
| 89 | } | |
| 90 | } | |
| 91 | _ => Ast::Identifier(name.clone()), | |
| 92 | }, | |
| 93 | _ => { | |
| 94 | println!("token: {:?}", token); | |
| 95 | return Err(AstError::new("Expected expression, but did not get it").into()); | |
| 96 | } | |
| 97 | }, | |
| 98 | None => return Err(AstError::new("Expected expression, but got nothing instead").into()), | |
| 99 | }; | |
| 100 | ||
| 101 | match tokens.peek() { | |
| 102 | Some(token) => match token { | |
| 103 | Token::Operator(operator) => { | |
| 104 | tokens.next(); | |
| 105 | return Ok(Ast::Operation { | |
| 106 | operator: operator.clone(), | |
| 107 | left: Box::new(left), | |
| 108 | right: Box::new(parse_expression(tokens)?), | |
| 109 | }); | |
| 110 | } | |
| 111 | _ => (), | |
| 112 | }, | |
| 113 | _ => (), | |
| 114 | } | |
| 115 | ||
| 116 | Ok(left) | |
| 117 | } |
crates/ast/src/parse_statement.rs created+269| ... | ... | @@ -0,0 +1,269 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use tokenizer::Token; | |
| 4 | ||
| 5 | use super::error::AstError; | |
| 6 | use super::parse_block::parse_block; | |
| 7 | use super::parse_expression::parse_expression; | |
| 8 | use super::parse_type::parse_type; | |
| 9 | use super::types::{Argument, Ast, ParserContext}; | |
| 10 | ||
| 11 | /// Precondition: There is at least one token in the iterator | |
| 12 | pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> { | |
| 13 | let token = tokens.next().unwrap(); | |
| 14 | match token { | |
| 15 | Token::Pub => { | |
| 16 | match tokens.peek() { | |
| 17 | Some(Token::Let) | Some(Token::Var) | Some(Token::Function) => (), | |
| 18 | _ => return Err(AstError::new("Expected let, var, or fn after pub").into()), | |
| 19 | } | |
| 20 | ||
| 21 | let inner = parse_statement(tokens)?; | |
| 22 | ||
| 23 | return Ok(Ast::Public { | |
| 24 | value: Box::new(inner), | |
| 25 | }); | |
| 26 | } | |
| 27 | Token::Let => { | |
| 28 | let name = match tokens.next() { | |
| 29 | Some(Token::Identifier(name)) => name, | |
| 30 | _ => return Err(AstError::new("Expected identifier after var").into()), | |
| 31 | }; | |
| 32 | let return_type = match tokens.next() { | |
| 33 | Some(Token::Colon) => parse_type(tokens)?, | |
| 34 | _ => return Err(AstError::new("Expected colon after identifier").into()), | |
| 35 | }; | |
| 36 | let value = match tokens.next() { | |
| 37 | Some(Token::Equals) => parse_expression(tokens)?, | |
| 38 | _ => return Err(AstError::new("Expected equals after identifier").into()), | |
| 39 | }; | |
| 40 | match tokens.next() { | |
| 41 | Some(Token::Semicolon) => (), | |
| 42 | _ => { | |
| 43 | return Err( | |
| 44 | AstError::new("Expected semicolon after variable declaration").into(), | |
| 45 | ) | |
| 46 | } | |
| 47 | }; | |
| 48 | Ok(Ast::ConstantDeclaration { | |
| 49 | name: name.clone(), | |
| 50 | return_type, | |
| 51 | value: Box::new(value), | |
| 52 | }) | |
| 53 | } | |
| 54 | Token::Var => { | |
| 55 | let name = match tokens.next() { | |
| 56 | Some(Token::Identifier(name)) => name, | |
| 57 | _ => return Err(AstError::new("Expected identifier after var").into()), | |
| 58 | }; | |
| 59 | let return_type = match tokens.next() { | |
| 60 | Some(Token::Colon) => parse_type(tokens)?, | |
| 61 | _ => return Err(AstError::new("Expected colon after identifier").into()), | |
| 62 | }; | |
| 63 | let value = match tokens.next() { | |
| 64 | Some(Token::Equals) => parse_expression(tokens)?, | |
| 65 | _ => return Err(AstError::new("Expected equals after identifier").into()), | |
| 66 | }; | |
| 67 | match tokens.next() { | |
| 68 | Some(Token::Semicolon) => (), | |
| 69 | _ => { | |
| 70 | return Err( | |
| 71 | AstError::new("Expected semicolon after variable declaration").into(), | |
| 72 | ) | |
| 73 | } | |
| 74 | }; | |
| 75 | Ok(Ast::VariableDeclaration { | |
| 76 | name: name.clone(), | |
| 77 | return_type, | |
| 78 | value: Box::new(value), | |
| 79 | }) | |
| 80 | } | |
| 81 | Token::Return => { | |
| 82 | let expression = parse_expression(tokens)?; | |
| 83 | ||
| 84 | match tokens.next() { | |
| 85 | Some(Token::Semicolon) => (), | |
| 86 | _ => return Err(AstError::new("Expected semicolon after return statement").into()), | |
| 87 | }; | |
| 88 | ||
| 89 | Ok(Ast::Return { | |
| 90 | return_value: Box::new(expression), | |
| 91 | }) | |
| 92 | } | |
| 93 | Token::Function => { | |
| 94 | let name = match tokens.next() { | |
| 95 | Some(Token::Identifier(name)) => name.clone(), | |
| 96 | _ => return Err(AstError::new("Expected identifier after fn").into()), | |
| 97 | }; | |
| 98 | ||
| 99 | match tokens.next() { | |
| 100 | Some(Token::OpenParanthesis) => (), | |
| 101 | _ => { | |
| 102 | return Err(AstError::new( | |
| 103 | "Expected open paranthesis after identifier in function", | |
| 104 | ) | |
| 105 | .into()) | |
| 106 | } | |
| 107 | }; | |
| 108 | ||
| 109 | let mut arguments = Vec::new(); | |
| 110 | ||
| 111 | loop { | |
| 112 | match tokens.peek() { | |
| 113 | Some(Token::ClosedParanthesis) => { | |
| 114 | tokens.next(); | |
| 115 | break; | |
| 116 | } | |
| 117 | _ => (), | |
| 118 | } | |
| 119 | ||
| 120 | let argument_name = match tokens.next() { | |
| 121 | Some(Token::Identifier(name)) => name, | |
| 122 | _ => { | |
| 123 | return Err(AstError::new( | |
| 124 | "Expected identifier for argument name in function", | |
| 125 | ) | |
| 126 | .into()) | |
| 127 | } | |
| 128 | }; | |
| 129 | ||
| 130 | let return_type = match tokens.next() { | |
| 131 | Some(Token::Colon) => parse_type(tokens)?, | |
| 132 | _ => return Err(AstError::new("Expected colon after identifier").into()), | |
| 133 | }; | |
| 134 | ||
| 135 | match tokens.peek() { | |
| 136 | Some(Token::Comma) => { | |
| 137 | tokens.next(); | |
| 138 | } | |
| 139 | _ => (), | |
| 140 | } | |
| 141 | ||
| 142 | arguments.push(Argument { | |
| 143 | name: argument_name.clone(), | |
| 144 | return_type, | |
| 145 | }) | |
| 146 | } | |
| 147 | ||
| 148 | let return_type = match tokens.next() { | |
| 149 | Some(Token::RightArrow) => parse_type(tokens)?, | |
| 150 | _ => { | |
| 151 | return Err(AstError::new( | |
| 152 | "Expected right arrow after argument list in function", | |
| 153 | ) | |
| 154 | .into()) | |
| 155 | } | |
| 156 | }; | |
| 157 | ||
| 158 | match tokens.peek() { | |
| 159 | Some(Token::OpenBracket) => (), | |
| 160 | _ => { | |
| 161 | return Err(AstError::new( | |
| 162 | "Expected open bracket after type in function declaration", | |
| 163 | ) | |
| 164 | .into()) | |
| 165 | } | |
| 166 | }; | |
| 167 | ||
| 168 | let block = parse_block(tokens)?; | |
| 169 | ||
| 170 | return Ok(Ast::Function { | |
| 171 | name, | |
| 172 | arguments, | |
| 173 | return_type, | |
| 174 | block, | |
| 175 | }); | |
| 176 | } | |
| 177 | Token::If => { | |
| 178 | let condition = parse_expression(tokens)?; | |
| 179 | ||
| 180 | let value = parse_block(tokens)?; | |
| 181 | ||
| 182 | let mut else_value = None; | |
| 183 | ||
| 184 | match tokens.peek() { | |
| 185 | Some(Token::Else) => { | |
| 186 | tokens.next(); | |
| 187 | match tokens.peek() { | |
| 188 | Option::Some(Token::If) => { | |
| 189 | else_value = Some(Box::new(parse_expression(tokens)?)); | |
| 190 | } | |
| 191 | Option::Some(Token::OpenBracket) => { | |
| 192 | else_value = Some(Box::new(Ast::Block(parse_block(tokens)?))); | |
| 193 | } | |
| 194 | _ => { | |
| 195 | return Err(AstError::new( | |
| 196 | "Expected if or open bracket after else in if statement", | |
| 197 | ) | |
| 198 | .into()) | |
| 199 | } | |
| 200 | } | |
| 201 | } | |
| 202 | _ => (), | |
| 203 | } | |
| 204 | ||
| 205 | return Ok(Ast::If { | |
| 206 | condition: Box::new(condition), | |
| 207 | value, | |
| 208 | else_value, | |
| 209 | }); | |
| 210 | } | |
| 211 | Token::Identifier(name) => match tokens.peek() { | |
| 212 | Some(Token::OpenParanthesis) => { | |
| 213 | tokens.next(); | |
| 214 | ||
| 215 | let mut arguments = Vec::new(); | |
| 216 | ||
| 217 | loop { | |
| 218 | match tokens.peek() { | |
| 219 | Some(Token::ClosedParanthesis) => { | |
| 220 | tokens.next(); | |
| 221 | break; | |
| 222 | } | |
| 223 | _ => (), | |
| 224 | } | |
| 225 | arguments.push(parse_expression(tokens)?); | |
| 226 | ||
| 227 | match tokens.peek() { | |
| 228 | Some(Token::Comma) => { | |
| 229 | tokens.next(); | |
| 230 | } | |
| 231 | Some(Token::ClosedParanthesis) => (), | |
| 232 | _ => { | |
| 233 | return Err(AstError::new( | |
| 234 | "Expected ) or , but found something else instead.", | |
| 235 | ) | |
| 236 | .into()) | |
| 237 | } | |
| 238 | } | |
| 239 | } | |
| 240 | ||
| 241 | match tokens.next() { | |
| 242 | Some(Token::Semicolon) => (), | |
| 243 | _ => return Err(AstError::new("Expected semicolon after function call").into()), | |
| 244 | }; | |
| 245 | ||
| 246 | Ok(Ast::FunctionCall { | |
| 247 | name: name.clone(), | |
| 248 | arguments, | |
| 249 | }) | |
| 250 | } | |
| 251 | _ => Err(AstError::new("Unexpected identifier").into()), | |
| 252 | }, | |
| 253 | Token::Comment(comment) => Ok(Ast::Comment(comment.clone())), | |
| 254 | Token::DocComment(comment) => { | |
| 255 | let mut concatted_comments = comment.clone(); | |
| 256 | loop { | |
| 257 | match tokens.peek() { | |
| 258 | Some(Token::DocComment(comment)) => { | |
| 259 | concatted_comments.push_str(format!("\n{}", comment).as_str()); | |
| 260 | tokens.next(); | |
| 261 | } | |
| 262 | _ => break, | |
| 263 | } | |
| 264 | } | |
| 265 | Ok(Ast::DocComment(concatted_comments)) | |
| 266 | } | |
| 267 | _ => return Err(AstError::new("Unexpected token").into()), | |
| 268 | } | |
| 269 | } |
crates/ast/src/parse_type.rs created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use tokenizer::Token; | |
| 4 | ||
| 5 | use super::error::AstError; | |
| 6 | use super::types::{ParserContext, Type}; | |
| 7 | ||
| 8 | pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> { | |
| 9 | match tokens.next() { | |
| 10 | Some(Token::Identifier(typ)) => match typ.as_str() { | |
| 11 | "int" => Ok(Type::Int), | |
| 12 | "float" => Ok(Type::Float), | |
| 13 | "bigint" => Ok(Type::Bigint), | |
| 14 | "bool" => Ok(Type::Bool), | |
| 15 | "string" => Ok(Type::String), | |
| 16 | _ => return Err(AstError::new("Expected type").into()), | |
| 17 | }, | |
| 18 | _ => return Err(AstError::new("Expected type").into()), | |
| 19 | } | |
| 20 | } |
crates/ast/src/types.rs created+110| ... | ... | @@ -0,0 +1,110 @@ |
| 1 | // TODO(lino-levan): Split up AST into expressions, statements, etc. | |
| 2 | ||
| 3 | use tokenizer::Token; | |
| 4 | use util::Operator; | |
| 5 | ||
| 6 | #[derive(Debug)] | |
| 7 | pub struct ParserContext { | |
| 8 | pub tokens: Vec<Token>, | |
| 9 | pub cursor: usize, | |
| 10 | } | |
| 11 | ||
| 12 | impl ParserContext { | |
| 13 | pub fn new(tokens: Vec<Token>) -> ParserContext { | |
| 14 | ParserContext { tokens, cursor: 0 } | |
| 15 | } | |
| 16 | ||
| 17 | pub fn empty(&self) -> bool { | |
| 18 | self.cursor == self.tokens.len() | |
| 19 | } | |
| 20 | ||
| 21 | pub fn back(&mut self) { | |
| 22 | self.cursor -= 1; | |
| 23 | } | |
| 24 | ||
| 25 | pub fn next(&mut self) -> Option<Token> { | |
| 26 | if self.cursor == self.tokens.len() { | |
| 27 | return None; | |
| 28 | } | |
| 29 | ||
| 30 | let token = self.tokens[self.cursor].clone(); | |
| 31 | self.cursor += 1; | |
| 32 | Some(token) | |
| 33 | } | |
| 34 | ||
| 35 | pub fn peek(&self) -> Option<Token> { | |
| 36 | if self.cursor == self.tokens.len() { | |
| 37 | return None; | |
| 38 | } | |
| 39 | ||
| 40 | Some(self.tokens[self.cursor].clone()) | |
| 41 | } | |
| 42 | } | |
| 43 | ||
| 44 | #[derive(Debug)] | |
| 45 | pub enum Type { | |
| 46 | Int, | |
| 47 | Float, | |
| 48 | Bigint, | |
| 49 | Bool, | |
| 50 | String, | |
| 51 | } | |
| 52 | ||
| 53 | #[derive(Debug)] | |
| 54 | pub struct Block { | |
| 55 | pub value: Vec<Ast>, | |
| 56 | pub implicit_return: bool, | |
| 57 | } | |
| 58 | ||
| 59 | #[derive(Debug)] | |
| 60 | pub struct Argument { | |
| 61 | pub name: String, | |
| 62 | pub return_type: Type, | |
| 63 | } | |
| 64 | ||
| 65 | #[derive(Debug)] | |
| 66 | pub enum Ast { | |
| 67 | Public { | |
| 68 | value: Box<Ast>, | |
| 69 | }, | |
| 70 | ConstantDeclaration { | |
| 71 | name: String, | |
| 72 | return_type: Type, | |
| 73 | value: Box<Ast>, | |
| 74 | }, | |
| 75 | VariableDeclaration { | |
| 76 | name: String, | |
| 77 | return_type: Type, | |
| 78 | value: Box<Ast>, | |
| 79 | }, | |
| 80 | Operation { | |
| 81 | operator: Operator, | |
| 82 | left: Box<Ast>, | |
| 83 | right: Box<Ast>, | |
| 84 | }, | |
| 85 | Return { | |
| 86 | return_value: Box<Ast>, | |
| 87 | }, | |
| 88 | Function { | |
| 89 | name: String, | |
| 90 | arguments: Vec<Argument>, | |
| 91 | return_type: Type, | |
| 92 | block: Block, | |
| 93 | }, | |
| 94 | FunctionCall { | |
| 95 | name: String, | |
| 96 | arguments: Vec<Ast>, | |
| 97 | }, | |
| 98 | If { | |
| 99 | condition: Box<Ast>, | |
| 100 | value: Block, | |
| 101 | else_value: Option<Box<Ast>>, | |
| 102 | }, | |
| 103 | Block(Block), | |
| 104 | Number(String), | |
| 105 | Bool(bool), | |
| 106 | String(String), | |
| 107 | Identifier(String), | |
| 108 | Comment(String), | |
| 109 | DocComment(String), | |
| 110 | } |
crates/cli/Cargo.lock created+532| ... | ... | @@ -0,0 +1,532 @@ |
| 1 | # This file is automatically @generated by Cargo. | |
| 2 | # It is not intended for manual editing. | |
| 3 | version = 3 | |
| 4 | ||
| 5 | [[package]] | |
| 6 | name = "addr2line" | |
| 7 | version = "0.21.0" | |
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" | |
| 10 | dependencies = [ | |
| 11 | "gimli", | |
| 12 | ] | |
| 13 | ||
| 14 | [[package]] | |
| 15 | name = "adler" | |
| 16 | version = "1.0.2" | |
| 17 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | |
| 19 | ||
| 20 | [[package]] | |
| 21 | name = "anstream" | |
| 22 | version = "0.6.5" | |
| 23 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 24 | checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" | |
| 25 | dependencies = [ | |
| 26 | "anstyle", | |
| 27 | "anstyle-parse", | |
| 28 | "anstyle-query", | |
| 29 | "anstyle-wincon", | |
| 30 | "colorchoice", | |
| 31 | "utf8parse", | |
| 32 | ] | |
| 33 | ||
| 34 | [[package]] | |
| 35 | name = "anstyle" | |
| 36 | version = "1.0.4" | |
| 37 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 38 | checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" | |
| 39 | ||
| 40 | [[package]] | |
| 41 | name = "anstyle-parse" | |
| 42 | version = "0.2.3" | |
| 43 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 44 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" | |
| 45 | dependencies = [ | |
| 46 | "utf8parse", | |
| 47 | ] | |
| 48 | ||
| 49 | [[package]] | |
| 50 | name = "anstyle-query" | |
| 51 | version = "1.0.2" | |
| 52 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 53 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" | |
| 54 | dependencies = [ | |
| 55 | "windows-sys", | |
| 56 | ] | |
| 57 | ||
| 58 | [[package]] | |
| 59 | name = "anstyle-wincon" | |
| 60 | version = "3.0.2" | |
| 61 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 62 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" | |
| 63 | dependencies = [ | |
| 64 | "anstyle", | |
| 65 | "windows-sys", | |
| 66 | ] | |
| 67 | ||
| 68 | [[package]] | |
| 69 | name = "backtrace" | |
| 70 | version = "0.3.69" | |
| 71 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 72 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" | |
| 73 | dependencies = [ | |
| 74 | "addr2line", | |
| 75 | "cc", | |
| 76 | "cfg-if", | |
| 77 | "libc", | |
| 78 | "miniz_oxide", | |
| 79 | "object", | |
| 80 | "rustc-demangle", | |
| 81 | ] | |
| 82 | ||
| 83 | [[package]] | |
| 84 | name = "backtrace-ext" | |
| 85 | version = "0.2.1" | |
| 86 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 87 | checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" | |
| 88 | dependencies = [ | |
| 89 | "backtrace", | |
| 90 | ] | |
| 91 | ||
| 92 | [[package]] | |
| 93 | name = "bitflags" | |
| 94 | version = "2.4.1" | |
| 95 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 96 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" | |
| 97 | ||
| 98 | [[package]] | |
| 99 | name = "blight" | |
| 100 | version = "0.1.0" | |
| 101 | dependencies = [ | |
| 102 | "clap", | |
| 103 | "miette", | |
| 104 | "thiserror", | |
| 105 | ] | |
| 106 | ||
| 107 | [[package]] | |
| 108 | name = "cc" | |
| 109 | version = "1.0.83" | |
| 110 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 111 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" | |
| 112 | dependencies = [ | |
| 113 | "libc", | |
| 114 | ] | |
| 115 | ||
| 116 | [[package]] | |
| 117 | name = "cfg-if" | |
| 118 | version = "1.0.0" | |
| 119 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 120 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |
| 121 | ||
| 122 | [[package]] | |
| 123 | name = "clap" | |
| 124 | version = "4.4.12" | |
| 125 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 126 | checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" | |
| 127 | dependencies = [ | |
| 128 | "clap_builder", | |
| 129 | "clap_derive", | |
| 130 | ] | |
| 131 | ||
| 132 | [[package]] | |
| 133 | name = "clap_builder" | |
| 134 | version = "4.4.12" | |
| 135 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 136 | checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" | |
| 137 | dependencies = [ | |
| 138 | "anstream", | |
| 139 | "anstyle", | |
| 140 | "clap_lex", | |
| 141 | "strsim", | |
| 142 | ] | |
| 143 | ||
| 144 | [[package]] | |
| 145 | name = "clap_derive" | |
| 146 | version = "4.4.7" | |
| 147 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 148 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" | |
| 149 | dependencies = [ | |
| 150 | "heck", | |
| 151 | "proc-macro2", | |
| 152 | "quote", | |
| 153 | "syn", | |
| 154 | ] | |
| 155 | ||
| 156 | [[package]] | |
| 157 | name = "clap_lex" | |
| 158 | version = "0.6.0" | |
| 159 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 160 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" | |
| 161 | ||
| 162 | [[package]] | |
| 163 | name = "colorchoice" | |
| 164 | version = "1.0.0" | |
| 165 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 166 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" | |
| 167 | ||
| 168 | [[package]] | |
| 169 | name = "errno" | |
| 170 | version = "0.3.8" | |
| 171 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 172 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" | |
| 173 | dependencies = [ | |
| 174 | "libc", | |
| 175 | "windows-sys", | |
| 176 | ] | |
| 177 | ||
| 178 | [[package]] | |
| 179 | name = "gimli" | |
| 180 | version = "0.28.1" | |
| 181 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 182 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" | |
| 183 | ||
| 184 | [[package]] | |
| 185 | name = "heck" | |
| 186 | version = "0.4.1" | |
| 187 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 188 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" | |
| 189 | ||
| 190 | [[package]] | |
| 191 | name = "hermit-abi" | |
| 192 | version = "0.3.3" | |
| 193 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 194 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" | |
| 195 | ||
| 196 | [[package]] | |
| 197 | name = "is-terminal" | |
| 198 | version = "0.4.10" | |
| 199 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 200 | checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" | |
| 201 | dependencies = [ | |
| 202 | "hermit-abi", | |
| 203 | "rustix", | |
| 204 | "windows-sys", | |
| 205 | ] | |
| 206 | ||
| 207 | [[package]] | |
| 208 | name = "is_ci" | |
| 209 | version = "1.1.1" | |
| 210 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 211 | checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" | |
| 212 | ||
| 213 | [[package]] | |
| 214 | name = "libc" | |
| 215 | version = "0.2.151" | |
| 216 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 217 | checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" | |
| 218 | ||
| 219 | [[package]] | |
| 220 | name = "linux-raw-sys" | |
| 221 | version = "0.4.12" | |
| 222 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 223 | checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" | |
| 224 | ||
| 225 | [[package]] | |
| 226 | name = "memchr" | |
| 227 | version = "2.7.1" | |
| 228 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 229 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" | |
| 230 | ||
| 231 | [[package]] | |
| 232 | name = "miette" | |
| 233 | version = "5.10.0" | |
| 234 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 235 | checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" | |
| 236 | dependencies = [ | |
| 237 | "backtrace", | |
| 238 | "backtrace-ext", | |
| 239 | "is-terminal", | |
| 240 | "miette-derive", | |
| 241 | "once_cell", | |
| 242 | "owo-colors", | |
| 243 | "supports-color", | |
| 244 | "supports-hyperlinks", | |
| 245 | "supports-unicode", | |
| 246 | "terminal_size", | |
| 247 | "textwrap", | |
| 248 | "thiserror", | |
| 249 | "unicode-width", | |
| 250 | ] | |
| 251 | ||
| 252 | [[package]] | |
| 253 | name = "miette-derive" | |
| 254 | version = "5.10.0" | |
| 255 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 256 | checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" | |
| 257 | dependencies = [ | |
| 258 | "proc-macro2", | |
| 259 | "quote", | |
| 260 | "syn", | |
| 261 | ] | |
| 262 | ||
| 263 | [[package]] | |
| 264 | name = "miniz_oxide" | |
| 265 | version = "0.7.1" | |
| 266 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 267 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" | |
| 268 | dependencies = [ | |
| 269 | "adler", | |
| 270 | ] | |
| 271 | ||
| 272 | [[package]] | |
| 273 | name = "object" | |
| 274 | version = "0.32.2" | |
| 275 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 276 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" | |
| 277 | dependencies = [ | |
| 278 | "memchr", | |
| 279 | ] | |
| 280 | ||
| 281 | [[package]] | |
| 282 | name = "once_cell" | |
| 283 | version = "1.19.0" | |
| 284 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 285 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" | |
| 286 | ||
| 287 | [[package]] | |
| 288 | name = "owo-colors" | |
| 289 | version = "3.5.0" | |
| 290 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 291 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" | |
| 292 | ||
| 293 | [[package]] | |
| 294 | name = "proc-macro2" | |
| 295 | version = "1.0.73" | |
| 296 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 297 | checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1" | |
| 298 | dependencies = [ | |
| 299 | "unicode-ident", | |
| 300 | ] | |
| 301 | ||
| 302 | [[package]] | |
| 303 | name = "quote" | |
| 304 | version = "1.0.34" | |
| 305 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 306 | checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a" | |
| 307 | dependencies = [ | |
| 308 | "proc-macro2", | |
| 309 | ] | |
| 310 | ||
| 311 | [[package]] | |
| 312 | name = "rustc-demangle" | |
| 313 | version = "0.1.23" | |
| 314 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 315 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" | |
| 316 | ||
| 317 | [[package]] | |
| 318 | name = "rustix" | |
| 319 | version = "0.38.28" | |
| 320 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 321 | checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" | |
| 322 | dependencies = [ | |
| 323 | "bitflags", | |
| 324 | "errno", | |
| 325 | "libc", | |
| 326 | "linux-raw-sys", | |
| 327 | "windows-sys", | |
| 328 | ] | |
| 329 | ||
| 330 | [[package]] | |
| 331 | name = "smawk" | |
| 332 | version = "0.3.2" | |
| 333 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 334 | checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" | |
| 335 | ||
| 336 | [[package]] | |
| 337 | name = "strsim" | |
| 338 | version = "0.10.0" | |
| 339 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 340 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | |
| 341 | ||
| 342 | [[package]] | |
| 343 | name = "supports-color" | |
| 344 | version = "2.1.0" | |
| 345 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 346 | checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" | |
| 347 | dependencies = [ | |
| 348 | "is-terminal", | |
| 349 | "is_ci", | |
| 350 | ] | |
| 351 | ||
| 352 | [[package]] | |
| 353 | name = "supports-hyperlinks" | |
| 354 | version = "2.1.0" | |
| 355 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 356 | checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" | |
| 357 | dependencies = [ | |
| 358 | "is-terminal", | |
| 359 | ] | |
| 360 | ||
| 361 | [[package]] | |
| 362 | name = "supports-unicode" | |
| 363 | version = "2.0.0" | |
| 364 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 365 | checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" | |
| 366 | dependencies = [ | |
| 367 | "is-terminal", | |
| 368 | ] | |
| 369 | ||
| 370 | [[package]] | |
| 371 | name = "syn" | |
| 372 | version = "2.0.44" | |
| 373 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 374 | checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d" | |
| 375 | dependencies = [ | |
| 376 | "proc-macro2", | |
| 377 | "quote", | |
| 378 | "unicode-ident", | |
| 379 | ] | |
| 380 | ||
| 381 | [[package]] | |
| 382 | name = "terminal_size" | |
| 383 | version = "0.1.17" | |
| 384 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 385 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" | |
| 386 | dependencies = [ | |
| 387 | "libc", | |
| 388 | "winapi", | |
| 389 | ] | |
| 390 | ||
| 391 | [[package]] | |
| 392 | name = "textwrap" | |
| 393 | version = "0.15.2" | |
| 394 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 395 | checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" | |
| 396 | dependencies = [ | |
| 397 | "smawk", | |
| 398 | "unicode-linebreak", | |
| 399 | "unicode-width", | |
| 400 | ] | |
| 401 | ||
| 402 | [[package]] | |
| 403 | name = "thiserror" | |
| 404 | version = "1.0.53" | |
| 405 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 406 | checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" | |
| 407 | dependencies = [ | |
| 408 | "thiserror-impl", | |
| 409 | ] | |
| 410 | ||
| 411 | [[package]] | |
| 412 | name = "thiserror-impl" | |
| 413 | version = "1.0.53" | |
| 414 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 415 | checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" | |
| 416 | dependencies = [ | |
| 417 | "proc-macro2", | |
| 418 | "quote", | |
| 419 | "syn", | |
| 420 | ] | |
| 421 | ||
| 422 | [[package]] | |
| 423 | name = "unicode-ident" | |
| 424 | version = "1.0.12" | |
| 425 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 426 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" | |
| 427 | ||
| 428 | [[package]] | |
| 429 | name = "unicode-linebreak" | |
| 430 | version = "0.1.5" | |
| 431 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 432 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" | |
| 433 | ||
| 434 | [[package]] | |
| 435 | name = "unicode-width" | |
| 436 | version = "0.1.11" | |
| 437 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 438 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" | |
| 439 | ||
| 440 | [[package]] | |
| 441 | name = "utf8parse" | |
| 442 | version = "0.2.1" | |
| 443 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 444 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | |
| 445 | ||
| 446 | [[package]] | |
| 447 | name = "winapi" | |
| 448 | version = "0.3.9" | |
| 449 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 450 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | |
| 451 | dependencies = [ | |
| 452 | "winapi-i686-pc-windows-gnu", | |
| 453 | "winapi-x86_64-pc-windows-gnu", | |
| 454 | ] | |
| 455 | ||
| 456 | [[package]] | |
| 457 | name = "winapi-i686-pc-windows-gnu" | |
| 458 | version = "0.4.0" | |
| 459 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 460 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | |
| 461 | ||
| 462 | [[package]] | |
| 463 | name = "winapi-x86_64-pc-windows-gnu" | |
| 464 | version = "0.4.0" | |
| 465 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 466 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | |
| 467 | ||
| 468 | [[package]] | |
| 469 | name = "windows-sys" | |
| 470 | version = "0.52.0" | |
| 471 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 472 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | |
| 473 | dependencies = [ | |
| 474 | "windows-targets", | |
| 475 | ] | |
| 476 | ||
| 477 | [[package]] | |
| 478 | name = "windows-targets" | |
| 479 | version = "0.52.0" | |
| 480 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 481 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" | |
| 482 | dependencies = [ | |
| 483 | "windows_aarch64_gnullvm", | |
| 484 | "windows_aarch64_msvc", | |
| 485 | "windows_i686_gnu", | |
| 486 | "windows_i686_msvc", | |
| 487 | "windows_x86_64_gnu", | |
| 488 | "windows_x86_64_gnullvm", | |
| 489 | "windows_x86_64_msvc", | |
| 490 | ] | |
| 491 | ||
| 492 | [[package]] | |
| 493 | name = "windows_aarch64_gnullvm" | |
| 494 | version = "0.52.0" | |
| 495 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 496 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" | |
| 497 | ||
| 498 | [[package]] | |
| 499 | name = "windows_aarch64_msvc" | |
| 500 | version = "0.52.0" | |
| 501 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 502 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" | |
| 503 | ||
| 504 | [[package]] | |
| 505 | name = "windows_i686_gnu" | |
| 506 | version = "0.52.0" | |
| 507 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 508 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" | |
| 509 | ||
| 510 | [[package]] | |
| 511 | name = "windows_i686_msvc" | |
| 512 | version = "0.52.0" | |
| 513 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 514 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" | |
| 515 | ||
| 516 | [[package]] | |
| 517 | name = "windows_x86_64_gnu" | |
| 518 | version = "0.52.0" | |
| 519 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 520 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" | |
| 521 | ||
| 522 | [[package]] | |
| 523 | name = "windows_x86_64_gnullvm" | |
| 524 | version = "0.52.0" | |
| 525 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 526 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" | |
| 527 | ||
| 528 | [[package]] | |
| 529 | name = "windows_x86_64_msvc" | |
| 530 | version = "0.52.0" | |
| 531 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 532 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" |
crates/cli/Cargo.toml created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | [package] | |
| 2 | name = "cli" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [[bin]] | |
| 7 | name = "blight" | |
| 8 | path = "./src/main.rs" | |
| 9 | ||
| 10 | [dependencies] | |
| 11 | clap.workspace = true | |
| 12 | miette.workspace = true | |
| 13 | thiserror.workspace = true | |
| 14 | ||
| 15 | tokenizer = { path = "../tokenizer" } | |
| 16 | ast = { path = "../ast" } | |
| 17 | js_printer = { path = "../js_printer" } |
crates/cli/src/main.rs created+120| ... | ... | @@ -0,0 +1,120 @@ |
| 1 | use std::path::PathBuf; | |
| 2 | ||
| 3 | use clap::{Parser, Subcommand}; | |
| 4 | use miette::Result; | |
| 5 | ||
| 6 | use tokenizer; | |
| 7 | use ast; | |
| 8 | use js_printer; | |
| 9 | ||
| 10 | #[derive(Parser)] | |
| 11 | #[command(author, version, about, long_about = None)] | |
| 12 | struct Cli { | |
| 13 | /// Turn debugging information on | |
| 14 | #[arg(short, long, action = clap::ArgAction::Count)] | |
| 15 | debug: u8, | |
| 16 | ||
| 17 | #[command(subcommand)] | |
| 18 | command: Commands, | |
| 19 | } | |
| 20 | ||
| 21 | #[derive(Subcommand)] | |
| 22 | enum Commands { | |
| 23 | /// Compiles a file into javascript | |
| 24 | Compile { | |
| 25 | file: PathBuf, | |
| 26 | // Whether to output to stdout instead of a file | |
| 27 | #[arg(long, default_value_t = false)] | |
| 28 | stdout: bool, | |
| 29 | }, | |
| 30 | Run { | |
| 31 | file: PathBuf, | |
| 32 | /// What javascript runtime to use | |
| 33 | #[arg(short, long, default_value = "deno")] | |
| 34 | runtime: String, | |
| 35 | }, | |
| 36 | } | |
| 37 | ||
| 38 | fn get_runtime(runtime: &String) -> String { | |
| 39 | match std::env::var("USER") { | |
| 40 | Ok(user) if user == "dave" => String::from("bun"), | |
| 41 | _ => runtime.clone(), | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 45 | ||
| 46 | pub fn transpile(content: String) -> Result<String> { | |
| 47 | // 1. Tokenize the input | |
| 48 | let tokens = tokenizer::tokenize(content)?; | |
| 49 | // 2. Parse the tokens into an AST | |
| 50 | let blight_ast = ast::parse(tokens)?; | |
| 51 | // 3. Type check the AST | |
| 52 | // type_check(tree.clone())?; | |
| 53 | // 4. Optimize the AST | |
| 54 | // optimize(tree.clone())?; | |
| 55 | // 5. Translate the AST into javascript | |
| 56 | // translate(tree.clone())?; | |
| 57 | // 6. Print the JS AST | |
| 58 | let javascript = js_printer::transpile(blight_ast)?; | |
| 59 | // 7. Return the javascript | |
| 60 | return Ok(javascript); | |
| 61 | } | |
| 62 | ||
| 63 | ||
| 64 | fn main() -> Result<()> { | |
| 65 | let cli = Cli::parse(); | |
| 66 | ||
| 67 | match cli.command { | |
| 68 | Commands::Compile { file, stdout } => { | |
| 69 | let contents = std::fs::read_to_string(file.clone()).unwrap(); | |
| 70 | let result = transpile(contents.clone())?; | |
| 71 | ||
| 72 | if stdout { | |
| 73 | println!("{}", result); | |
| 74 | } else { | |
| 75 | std::fs::write(file.with_extension("js"), result).unwrap(); | |
| 76 | } | |
| 77 | } | |
| 78 | Commands::Run { file, runtime } => { | |
| 79 | let contents = std::fs::read_to_string(file.clone()).unwrap(); | |
| 80 | let result = transpile(contents.clone())?; | |
| 81 | let mut temp_file = std::env::temp_dir(); | |
| 82 | temp_file.push("temp.js"); | |
| 83 | std::fs::write(temp_file.clone(), result).unwrap(); | |
| 84 | ||
| 85 | let rt = get_runtime(&runtime); | |
| 86 | ||
| 87 | match rt.as_str() { | |
| 88 | "deno" => { | |
| 89 | let output = std::process::Command::new("deno") | |
| 90 | .arg("run") | |
| 91 | .arg("-A") | |
| 92 | .arg(temp_file) | |
| 93 | .output() | |
| 94 | .expect("Failed to execute process"); | |
| 95 | println!("{}", String::from_utf8_lossy(&output.stdout)); | |
| 96 | } | |
| 97 | "node" => { | |
| 98 | let output = std::process::Command::new("node") | |
| 99 | .arg(temp_file) | |
| 100 | .output() | |
| 101 | .expect("Failed to execute process"); | |
| 102 | println!("{}", String::from_utf8_lossy(&output.stdout)); | |
| 103 | } | |
| 104 | "bun" => { | |
| 105 | let output = std::process::Command::new("bun") | |
| 106 | .arg("run") | |
| 107 | .arg(temp_file) | |
| 108 | .output() | |
| 109 | .expect("Failed to execute process"); | |
| 110 | println!("{}", String::from_utf8_lossy(&output.stdout)); | |
| 111 | } | |
| 112 | _ => { | |
| 113 | println!("Unknown runtime: {}", runtime); | |
| 114 | } | |
| 115 | } | |
| 116 | } | |
| 117 | } | |
| 118 | ||
| 119 | Ok(()) | |
| 120 | } |
crates/js_ast/Cargo.toml created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | [package] | |
| 2 | name = "js_ast" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [lib] | |
| 7 | ||
| 8 | [dependencies] | |
| 9 | miette.workspace = true | |
| 10 | thiserror.workspace = true |
crates/js_ast/src/lib.rs createdcrates/js_printer/Cargo.toml created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | [package] | |
| 2 | name = "js_printer" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [lib] | |
| 7 | ||
| 8 | [dependencies] | |
| 9 | miette.workspace = true | |
| 10 | thiserror.workspace = true | |
| 11 | ||
| 12 | ast = { path = "../ast" } |
crates/js_printer/src/lib.rs created+139| ... | ... | @@ -0,0 +1,139 @@ |
| 1 | use miette::Result; | |
| 2 | ||
| 3 | use ast::{Ast, Type}; | |
| 4 | ||
| 5 | fn transpile_helper(tree: &Ast) -> Result<String> { | |
| 6 | Ok(match tree { | |
| 7 | Ast::Number(number) => format!("{}", number), | |
| 8 | Ast::Identifier(name) => format!("{}", name), | |
| 9 | Ast::Bool(value) => format!("{}", value), | |
| 10 | Ast::String(value) => format!("\"{}\"", value), | |
| 11 | Ast::Comment(comment) => format!("// {}\n", comment), | |
| 12 | Ast::DocComment(comment) => format!("/** {} */\n", comment), | |
| 13 | Ast::Operation { | |
| 14 | operator, | |
| 15 | left, | |
| 16 | right, | |
| 17 | } => format!( | |
| 18 | "{} {} {}", | |
| 19 | transpile_helper(left)?, | |
| 20 | operator.clone().to_string(), | |
| 21 | transpile_helper(right)? | |
| 22 | ), | |
| 23 | Ast::Public { value } => format!("export {}", transpile_helper(value)?), | |
| 24 | Ast::VariableDeclaration { | |
| 25 | name, | |
| 26 | return_type, | |
| 27 | value, | |
| 28 | } => match return_type { | |
| 29 | Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(value)?), | |
| 30 | _ => format!("let {} = {};\n", name, transpile_helper(value)?), | |
| 31 | }, | |
| 32 | Ast::ConstantDeclaration { | |
| 33 | name, | |
| 34 | return_type, | |
| 35 | value, | |
| 36 | } => match return_type { | |
| 37 | Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(value)?), | |
| 38 | _ => format!("const {} = {};\n", name, transpile_helper(value)?), | |
| 39 | }, | |
| 40 | Ast::Return { return_value } => format!("return {};\n", transpile_helper(return_value)?), | |
| 41 | Ast::Function { | |
| 42 | name, | |
| 43 | arguments, | |
| 44 | return_type: _, | |
| 45 | block, | |
| 46 | } => { | |
| 47 | let mut result = format!("function {}(", name); | |
| 48 | ||
| 49 | for (i, argument) in arguments.iter().enumerate() { | |
| 50 | if i == 0 { | |
| 51 | result += argument.name.as_str(); | |
| 52 | } else { | |
| 53 | result += format!(", {}", argument.name).as_str(); | |
| 54 | } | |
| 55 | } | |
| 56 | ||
| 57 | result += ") {\n"; | |
| 58 | ||
| 59 | for (i, statement) in block.value.iter().enumerate() { | |
| 60 | if block.implicit_return && i == block.value.len() - 1 { | |
| 61 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 62 | break; | |
| 63 | } | |
| 64 | result += transpile_helper(statement)?.as_str(); | |
| 65 | } | |
| 66 | ||
| 67 | result += "}\n"; | |
| 68 | ||
| 69 | result | |
| 70 | } | |
| 71 | Ast::If { | |
| 72 | condition, | |
| 73 | value, | |
| 74 | else_value, | |
| 75 | } => { | |
| 76 | let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,); | |
| 77 | ||
| 78 | for (i, statement) in value.value.iter().enumerate() { | |
| 79 | if value.implicit_return && i == value.value.len() - 1 { | |
| 80 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 81 | break; | |
| 82 | } | |
| 83 | result += transpile_helper(statement)?.as_str(); | |
| 84 | } | |
| 85 | ||
| 86 | result += "}"; | |
| 87 | ||
| 88 | if let Some(val) = else_value { | |
| 89 | result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str(); | |
| 90 | } else { | |
| 91 | result += "\n"; | |
| 92 | } | |
| 93 | ||
| 94 | result | |
| 95 | } | |
| 96 | Ast::FunctionCall { name, arguments } => { | |
| 97 | let mut result = match name.as_str() { | |
| 98 | "print" => String::from("console.log("), | |
| 99 | _ => format!("{}(", name), | |
| 100 | }; | |
| 101 | ||
| 102 | for (i, argument) in arguments.iter().enumerate() { | |
| 103 | if i == 0 { | |
| 104 | result += transpile_helper(argument)?.as_str(); | |
| 105 | } else { | |
| 106 | result += format!(", {}", transpile_helper(argument)?).as_str(); | |
| 107 | } | |
| 108 | } | |
| 109 | ||
| 110 | result += ")"; | |
| 111 | ||
| 112 | result | |
| 113 | } | |
| 114 | Ast::Block(block) => { | |
| 115 | let mut result = String::from("(()=>{\n"); | |
| 116 | for (i, statement) in block.value.iter().enumerate() { | |
| 117 | if block.implicit_return && i == block.value.len() - 1 { | |
| 118 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 119 | break; | |
| 120 | } | |
| 121 | result += transpile_helper(statement)?.as_str(); | |
| 122 | } | |
| 123 | ||
| 124 | result += "})()\n"; | |
| 125 | ||
| 126 | result | |
| 127 | } | |
| 128 | }) | |
| 129 | } | |
| 130 | ||
| 131 | pub fn transpile(forest: Vec<Ast>) -> Result<String> { | |
| 132 | let mut result = String::new(); | |
| 133 | ||
| 134 | for tree in forest { | |
| 135 | result.push_str(&transpile_helper(&tree)?); | |
| 136 | } | |
| 137 | ||
| 138 | Ok(result) | |
| 139 | } |
crates/tokenizer/Cargo.toml created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | [package] | |
| 2 | name = "tokenizer" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [lib] | |
| 7 | ||
| 8 | [dependencies] | |
| 9 | miette.workspace = true | |
| 10 | thiserror.workspace = true | |
| 11 | ||
| 12 | util = { path = "../util" } |
crates/tokenizer/src/lib.rs created+199| ... | ... | @@ -0,0 +1,199 @@ |
| 1 | use miette::{Diagnostic, Result}; | |
| 2 | use thiserror::Error; | |
| 3 | ||
| 4 | use util::Operator; | |
| 5 | ||
| 6 | #[derive(Error, Diagnostic, Debug)] | |
| 7 | #[error("UnknownCharacter")] | |
| 8 | struct UnknownCharacter { | |
| 9 | #[help] | |
| 10 | error: String, | |
| 11 | } | |
| 12 | ||
| 13 | #[derive(Debug, Clone)] | |
| 14 | pub enum Token { | |
| 15 | // Literals | |
| 16 | Identifier(String), | |
| 17 | Number(String), | |
| 18 | String(String), | |
| 19 | // Comments | |
| 20 | Comment(String), | |
| 21 | DocComment(String), | |
| 22 | // Keywords | |
| 23 | True, | |
| 24 | False, | |
| 25 | Let, | |
| 26 | Var, | |
| 27 | If, | |
| 28 | Else, | |
| 29 | Return, | |
| 30 | Pub, | |
| 31 | Function, | |
| 32 | RightArrow, | |
| 33 | Comma, | |
| 34 | OpenParanthesis, | |
| 35 | ClosedParanthesis, | |
| 36 | OpenBracket, | |
| 37 | ClosedBracket, | |
| 38 | Colon, | |
| 39 | Equals, | |
| 40 | Semicolon, | |
| 41 | // Operators | |
| 42 | Operator(Operator), | |
| 43 | } | |
| 44 | ||
| 45 | pub fn tokenize(content: String) -> Result<Vec<Token>> { | |
| 46 | let mut tokens: Vec<Token> = Vec::new(); | |
| 47 | let mut chars = content.chars().enumerate().peekable(); | |
| 48 | ||
| 49 | loop { | |
| 50 | match chars.next() { | |
| 51 | Some((_, c)) => match c { | |
| 52 | 'a'..='z' | 'A'..='Z' | '_' => { | |
| 53 | let mut current_token = String::new(); | |
| 54 | current_token.push(c); | |
| 55 | loop { | |
| 56 | let c = chars.peek(); | |
| 57 | if c.is_none() { | |
| 58 | break; | |
| 59 | } | |
| 60 | let (_, c) = c.unwrap(); | |
| 61 | match c { | |
| 62 | 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => { | |
| 63 | current_token.push(*c); | |
| 64 | chars.next(); | |
| 65 | } | |
| 66 | _ => break, | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | match current_token.as_str() { | |
| 71 | "var" => tokens.push(Token::Var), | |
| 72 | "let" => tokens.push(Token::Let), | |
| 73 | "if" => tokens.push(Token::If), | |
| 74 | "else" => tokens.push(Token::Else), | |
| 75 | "pub" => tokens.push(Token::Pub), | |
| 76 | "fn" => tokens.push(Token::Function), | |
| 77 | "return" => tokens.push(Token::Return), | |
| 78 | "true" => tokens.push(Token::True), | |
| 79 | "false" => tokens.push(Token::False), | |
| 80 | _ => tokens.push(Token::Identifier(current_token)), | |
| 81 | } | |
| 82 | } | |
| 83 | '"' => { | |
| 84 | let mut current_token = String::new(); | |
| 85 | loop { | |
| 86 | let c = chars.next(); | |
| 87 | if c.is_none() { | |
| 88 | break; | |
| 89 | } | |
| 90 | let (_, c) = c.unwrap(); | |
| 91 | match c { | |
| 92 | '"' => break, | |
| 93 | _ => current_token.push(c), | |
| 94 | } | |
| 95 | } | |
| 96 | tokens.push(Token::String(current_token)); | |
| 97 | } | |
| 98 | '0'..='9' => { | |
| 99 | let mut current_token = String::new(); | |
| 100 | current_token.push(c); | |
| 101 | loop { | |
| 102 | let c = chars.peek(); | |
| 103 | if c.is_none() { | |
| 104 | break; | |
| 105 | } | |
| 106 | let (_, c) = c.unwrap(); | |
| 107 | match c { | |
| 108 | '0'..='9' => { | |
| 109 | current_token.push(*c); | |
| 110 | chars.next(); | |
| 111 | } | |
| 112 | _ => break, | |
| 113 | } | |
| 114 | } | |
| 115 | tokens.push(Token::Number(current_token)); | |
| 116 | } | |
| 117 | ':' => tokens.push(Token::Colon), | |
| 118 | '=' => match chars.peek() { | |
| 119 | Some((_, '=')) => { | |
| 120 | chars.next(); | |
| 121 | tokens.push(Token::Operator(Operator::Equals)); | |
| 122 | } | |
| 123 | _ => tokens.push(Token::Equals), | |
| 124 | }, | |
| 125 | ';' => tokens.push(Token::Semicolon), | |
| 126 | '>' => tokens.push(Token::Operator(Operator::GreaterThan)), | |
| 127 | '+' => tokens.push(Token::Operator(Operator::Add)), | |
| 128 | '-' => match chars.peek() { | |
| 129 | Some((_, '>')) => { | |
| 130 | chars.next(); | |
| 131 | tokens.push(Token::RightArrow); | |
| 132 | } | |
| 133 | _ => tokens.push(Token::Operator(Operator::Substract)), | |
| 134 | }, | |
| 135 | '*' => match chars.peek() { | |
| 136 | Some((_, '*')) => { | |
| 137 | chars.next(); | |
| 138 | tokens.push(Token::Operator(Operator::Power)); | |
| 139 | } | |
| 140 | _ => tokens.push(Token::Operator(Operator::Multiply)), | |
| 141 | }, | |
| 142 | '/' => { | |
| 143 | match chars.peek() { | |
| 144 | Some((_, '/')) => { | |
| 145 | chars.next(); // Consume the second slash | |
| 146 | ||
| 147 | let is_doc_comment = match chars.peek() { | |
| 148 | Some((_, '/')) => { | |
| 149 | chars.next(); // Consume the third slash | |
| 150 | true | |
| 151 | } | |
| 152 | _ => false, | |
| 153 | }; | |
| 154 | ||
| 155 | let mut comment = String::new(); | |
| 156 | loop { | |
| 157 | let c = chars.next(); | |
| 158 | if c.is_none() { | |
| 159 | break; | |
| 160 | } | |
| 161 | let (_, c) = c.unwrap(); | |
| 162 | match c { | |
| 163 | '\n' => break, | |
| 164 | _ => { | |
| 165 | comment.push(c.clone()); | |
| 166 | } | |
| 167 | } | |
| 168 | } | |
| 169 | ||
| 170 | comment = comment.trim().to_string(); | |
| 171 | ||
| 172 | if is_doc_comment { | |
| 173 | tokens.push(Token::DocComment(comment)); | |
| 174 | } else { | |
| 175 | tokens.push(Token::Comment(comment)); | |
| 176 | } | |
| 177 | } | |
| 178 | _ => tokens.push(Token::Operator(Operator::Divide)), | |
| 179 | } | |
| 180 | } | |
| 181 | ',' => tokens.push(Token::Comma), | |
| 182 | '(' => tokens.push(Token::OpenParanthesis), | |
| 183 | ')' => tokens.push(Token::ClosedParanthesis), | |
| 184 | '{' => tokens.push(Token::OpenBracket), | |
| 185 | '}' => tokens.push(Token::ClosedBracket), | |
| 186 | s if s.is_whitespace() => (), | |
| 187 | _ => { | |
| 188 | return Err(UnknownCharacter { | |
| 189 | error: format!("Unsupported character: {}", c), | |
| 190 | } | |
| 191 | .into()) | |
| 192 | } | |
| 193 | }, | |
| 194 | None => break, | |
| 195 | } | |
| 196 | } | |
| 197 | ||
| 198 | Ok(tokens) | |
| 199 | } |
crates/util/Cargo.toml created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | [package] | |
| 2 | name = "util" | |
| 3 | version = "0.1.0" | |
| 4 | edition = "2021" | |
| 5 | ||
| 6 | [lib] | |
| 7 | ||
| 8 | [dependencies] |
crates/util/src/lib.rs created+24| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | #[derive(Debug, Clone)] | |
| 2 | pub enum Operator { | |
| 3 | Add, | |
| 4 | Substract, | |
| 5 | Multiply, | |
| 6 | Divide, | |
| 7 | Power, | |
| 8 | Equals, | |
| 9 | GreaterThan, | |
| 10 | } | |
| 11 | ||
| 12 | impl Operator { | |
| 13 | pub fn to_string(self) -> String { | |
| 14 | String::from(match self { | |
| 15 | Self::Add => "+", | |
| 16 | Self::Substract => "-", | |
| 17 | Self::Divide => "/", | |
| 18 | Self::Multiply => "*", | |
| 19 | Self::Power => "**", | |
| 20 | Self::Equals => "===", | |
| 21 | Self::GreaterThan => ">", | |
| 22 | }) | |
| 23 | } | |
| 24 | } |