From bb0c2dfa562bc10f43061a5d71490523b9fa6fbe Mon Sep 17 00:00:00 2001
From: Louis Capitanchik <contact@louiscap.co>
Date: Sat, 27 May 2023 18:17:21 +0100
Subject: [PATCH] Add lalrpop parser

---
 .gitignore                                    |   6 +-
 Cargo.lock                                    | 580 ++++++++++++++++++
 forge-script-lang/Cargo.toml                  |   8 +-
 forge-script-lang/src/build.rs                |   5 +
 .../src/parser/forge_script.lalrpop           | 102 +++
 forge-script-lang/src/parser/lr_grammar.rs    |  45 ++
 forge-script-lang/src/parser/mod.rs           |   3 +
 7 files changed, 747 insertions(+), 2 deletions(-)
 create mode 100644 forge-script-lang/src/build.rs
 create mode 100644 forge-script-lang/src/parser/forge_script.lalrpop
 create mode 100644 forge-script-lang/src/parser/lr_grammar.rs

diff --git a/.gitignore b/.gitignore
index 47279c6..ff2439c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -126,4 +126,8 @@ target/
 # MSVC Windows builds of rustc generate these, which store debugging information
 *.pdb
 
-# End of https://www.toptal.com/developers/gitignore/api/intellij,rust
\ No newline at end of file
+# End of https://www.toptal.com/developers/gitignore/api/intellij,rust
+
+# Generated Parser
+
+forge-script-lang/src/parser/forge_script.rs
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 0f0b70e..c4fd76f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,42 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "ascii-canvas"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
+dependencies = [
+ "term",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
 [[package]]
 name = "bumpalo"
 version = "3.12.2"
@@ -14,6 +50,12 @@ version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
 
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -30,6 +72,81 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
+name = "dirs-next"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "ena"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
+dependencies = [
+ "log",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
 [[package]]
 name = "forge-script"
 version = "0.1.0"
@@ -41,6 +158,8 @@ dependencies = [
 name = "forge-script-lang"
 version = "0.1.0"
 dependencies = [
+ "lalrpop",
+ "lalrpop-util",
  "nom",
  "nom_locate",
  "peg",
@@ -58,6 +177,71 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+dependencies = [
+ "hermit-abi",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "js-sys"
 version = "0.3.62"
@@ -67,6 +251,56 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "lalrpop"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8"
+dependencies = [
+ "ascii-canvas",
+ "bit-set",
+ "diff",
+ "ena",
+ "is-terminal",
+ "itertools",
+ "lalrpop-util",
+ "petgraph",
+ "regex",
+ "regex-syntax",
+ "string_cache",
+ "term",
+ "tiny-keccak",
+ "unicode-xid",
+]
+
+[[package]]
+name = "lalrpop-util"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
+
+[[package]]
+name = "libc"
+version = "0.2.144"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
 [[package]]
 name = "log"
 version = "0.4.17"
@@ -88,6 +322,12 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+
 [[package]]
 name = "nom"
 version = "7.1.3"
@@ -115,6 +355,29 @@ version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys 0.45.0",
+]
+
 [[package]]
 name = "peg"
 version = "0.8.1"
@@ -142,6 +405,31 @@ version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739"
 
+[[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+
 [[package]]
 name = "proc-macro-error"
 version = "1.0.4"
@@ -184,6 +472,67 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
+dependencies = [
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+
+[[package]]
+name = "rustix"
+version = "0.37.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
 [[package]]
 name = "serde"
 version = "1.0.163"
@@ -215,6 +564,31 @@ dependencies = [
  "syn 2.0.15",
 ]
 
+[[package]]
+name = "siphasher"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "string_cache"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
+dependencies = [
+ "new_debug_unreachable",
+ "once_cell",
+ "parking_lot",
+ "phf_shared",
+ "precomputed-hash",
+]
+
 [[package]]
 name = "syn"
 version = "1.0.109"
@@ -237,6 +611,17 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "term"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
+dependencies = [
+ "dirs-next",
+ "rustversion",
+ "winapi",
+]
+
 [[package]]
 name = "test-case"
 version = "3.1.0"
@@ -272,18 +657,59 @@ dependencies = [
  "test-case-core",
 ]
 
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
 [[package]]
 name = "version_check"
 version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
 [[package]]
 name = "wasm-bindgen"
 version = "0.2.85"
@@ -337,3 +763,157 @@ name = "wasm-bindgen-shared"
 version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/forge-script-lang/Cargo.toml b/forge-script-lang/Cargo.toml
index ecf2488..2c17930 100644
--- a/forge-script-lang/Cargo.toml
+++ b/forge-script-lang/Cargo.toml
@@ -9,6 +9,8 @@ authors = [
 ]
 repository = "https://lab.lcr.gr/microhacks/forge-script.git"
 
+build = "src/build.rs"
+
 [features]
 default = []
 debug-ast = []
@@ -20,6 +22,10 @@ nom.workspace = true
 nom_locate.workspace = true
 peg.workspace = true
 serde = { version = "1.0", optional = true, features = ["derive"] }
+lalrpop-util = "0.20.0"
 
 [dev-dependencies]
-test-case = "3.1.0"
\ No newline at end of file
+test-case = "3.1.0"
+
+[build-dependencies]
+lalrpop = { version = "0.20.0", default-features = false }
\ No newline at end of file
diff --git a/forge-script-lang/src/build.rs b/forge-script-lang/src/build.rs
new file mode 100644
index 0000000..3094868
--- /dev/null
+++ b/forge-script-lang/src/build.rs
@@ -0,0 +1,5 @@
+pub fn main() {
+	lalrpop::Configuration::new()
+		.process_file("src/parser/forge_script.lalrpop")
+		.expect("Failed to parse language grammar");
+}
diff --git a/forge-script-lang/src/parser/forge_script.lalrpop b/forge-script-lang/src/parser/forge_script.lalrpop
new file mode 100644
index 0000000..06cb127
--- /dev/null
+++ b/forge-script-lang/src/parser/forge_script.lalrpop
@@ -0,0 +1,102 @@
+use crate::lexer::ScriptTokenType;
+use crate::parser::ast::*;
+use crate::runtime::numbers::Number;
+
+grammar<'a>;
+
+pub Expression: Expression = {
+    ValueExpression => Expression::Value(<>),
+}
+
+ValueExpression: ValueExpression = {
+    #[precedence(level="1")]
+    Literal => ValueExpression::Literal(<>),
+    #[precedence(level="1")]
+    "typeof" <expr:ValueExpression> => TypeofValue(Box::new(expr)).into(),
+
+    #[precedence(level="4")] #[assoc(side="left")]
+    <lhs:ValueExpression> "+" <rhs:ValueExpression> => {
+        ValueExpression::Binary {
+            lhs: Box::new(lhs),
+            rhs: Box::new(rhs),
+            operator: BinaryOp::Add,
+        }
+    },
+    #[precedence(level="4")] #[assoc(side="left")]
+    <lhs:ValueExpression> "-" <rhs:ValueExpression> => {
+        ValueExpression::Binary {
+            lhs: Box::new(lhs),
+            rhs: Box::new(rhs),
+            operator: BinaryOp::Subtract,
+        }
+    },
+}
+
+Literal: LiteralNode = {
+    "boolean" => LiteralNode::Boolean(<>),
+    "null" => LiteralNode::Null,
+    "float" => LiteralNode::Number(Number::Float(<>)),
+    "integer" => LiteralNode::Number(Number::Integer(<>)),
+    "string" => LiteralNode::String(String::from(<>)),
+    "owned_string" => LiteralNode::String(<>),
+}
+
+StringValue: String = {
+    "string" => String::from(<>),
+    "owned_string" => <>,
+}
+
+extern {
+    type Location = usize;
+    type Error = crate::TokenError<'a>;
+
+    enum ScriptTokenType<'a> {
+        "(" => ScriptTokenType::LeftParen,
+        ")" => ScriptTokenType::RightParen,
+        "{" => ScriptTokenType::LeftBrace,
+        "}" => ScriptTokenType::RightBrace,
+        "," => ScriptTokenType::Comma,
+        "." => ScriptTokenType::Dot,
+        "-" => ScriptTokenType::Minus,
+        "+" => ScriptTokenType::Plus,
+        ";" => ScriptTokenType::Semicolon,
+        "/" => ScriptTokenType::Slash,
+        "*" => ScriptTokenType::Asterisk,
+        "!" => ScriptTokenType::Bang,
+        "!=" => ScriptTokenType::BangEqual,
+        "=" => ScriptTokenType::Equal,
+        "==" => ScriptTokenType::EqualEqual,
+        ">" => ScriptTokenType::Greater,
+        ">=" => ScriptTokenType::GreaterEqual,
+        "<" => ScriptTokenType::Less,
+        "<=" => ScriptTokenType::LessEqual,
+        "||" => ScriptTokenType::DoublePipe,
+        "&&" => ScriptTokenType::DoubleAmpersand,
+        "%" => ScriptTokenType::Modulo,
+        "^" => ScriptTokenType::Caret,
+        "struct" => ScriptTokenType::Class,
+        "else" => ScriptTokenType::Else,
+        "fn" => ScriptTokenType::Function,
+        "for" => ScriptTokenType::For,
+        "if" => ScriptTokenType::If,
+        "null" => ScriptTokenType::Null,
+        "print" => ScriptTokenType::Print,
+        "return" => ScriptTokenType::Return,
+        "super" => ScriptTokenType::Super,
+        "this" => ScriptTokenType::This,
+        "let" => ScriptTokenType::Let,
+        "while" => ScriptTokenType::While,
+        "export" => ScriptTokenType::Export,
+        "import" => ScriptTokenType::Import,
+        "as" => ScriptTokenType::Alias,
+        "from" => ScriptTokenType::From,
+        "typeof" => ScriptTokenType::Typeof,
+        "finally" => ScriptTokenType::Finally,
+        "boolean" => ScriptTokenType::Boolean(<bool>),
+        "float" => ScriptTokenType::Float(<f64>),
+        "integer" => ScriptTokenType::Integer(<i64>),
+        "owned_string" => ScriptTokenType::OwnedString(<String>),
+        "string" => ScriptTokenType::String(<&'a str>),
+        "identifier" => ScriptTokenType::Identifier(<&'a str>),
+    }
+}
\ No newline at end of file
diff --git a/forge-script-lang/src/parser/lr_grammar.rs b/forge-script-lang/src/parser/lr_grammar.rs
new file mode 100644
index 0000000..c7d0e39
--- /dev/null
+++ b/forge-script-lang/src/parser/lr_grammar.rs
@@ -0,0 +1,45 @@
+// use lalrpop_util::lalrpop_mod;
+// lalrpop_mod!(pub forge_script);
+
+use crate::lexer::{ScriptToken, ScriptTokenType};
+use crate::TokenError;
+use peg::Parse;
+use std::slice::Iter;
+
+pub struct TokenInput<'a>(std::slice::Iter<'a, ScriptToken<'a>>);
+
+impl<'a> From<Iter<'a, ScriptToken<'a>>> for TokenInput<'a> {
+	fn from(value: Iter<'a, ScriptToken<'a>>) -> Self {
+		TokenInput(value)
+	}
+}
+
+pub type InputSpan<'a, Loc, Tok> = Result<(Loc, Tok, Loc), TokenError<'a>>;
+
+impl<'a> Iterator for TokenInput<'a> {
+	type Item = InputSpan<'a, usize, ScriptTokenType<'a>>;
+
+	fn next(&mut self) -> Option<Self::Item> {
+		self.0.next().map(|tok| {
+			Ok((
+				tok.position.start(),
+				tok.token_type.clone(),
+				tok.position.start() + tok.position.len(),
+			))
+		})
+	}
+}
+
+#[cfg(test)]
+mod grammar_test {
+	use crate::lexer::{script_to_tokens, ScriptTokenType};
+	use crate::parser::lr_grammar::{InputSpan, TokenInput};
+
+	#[test]
+	fn basic_parsing() {
+		let code = script_to_tokens("4 + 4").expect("Failed to parse");
+		crate::parser::forge_script::ExpressionParser::new()
+			.parse::<InputSpan<usize, ScriptTokenType>, TokenInput>(code.iter().into())
+			.expect("Failed to boop");
+	}
+}
diff --git a/forge-script-lang/src/parser/mod.rs b/forge-script-lang/src/parser/mod.rs
index acbf4a7..2745c9f 100644
--- a/forge-script-lang/src/parser/mod.rs
+++ b/forge-script-lang/src/parser/mod.rs
@@ -1,9 +1,12 @@
 pub mod ast;
 mod atoms;
 mod grammar;
+mod lr_grammar;
 #[cfg(test)]
 mod test_suite;
 
+mod forge_script;
+
 use crate::error::{ForgeError, ForgeErrorKind, ForgeResult};
 use crate::print_forge_error;
 pub use atoms::TokenSlice;
-- 
GitLab