✍️ 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. # It is not intended for manual editing.
version = 4 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]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.0"
@@ -12,8 +42,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
name = "bang" name = "bang"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"codespan", "ariadne",
"codespan-reporting", "internment",
"memmap2",
"proptest", "proptest",
"proptest-derive", "proptest-derive",
"thiserror", "thiserror",
@@ -34,6 +65,12 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.9.4" version = "2.9.4"
@@ -47,26 +84,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]] [[package]]
name = "codespan" name = "concolor"
version = "0.12.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4b418d52c9206820a56fc1aa28db73d67e346ba8ba6aa90987e8d6becef7e4" checksum = "0b946244a988c390a94667ae0e3958411fa40cc46ea496a929b263d883f5f9c3"
dependencies = [ dependencies = [
"codespan-reporting", "bitflags 1.3.2",
"serde", "concolor-query",
"is-terminal",
] ]
[[package]] [[package]]
name = "codespan-reporting" name = "concolor-query"
version = "0.12.0" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf"
dependencies = [ dependencies = [
"serde", "windows-sys 0.45.0",
"termcolor",
"unicode-width",
] ]
[[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]] [[package]]
name = "errno" name = "errno"
version = "0.3.14" version = "0.3.14"
@@ -74,7 +129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@@ -89,6 +144,23 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 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]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.3.3" version = "0.3.3"
@@ -98,7 +170,53 @@ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"r-efi", "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]] [[package]]
@@ -119,6 +237,25 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" 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]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.19" version = "0.2.19"
@@ -134,13 +271,26 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 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]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.21" version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [ dependencies = [
"zerocopy", "zerocopy 0.8.27",
] ]
[[package]] [[package]]
@@ -160,7 +310,7 @@ checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce"
dependencies = [ dependencies = [
"bit-set", "bit-set",
"bit-vec", "bit-vec",
"bitflags", "bitflags 2.9.4",
"lazy_static", "lazy_static",
"num-traits", "num-traits",
"rand", "rand",
@@ -191,9 +341,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.40" version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -230,7 +380,7 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [ dependencies = [
"getrandom", "getrandom 0.3.3",
] ]
[[package]] [[package]]
@@ -242,6 +392,15 @@ dependencies = [
"rand_core", "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]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.6" version = "0.8.6"
@@ -254,18 +413,18 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.9.4",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
name = "rusty-fork" name = "rusty-fork"
version = "0.3.0" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
dependencies = [ dependencies = [
"fnv", "fnv",
"quick-error", "quick-error",
@@ -274,34 +433,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "serde" name = "scopeguard"
version = "1.0.227" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80ece43fc6fbed4eb5392ab50c07334d3e577cbf40997ee896fe7af40bba4245" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]] [[package]]
name = "serde_core" name = "smallvec"
version = "1.0.227" version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a576275b607a2c86ea29e410193df32bc680303c82f31e275bbfcafe8b33be5" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
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",
]
[[package]] [[package]]
name = "syn" name = "syn"
@@ -321,35 +462,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
dependencies = [ dependencies = [
"fastrand", "fastrand",
"getrandom", "getrandom 0.3.3",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys", "windows-sys 0.61.2",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
] ]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "2.0.16" version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "2.0.16" version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -370,9 +502,15 @@ checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.2.1" version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "wait-timeout" name = "wait-timeout"
@@ -383,6 +521,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.14.7+wasi-0.2.4" version = "0.14.7+wasi-0.2.4"
@@ -401,43 +545,199 @@ dependencies = [
"wit-bindgen", "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]] [[package]]
name = "windows-link" name = "windows-link"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.61.1" version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"windows-link", "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]] [[package]]
name = "wit-bindgen" name = "wit-bindgen"
version = "0.46.0" version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 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]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.27" version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [ 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]] [[package]]

View File

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

View File

@@ -6,11 +6,61 @@ mod parse;
mod parser_tests; mod parser_tests;
pub mod tokens; 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}; pub use location::{Located, Location};
use memmap2::Mmap;
pub use name::Name; pub use name::Name;
use proptest_derive::Arbitrary; use proptest_derive::Arbitrary;
use std::collections::HashMap;
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::Range; 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)] #[derive(Debug)]
pub struct Module { pub struct Module {

View File

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

View File

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