✍️ Switch to a handwritten lexer and parser. #1

Open
acw wants to merge 33 commits from handwritten-lexer into master
7 changed files with 549 additions and 173 deletions
Showing only changes of commit 55df27de98 - Show all commits

458
Cargo.lock generated
View File

@@ -2,6 +2,36 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"getrandom 0.2.16",
"once_cell",
"version_check",
"zerocopy 0.7.35",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "ariadne"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36f5e3dca4e09a6f340a61a0e9c7b61e030c69fc27bf29d73218f7e5e3b7638f"
dependencies = [
"concolor",
"unicode-width",
"yansi",
]
[[package]]
name = "autocfg"
version = "1.5.0"
@@ -12,8 +42,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
name = "bang"
version = "0.1.0"
dependencies = [
"codespan",
"codespan-reporting",
"ariadne",
"internment",
"memmap2",
"proptest",
"proptest-derive",
"thiserror",
@@ -34,6 +65,12 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.4"
@@ -47,26 +84,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "codespan"
version = "0.12.0"
name = "concolor"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4b418d52c9206820a56fc1aa28db73d67e346ba8ba6aa90987e8d6becef7e4"
checksum = "0b946244a988c390a94667ae0e3958411fa40cc46ea496a929b263d883f5f9c3"
dependencies = [
"codespan-reporting",
"serde",
"bitflags 1.3.2",
"concolor-query",
"is-terminal",
]
[[package]]
name = "codespan-reporting"
version = "0.12.0"
name = "concolor-query"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
dependencies = [
"serde",
"termcolor",
"unicode-width",
"windows-sys 0.45.0",
]
[[package]]
name = "dashmap"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.14"
@@ -74,7 +129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.61.2",
]
[[package]]
@@ -89,6 +144,23 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi 0.11.1+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.3"
@@ -98,7 +170,53 @@ dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi",
"wasi 0.14.7+wasi-0.2.4",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "internment"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "636d4b0f6a39fd684effe2a73f5310df16a3fa7954c26d36833e98f44d1977a2"
dependencies = [
"ahash",
"dashmap",
"hashbrown 0.15.5",
"once_cell",
]
[[package]]
name = "is-terminal"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.59.0",
]
[[package]]
@@ -119,6 +237,25 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "lock_api"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "memmap2"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7"
dependencies = [
"libc",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -134,13 +271,26 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "parking_lot_core"
version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.52.6",
]
[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
"zerocopy 0.8.27",
]
[[package]]
@@ -160,7 +310,7 @@ checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce"
dependencies = [
"bit-set",
"bit-vec",
"bitflags",
"bitflags 2.9.4",
"lazy_static",
"num-traits",
"rand",
@@ -191,9 +341,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
@@ -230,7 +380,7 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom",
"getrandom 0.3.3",
]
[[package]]
@@ -242,6 +392,15 @@ dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
dependencies = [
"bitflags 2.9.4",
]
[[package]]
name = "regex-syntax"
version = "0.8.6"
@@ -254,18 +413,18 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
dependencies = [
"bitflags",
"bitflags 2.9.4",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
"windows-sys 0.61.2",
]
[[package]]
name = "rusty-fork"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
dependencies = [
"fnv",
"quick-error",
@@ -274,34 +433,16 @@ dependencies = [
]
[[package]]
name = "serde"
version = "1.0.227"
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80ece43fc6fbed4eb5392ab50c07334d3e577cbf40997ee896fe7af40bba4245"
dependencies = [
"serde_core",
"serde_derive",
]
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde_core"
version = "1.0.227"
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a576275b607a2c86ea29e410193df32bc680303c82f31e275bbfcafe8b33be5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.227"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51e694923b8824cf0e9b382adf0f60d4e05f348f357b38833a3fa5ed7c2ede04"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "syn"
@@ -321,35 +462,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
dependencies = [
"fastrand",
"getrandom",
"getrandom 0.3.3",
"once_cell",
"rustix",
"windows-sys",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
"windows-sys 0.61.2",
]
[[package]]
name = "thiserror"
version = "2.0.16"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.16"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
@@ -370,9 +502,15 @@ checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]]
name = "unicode-width"
version = "0.2.1"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wait-timeout"
@@ -383,6 +521,12 @@ dependencies = [
"libc",
]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.7+wasi-0.2.4"
@@ -401,43 +545,199 @@ dependencies = [
"wit-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-link"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.61.1"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[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.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
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.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[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.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[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.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wit-bindgen"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive 0.7.35",
]
[[package]]
name = "zerocopy"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
"zerocopy-derive 0.8.27",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]

View File

@@ -4,8 +4,9 @@ version = "0.1.0"
edition = "2024"
[dependencies]
codespan = "0.12.0"
codespan-reporting = "0.12.0"
ariadne = { version = "0.5.1", features = ["auto-color"] }
internment = { version = "0.8.6", features = ["arc", "arena"] }
memmap2 = "0.9.8"
proptest = "1.7.0"
proptest-derive = "0.6.0"
thiserror = "2.0.12"

View File

@@ -6,11 +6,61 @@ mod parse;
mod parser_tests;
pub mod tokens;
pub use crate::syntax::error::ParserError;
use crate::syntax::parse::Parser;
use crate::syntax::tokens::Lexer;
use internment::ArcIntern;
pub use location::{Located, Location};
use memmap2::Mmap;
pub use name::Name;
use proptest_derive::Arbitrary;
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Range;
use std::path::{Path, PathBuf};
pub struct Universe {
pub files: HashMap<PathBuf, Mmap>,
pub modules: HashMap<PathBuf, Module>,
}
impl Default for Universe {
fn default() -> Self {
Universe {
files: HashMap::new(),
modules: HashMap::new(),
}
}
}
impl Universe {
pub fn add_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ParserError> {
let filename = file.as_ref().to_string_lossy().into_owned();
let file_handle = std::fs::File::open(&file)
.map_err(|e| ParserError::OpenError {
file: filename.clone(),
error: e,
})?;
let contents = unsafe { Mmap::map(&file_handle) }
.map_err(|e| ParserError::ReadError {
file: filename.clone(),
error: e,
})?;
let string_contents = std::str::from_utf8(&contents)
.map_err(|e| ParserError::Utf8Error {
file: filename.clone(),
error: e,
})?;
let lexer = Lexer::from(string_contents);
let mut parser = Parser::new(&file, lexer);
let module = parser.parse_module()?;
self.modules.insert(file.as_ref().to_path_buf(), module);
Ok(())
}
}
#[derive(Debug)]
pub struct Module {

View File

@@ -1,23 +1,34 @@
//use codespan_reporting::diagnostic::{Diagnostic, Label};
use crate::syntax::tokens::Token;
use std::ops::Range;
use std::path::PathBuf;
use internment::ArcIntern;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ParserError {
#[error("Lexer error at {file_id}: {error}")]
LexerError { file_id: usize, error: LexerError },
#[error("Lexer error at {file}: {error}")]
LexerError { file: ArcIntern<PathBuf>, error: LexerError },
#[error("Unacceptable end of file at {file_id} while {place}")]
UnacceptableEof { file_id: usize, place: &'static str },
#[error("Unacceptable end of file at {file} while {place}")]
UnacceptableEof { file: ArcIntern<PathBuf>, place: &'static str },
#[error("Unexpected token at {file_id}: expected {expected}, saw {token}")]
#[error("Unexpected token at {file}: expected {expected}, saw {token}")]
UnexpectedToken {
file_id: usize,
file: ArcIntern<PathBuf>,
span: Range<usize>,
token: Token,
expected: &'static str,
},
#[error("Unexpected problem opening file {file}: {error}")]
OpenError { file: String, error: std::io::Error },
#[error("Unexpected problem reading file {file}: {error}")]
ReadError { file: String, error: std::io::Error },
#[error("UTF-8 problem reading file {file}: {error}")]
Utf8Error { file: String, error: std::str::Utf8Error },
}
#[derive(Clone, Debug, Error, PartialEq)]

View File

@@ -1,6 +1,8 @@
use codespan_reporting::diagnostic::Label;
use ariadne::Span;
use internment::ArcIntern;
use std::cmp::{max, min};
use std::ops::Range;
use std::path::PathBuf;
pub trait Located {
fn location(&self) -> Location;
@@ -8,19 +10,35 @@ pub trait Located {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Location {
file_id: usize,
file: ArcIntern<PathBuf>,
span: Range<usize>,
}
impl Span for Location {
type SourceId = ArcIntern<PathBuf>;
fn source(&self) -> &Self::SourceId {
&self.file
}
fn start(&self) -> usize {
self.span.start
}
fn end(&self) -> usize {
self.span.end
}
}
impl Location {
pub fn new(file_id: usize, span: Range<usize>) -> Self {
Location { file_id, span }
pub fn new(file: &ArcIntern<PathBuf>, span: Range<usize>) -> Self {
Location { file: file.clone(), span }
}
pub fn extend_to(&self, other: &Location) -> Location {
assert_eq!(self.file_id, other.file_id);
assert_eq!(self.file, other.file);
Location {
file_id: self.file_id,
file: self.file.clone(),
span: min(self.span.start, other.span.start)..max(self.span.end, other.span.end),
}
}
@@ -30,19 +48,11 @@ impl Location {
self
}
pub fn file_id(&self) -> usize {
self.file_id
pub fn file(&self) -> &str {
self.file.to_str().unwrap_or("<bad_name>")
}
pub fn span(&self) -> Range<usize> {
self.span.clone()
}
pub fn primary_label(&self) -> Label<usize> {
Label::primary(self.file_id, self.span.clone())
}
pub fn secondary_label(&self) -> Label<usize> {
Label::secondary(self.file_id, self.span.clone())
}
}

View File

@@ -1,11 +1,12 @@
use crate::syntax::error::ParserError;
use crate::syntax::tokens::{Lexer, LocatedToken, Token};
use crate::syntax::*;
use internment::ArcIntern;
use std::collections::HashMap;
pub struct Parser<'a> {
file_id: usize,
lexer: Lexer<'a>,
pub struct Parser<'lexer> {
file: ArcIntern<PathBuf>,
lexer: Lexer<'lexer>,
known_tokens: Vec<LocatedToken>,
prefix_precedence_table: HashMap<String, u8>,
infix_precedence_table: HashMap<String, (u8, u8)>,
@@ -18,16 +19,19 @@ pub enum Associativity {
None,
}
impl<'a> Parser<'a> {
impl<'lexer> Parser<'lexer> {
/// Create a new parser from the given file index and lexer.
///
/// The file index will be used for annotating locations and for
/// error messages. If you don't care about either, you can use
/// 0 with no loss of functionality. (Obviously, it will be harder
/// to create quality error messages, but you already knew that.)
pub fn new(file_id: usize, lexer: Lexer<'a>) -> Parser<'a> {
pub fn new<P: AsRef<Path>>(
file: P,
lexer: Lexer<'lexer>
) -> Parser<'lexer> {
Parser {
file_id,
file: ArcIntern::new(file.as_ref().to_path_buf()),
lexer,
known_tokens: vec![],
prefix_precedence_table: HashMap::new(),
@@ -82,7 +86,7 @@ impl<'a> Parser<'a> {
.next()
.transpose()
.map_err(|error| ParserError::LexerError {
file_id: self.file_id,
file: self.file.clone(),
error,
})
}
@@ -94,13 +98,13 @@ impl<'a> Parser<'a> {
fn bad_eof(&mut self, place: &'static str) -> ParserError {
ParserError::UnacceptableEof {
file_id: self.file_id,
file: self.file.clone(),
place,
}
}
fn to_location(&self, span: Range<usize>) -> Location {
Location::new(self.file_id, span)
Location::new(&self.file, span)
}
pub fn parse_module(&mut self) -> Result<Module, ParserError> {
@@ -161,7 +165,7 @@ impl<'a> Parser<'a> {
if !matches!(maybe_paren.token, Token::OpenParen) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_paren.span,
token: maybe_paren.token,
expected: "open parenthesis, following the restrict keyword",
@@ -179,7 +183,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("Looking for open paren after restrict"))?;
if !matches!(maybe_paren.token, Token::CloseParen) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_paren.span,
token: maybe_paren.token,
expected: "close parenthesis following type restrictions",
@@ -212,7 +216,7 @@ impl<'a> Parser<'a> {
weird => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_constructor.span,
token: weird,
expected: "Constructor name, comma, or close parenthesis in type restriction",
@@ -261,7 +265,7 @@ impl<'a> Parser<'a> {
}
Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "'structure', 'enumeration', or a value identifier",
@@ -274,7 +278,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("looking for definition"))?;
if !matches!(structure_token.token, Token::ValueName(ref s) if s == "structure") {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: structure_token.span,
token: structure_token.token,
expected: "the 'structure' keyword",
@@ -288,7 +292,7 @@ impl<'a> Parser<'a> {
Token::TypeName(str) => str,
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: name.span,
token: name.token,
expected: "a structure name",
@@ -301,7 +305,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("the open brace after a structure name"))?;
if !matches!(brace.token, Token::OpenBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: brace.span,
token: brace.token,
expected: "the brace after a structure name",
@@ -319,7 +323,7 @@ impl<'a> Parser<'a> {
})?;
if !matches!(brace.token, Token::CloseBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: brace.span,
token: brace.token,
expected: "the brace at the end of a structure definition",
@@ -355,7 +359,7 @@ impl<'a> Parser<'a> {
})?;
if !matches!(maybe_colon.token, Token::Colon) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_colon.span,
token: maybe_colon.token,
expected: "colon after field name in constructor",
@@ -388,7 +392,7 @@ impl<'a> Parser<'a> {
return Ok(None);
} else {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_name.span,
token: maybe_name.token,
expected: "a field name",
@@ -412,7 +416,7 @@ impl<'a> Parser<'a> {
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_colon.span,
token: maybe_colon.token,
expected: "colon, comma, or close brace after field name",
@@ -432,7 +436,7 @@ impl<'a> Parser<'a> {
}
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: end_token.span,
token: end_token.token,
expected: "looking for comma or close brace after field definition",
@@ -459,7 +463,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("looking for definition"))?;
if !matches!(enumeration_token.token, Token::ValueName(ref e) if e == "enumeration") {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: enumeration_token.span,
token: enumeration_token.token,
expected: "the 'enumeration' keyword",
@@ -473,7 +477,7 @@ impl<'a> Parser<'a> {
Token::TypeName(str) => str,
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: name.span,
token: name.token,
expected: "an enumeration name",
@@ -486,7 +490,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("the open brace after an enumeration name"))?;
if !matches!(brace.token, Token::OpenBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: brace.span,
token: brace.token,
expected: "the brace after an enumeration name",
@@ -504,7 +508,7 @@ impl<'a> Parser<'a> {
})?;
if !matches!(brace.token, Token::CloseBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: brace.span,
token: brace.token,
expected: "the brace at the end of an enumeration definition",
@@ -535,7 +539,7 @@ impl<'a> Parser<'a> {
_ => {
self.save(maybe_name.clone());
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_name.span,
token: maybe_name.token,
expected: "variant name (identifier starting with a capital)",
@@ -555,7 +559,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("trying to parse a enumeration variant's type"))?;
if !matches!(maybe_close.token, Token::CloseParen) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_close.span,
token: maybe_close.token,
expected: "close paren to end an enumeration variant's type argument",
@@ -581,7 +585,7 @@ impl<'a> Parser<'a> {
_ => {
self.save(ender.clone());
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: ender.span,
token: ender.token,
expected: "comma or close brace after enumeration variant",
@@ -598,7 +602,7 @@ impl<'a> Parser<'a> {
}))
}
pub fn parse_function_or_value(&mut self) -> Result<Def, ParserError> {
fn parse_function_or_value(&mut self) -> Result<Def, ParserError> {
unimplemented!()
}
@@ -617,17 +621,17 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_match_expression(&mut self) -> Result<Expression, ParserError> {
fn parse_match_expression(&mut self) -> Result<Expression, ParserError> {
unimplemented!()
}
pub fn parse_if_expression(&mut self) -> Result<ConditionalExpr, ParserError> {
fn parse_if_expression(&mut self) -> Result<ConditionalExpr, ParserError> {
let next = self
.next()?
.ok_or_else(|| self.bad_eof("looking for an 'if' to start conditional"))?;
if !matches!(next.token, Token::ValueName(ref x) if x == "if") {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "an 'if' to start a conditional",
@@ -677,7 +681,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("looking for open brace to start block"))?;
if !matches!(next.token, Token::OpenBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "an open brace to start a block",
@@ -701,7 +705,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("looking for statement or block close"))?;
if !matches!(next.token, Token::CloseBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "a close brace to end a block",
@@ -762,7 +766,7 @@ impl<'a> Parser<'a> {
if !matches!(next.token, Token::ValueName(ref n) if n == "let") {
self.save(next.clone());
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "a 'let' to open a binding statement",
@@ -785,7 +789,7 @@ impl<'a> Parser<'a> {
Token::ValueName(v) => Name::new(self.to_location(next.span), v),
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "a variable name for the let binding",
@@ -798,7 +802,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("an '=' after a variable name in a binding"))?;
if !matches!(next.token, Token::OperatorName(ref x) if x == "=") {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "an '=' after the variable name in a let binding",
@@ -812,7 +816,7 @@ impl<'a> Parser<'a> {
.ok_or_else(|| self.bad_eof("looking for terminal semicolon for let statement"))?;
if !matches!(next.token, Token::Semi) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "a semicolon to finish a let statement",
@@ -839,7 +843,7 @@ impl<'a> Parser<'a> {
if *pre_prec < level {
self.save(next.clone());
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "a base expression of a tighter-binding prefix operator",
@@ -918,7 +922,7 @@ impl<'a> Parser<'a> {
if !matches!(next.token, Token::OpenParen) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "open paren for call arguments",
@@ -948,7 +952,7 @@ impl<'a> Parser<'a> {
Token::CloseParen => break,
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "comma or close paren in function arguments",
@@ -985,7 +989,7 @@ impl<'a> Parser<'a> {
} else {
self.save(hopefully_close.clone());
Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: hopefully_close.span,
token: hopefully_close.token,
expected: "close paren after expression",
@@ -1012,7 +1016,7 @@ impl<'a> Parser<'a> {
})?;
if !matches!(closer.token, Token::CloseBrace) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: closer.span,
token: closer.token,
expected: "close brace or comma after field value",
@@ -1028,7 +1032,7 @@ impl<'a> Parser<'a> {
})?;
if !matches!(second_colon.token, Token::Colon) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: second_colon.span,
token: second_colon.token,
expected: "second colon in enumeration value",
@@ -1047,7 +1051,7 @@ impl<'a> Parser<'a> {
_ => {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: vname.span,
token: vname.token,
expected: "enumeration value name",
@@ -1063,7 +1067,7 @@ impl<'a> Parser<'a> {
})?;
if !matches!(tok.token, Token::CloseParen) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: tok.span,
token: tok.token,
expected: "close paren after enum value argument",
@@ -1079,7 +1083,7 @@ impl<'a> Parser<'a> {
}
_ => Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: after_type_name.span,
token: after_type_name.token,
expected: "colon, open brace, or open paren in constructor",
@@ -1096,7 +1100,7 @@ impl<'a> Parser<'a> {
_ => {
self.save(next.clone());
Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "some base expression or an open brace",
@@ -1120,7 +1124,7 @@ impl<'a> Parser<'a> {
match args.pop() {
None => {
return Err(ParserError::UnacceptableEof {
file_id: self.file_id,
file: self.file.clone(),
place: "parsing function type or type",
});
}
@@ -1129,7 +1133,7 @@ impl<'a> Parser<'a> {
Some(_) => {
return Err(ParserError::UnacceptableEof {
file_id: self.file_id,
file: self.file.clone(),
place: "looking for '->' in function type",
});
}
@@ -1147,7 +1151,7 @@ impl<'a> Parser<'a> {
let LocatedToken { token, span } = maybe_arrow;
Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span,
token,
expected: "'->' in function type",
@@ -1193,7 +1197,7 @@ impl<'a> Parser<'a> {
if !matches!(closer.token, Token::CloseParen) {
return Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: closer.span,
token: closer.token,
expected: "close parenthesis to finish a type",
@@ -1209,7 +1213,7 @@ impl<'a> Parser<'a> {
});
Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span,
token,
expected: "type constructor, type variable, or primitive type",
@@ -1239,7 +1243,7 @@ impl<'a> Parser<'a> {
_ => {
self.save(maybe_constant.clone());
Err(ParserError::UnexpectedToken {
file_id: self.file_id,
file: self.file.clone(),
span: maybe_constant.span,
token: maybe_constant.token,
expected: "constant value",

View File

@@ -7,7 +7,7 @@ use crate::syntax::*;
fn constants() {
let parse_constant = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_constant()
};
@@ -65,7 +65,7 @@ fn constants() {
fn types() {
let parse_type = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_type()
};
@@ -123,7 +123,7 @@ fn types() {
fn type_restrictions() {
let parse_tr = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_type_restrictions()
};
@@ -195,7 +195,7 @@ fn type_restrictions() {
fn field_definition() {
let parse_fd = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_field_definition()
};
@@ -249,7 +249,7 @@ fn field_definition() {
fn structures() {
let parse_st = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_structure()
};
@@ -325,7 +325,7 @@ fn structures() {
fn enum_variant() {
let parse_ev = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_enum_variant()
};
@@ -382,7 +382,7 @@ fn enum_variant() {
fn enumerations() {
let parse_en = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_enumeration()
};
@@ -418,7 +418,7 @@ fn enumerations() {
fn expressions() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_expression()
};
@@ -451,7 +451,7 @@ fn expressions() {
fn enumeration_values() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_expression()
};
@@ -472,7 +472,7 @@ fn enumeration_values() {
fn structure_value() {
let parse_st = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_expression()
};
@@ -521,7 +521,7 @@ fn structure_value() {
fn infix_and_precedence() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.add_infix_precedence("+", parse::Associativity::Left, 6);
result.add_infix_precedence("*", parse::Associativity::Right, 7);
result.parse_expression()
@@ -625,7 +625,7 @@ fn infix_and_precedence() {
fn calls() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.add_infix_precedence("+", parse::Associativity::Left, 6);
result.add_infix_precedence("*", parse::Associativity::Right, 7);
result.parse_expression()
@@ -766,7 +766,7 @@ fn calls() {
fn prefix_and_postfix() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.add_infix_precedence("+", parse::Associativity::Left, 4);
result.add_infix_precedence("*", parse::Associativity::Left, 8);
result.add_prefix_precedence("++", 6);
@@ -840,7 +840,7 @@ fn prefix_and_postfix() {
fn blocks() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_expression()
};
@@ -879,7 +879,7 @@ fn blocks() {
fn bindings() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_expression()
};
@@ -896,7 +896,7 @@ fn bindings() {
fn conditionals() {
let parse_ex = |str| {
let lexer = Lexer::from(str);
let mut result = Parser::new(0, lexer);
let mut result = Parser::new("test", lexer);
result.parse_expression()
};