Improve positioning
This commit is contained in:
parent
3224c04f72
commit
46419956bd
80
Cargo.lock
generated
80
Cargo.lock
generated
@ -4,9 +4,9 @@ version = 3
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.9"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -96,9 +96,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.86"
|
version = "1.0.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
|
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -121,9 +121,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.2"
|
version = "4.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651"
|
checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@ -143,9 +143,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.0"
|
version = "4.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
|
checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -243,15 +243,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.6"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
@ -302,9 +302,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.78"
|
version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@ -420,9 +420,9 @@ checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.50"
|
version = "2.0.53"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
|
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -499,7 +499,7 @@ version = "0.52.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.0",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -534,17 +534,17 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.0",
|
"windows_aarch64_gnullvm 0.52.4",
|
||||||
"windows_aarch64_msvc 0.52.0",
|
"windows_aarch64_msvc 0.52.4",
|
||||||
"windows_i686_gnu 0.52.0",
|
"windows_i686_gnu 0.52.4",
|
||||||
"windows_i686_msvc 0.52.0",
|
"windows_i686_msvc 0.52.4",
|
||||||
"windows_x86_64_gnu 0.52.0",
|
"windows_x86_64_gnu 0.52.4",
|
||||||
"windows_x86_64_gnullvm 0.52.0",
|
"windows_x86_64_gnullvm 0.52.4",
|
||||||
"windows_x86_64_msvc 0.52.0",
|
"windows_x86_64_msvc 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -561,9 +561,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
@ -579,9 +579,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
@ -597,9 +597,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
@ -615,9 +615,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
@ -633,9 +633,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
@ -651,9 +651,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
@ -669,9 +669,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.0"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yansi"
|
name = "yansi"
|
||||||
|
@ -126,7 +126,9 @@ mod tests {
|
|||||||
None,
|
None,
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
Positioned {
|
Positioned {
|
||||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
node: Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
position: (0, 0),
|
position: (0, 0),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -152,7 +154,9 @@ mod tests {
|
|||||||
None,
|
None,
|
||||||
AssignmentOperator::AddAssign,
|
AssignmentOperator::AddAssign,
|
||||||
Positioned {
|
Positioned {
|
||||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(41))),
|
node: Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(41)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
position: (0, 0),
|
position: (0, 0),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -178,7 +182,9 @@ mod tests {
|
|||||||
None,
|
None,
|
||||||
AssignmentOperator::SubAssign,
|
AssignmentOperator::SubAssign,
|
||||||
Positioned {
|
Positioned {
|
||||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(1))),
|
node: Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
position: (0, 0),
|
position: (0, 0),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -201,7 +207,9 @@ mod tests {
|
|||||||
}),
|
}),
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
Positioned {
|
Positioned {
|
||||||
node: Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
node: Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
position: (0, 0),
|
position: (0, 0),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -61,9 +61,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn run_returns_value_of_final_statement() {
|
fn run_returns_value_of_final_statement() {
|
||||||
let block = Block::new(vec![
|
let block = Block::new(vec![
|
||||||
Statement::Expression(Expression::Value(ValueNode::Integer(1))),
|
Statement::Expression(
|
||||||
Statement::Expression(Expression::Value(ValueNode::Integer(2))),
|
Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()),
|
||||||
Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
),
|
||||||
|
Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(2)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
|
Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -75,8 +81,12 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn expected_type_returns_type_of_final_statement() {
|
fn expected_type_returns_type_of_final_statement() {
|
||||||
let block = Block::new(vec![
|
let block = Block::new(vec![
|
||||||
Statement::Expression(Expression::Value(ValueNode::String("42".to_string()))),
|
Statement::Expression(
|
||||||
Statement::Expression(Expression::Value(ValueNode::Integer(42))),
|
Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()),
|
||||||
|
),
|
||||||
|
Statement::Expression(
|
||||||
|
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))
|
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))
|
||||||
|
@ -83,11 +83,12 @@ mod tests {
|
|||||||
fn simple_if() {
|
fn simple_if() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
IfElse::new(
|
IfElse::new(
|
||||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||||
Block::new(vec![Statement::Expression(Expression::Value(
|
Block::new(vec![Statement::Expression(
|
||||||
ValueNode::String("foo".to_string())
|
Expression::Value(ValueNode::String("foo".to_string()))
|
||||||
),)])
|
.positioned((0..0).into())
|
||||||
.positioned((0, 0)),
|
)])
|
||||||
|
.positioned((0..0).into()),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
.run(&Context::new()),
|
.run(&Context::new()),
|
||||||
@ -99,16 +100,18 @@ mod tests {
|
|||||||
fn simple_if_else() {
|
fn simple_if_else() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
IfElse::new(
|
IfElse::new(
|
||||||
Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)),
|
Expression::Value(ValueNode::Boolean(false)).positioned((0..0).into()),
|
||||||
Block::new(vec![Statement::Expression(Expression::Value(
|
Block::new(vec![Statement::Expression(
|
||||||
ValueNode::String("foo".to_string())
|
Expression::Value(ValueNode::String("foo".to_string()))
|
||||||
))])
|
.positioned((0..0).into())
|
||||||
.positioned((0, 0)),
|
)])
|
||||||
|
.positioned((0..0).into()),
|
||||||
Some(
|
Some(
|
||||||
Block::new(vec![Statement::Expression(Expression::Value(
|
Block::new(vec![Statement::Expression(
|
||||||
ValueNode::String("bar".to_string())
|
Expression::Value(ValueNode::String("bar".to_string()))
|
||||||
))])
|
.positioned((0..0).into())
|
||||||
.positioned((0, 0))
|
)])
|
||||||
|
.positioned((0..0).into())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.run(&Context::new()),
|
.run(&Context::new()),
|
||||||
|
@ -139,8 +139,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn equal() {
|
fn equal() {
|
||||||
assert!(Logic::Equal(
|
assert!(Logic::Equal(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -153,8 +153,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn not_equal() {
|
fn not_equal() {
|
||||||
assert!(Logic::NotEqual(
|
assert!(Logic::NotEqual(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -167,8 +167,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn greater() {
|
fn greater() {
|
||||||
assert!(Logic::Greater(
|
assert!(Logic::Greater(
|
||||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -181,8 +181,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn less() {
|
fn less() {
|
||||||
assert!(Logic::Less(
|
assert!(Logic::Less(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -195,8 +195,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn greater_or_equal() {
|
fn greater_or_equal() {
|
||||||
assert!(Logic::GreaterOrEqual(
|
assert!(Logic::GreaterOrEqual(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(41)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(41)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -206,8 +206,8 @@ mod tests {
|
|||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
assert!(Logic::GreaterOrEqual(
|
assert!(Logic::GreaterOrEqual(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -220,8 +220,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn less_or_equal() {
|
fn less_or_equal() {
|
||||||
assert!(Logic::LessOrEqual(
|
assert!(Logic::LessOrEqual(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(43)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -231,8 +231,8 @@ mod tests {
|
|||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
assert!(Logic::LessOrEqual(
|
assert!(Logic::LessOrEqual(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -245,8 +245,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn and() {
|
fn and() {
|
||||||
assert!(Logic::And(
|
assert!(Logic::And(
|
||||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -259,8 +259,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn or() {
|
fn or() {
|
||||||
assert!(Logic::Or(
|
assert!(Logic::Or(
|
||||||
Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
|
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)),
|
Expression::Value(ValueNode::Boolean(false)).positioned((0..0).into()),
|
||||||
)
|
)
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -273,7 +273,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn not() {
|
fn not() {
|
||||||
assert!(
|
assert!(
|
||||||
Logic::Not(Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)))
|
Logic::Not(Expression::Value(ValueNode::Boolean(false)).positioned((0..0).into()))
|
||||||
.run(&Context::new())
|
.run(&Context::new())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_return_value()
|
.as_return_value()
|
||||||
|
@ -13,6 +13,8 @@ pub mod r#type;
|
|||||||
pub mod value_node;
|
pub mod value_node;
|
||||||
pub mod r#while;
|
pub mod r#while;
|
||||||
|
|
||||||
|
use chumsky::span::{SimpleSpan, Span};
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
assignment::{Assignment, AssignmentOperator},
|
assignment::{Assignment, AssignmentOperator},
|
||||||
block::Block,
|
block::Block,
|
||||||
@ -47,10 +49,10 @@ pub trait AbstractTree: Sized {
|
|||||||
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
|
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
|
||||||
fn run(self, context: &Context) -> Result<Action, RuntimeError>;
|
fn run(self, context: &Context) -> Result<Action, RuntimeError>;
|
||||||
|
|
||||||
fn positioned(self, position: (usize, usize)) -> Positioned<Self> {
|
fn positioned(self, span: SimpleSpan) -> Positioned<Self> {
|
||||||
Positioned {
|
Positioned {
|
||||||
node: self,
|
node: self,
|
||||||
position,
|
position: (span.start(), span.end()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,16 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type, While};
|
use super::{
|
||||||
|
AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Positioned, Type, While,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Assignment(Assignment),
|
Assignment(Assignment),
|
||||||
Block(Block),
|
Block(Block),
|
||||||
Break,
|
Break,
|
||||||
Expression(Expression),
|
Expression(Positioned<Expression>),
|
||||||
IfElse(IfElse),
|
IfElse(IfElse),
|
||||||
Loop(Loop),
|
Loop(Loop),
|
||||||
While(While),
|
While(While),
|
||||||
@ -22,7 +24,7 @@ impl AbstractTree for Statement {
|
|||||||
Statement::Assignment(assignment) => assignment.expected_type(_context),
|
Statement::Assignment(assignment) => assignment.expected_type(_context),
|
||||||
Statement::Block(block) => block.expected_type(_context),
|
Statement::Block(block) => block.expected_type(_context),
|
||||||
Statement::Break => Ok(Type::None),
|
Statement::Break => Ok(Type::None),
|
||||||
Statement::Expression(expression) => expression.expected_type(_context),
|
Statement::Expression(expression) => expression.node.expected_type(_context),
|
||||||
Statement::IfElse(if_else) => if_else.expected_type(_context),
|
Statement::IfElse(if_else) => if_else.expected_type(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.expected_type(_context),
|
Statement::Loop(r#loop) => r#loop.expected_type(_context),
|
||||||
Statement::While(r#while) => r#while.expected_type(_context),
|
Statement::While(r#while) => r#while.expected_type(_context),
|
||||||
@ -34,7 +36,7 @@ impl AbstractTree for Statement {
|
|||||||
Statement::Assignment(assignment) => assignment.validate(_context),
|
Statement::Assignment(assignment) => assignment.validate(_context),
|
||||||
Statement::Block(block) => block.validate(_context),
|
Statement::Block(block) => block.validate(_context),
|
||||||
Statement::Break => Ok(()),
|
Statement::Break => Ok(()),
|
||||||
Statement::Expression(expression) => expression.validate(_context),
|
Statement::Expression(expression) => expression.node.validate(_context),
|
||||||
Statement::IfElse(if_else) => if_else.validate(_context),
|
Statement::IfElse(if_else) => if_else.validate(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.validate(_context),
|
Statement::Loop(r#loop) => r#loop.validate(_context),
|
||||||
Statement::While(r#while) => r#while.validate(_context),
|
Statement::While(r#while) => r#while.validate(_context),
|
||||||
@ -46,7 +48,7 @@ impl AbstractTree for Statement {
|
|||||||
Statement::Assignment(assignment) => assignment.run(_context),
|
Statement::Assignment(assignment) => assignment.run(_context),
|
||||||
Statement::Block(block) => block.run(_context),
|
Statement::Block(block) => block.run(_context),
|
||||||
Statement::Break => Ok(Action::Break),
|
Statement::Break => Ok(Action::Break),
|
||||||
Statement::Expression(expression) => expression.run(_context),
|
Statement::Expression(expression) => expression.node.run(_context),
|
||||||
Statement::IfElse(if_else) => if_else.run(_context),
|
Statement::IfElse(if_else) => if_else.run(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.run(_context),
|
Statement::Loop(r#loop) => r#loop.run(_context),
|
||||||
Statement::While(r#while) => r#while.run(_context),
|
Statement::While(r#while) => r#while.run(_context),
|
||||||
|
14
src/error.rs
14
src/error.rs
@ -19,7 +19,7 @@ pub enum Error {
|
|||||||
span: (usize, usize),
|
span: (usize, usize),
|
||||||
},
|
},
|
||||||
Runtime(RuntimeError),
|
Runtime(RuntimeError),
|
||||||
Validation(ValidationError),
|
Validation(ValidationError, (usize, usize)),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
@ -46,9 +46,15 @@ impl Error {
|
|||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
Error::Runtime(_) => todo!(),
|
Error::Runtime(_) => todo!(),
|
||||||
Error::Validation(validation_error) => {
|
Error::Validation(validation_error, position) => {
|
||||||
let mut report =
|
let mut report = Report::build(
|
||||||
Report::build(ReportKind::Custom("Validation Error", Color::White), (), 0);
|
ReportKind::Custom("Validation Error: The code was not run.", Color::White),
|
||||||
|
(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.with_label(
|
||||||
|
Label::new(position.0..position.1).with_message("Error found in this item."),
|
||||||
|
);
|
||||||
|
|
||||||
match validation_error {
|
match validation_error {
|
||||||
ValidationError::ExpectedBoolean => {
|
ValidationError::ExpectedBoolean => {
|
||||||
|
@ -35,9 +35,10 @@ impl Interpreter {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|statement| {
|
.filter_map(|statement| {
|
||||||
statement
|
statement
|
||||||
|
.node
|
||||||
.validate(&self.context)
|
.validate(&self.context)
|
||||||
.err()
|
.err()
|
||||||
.map(|validation_error| Error::Validation(validation_error))
|
.map(|validation_error| Error::Validation(validation_error, statement.position))
|
||||||
})
|
})
|
||||||
.collect::<Vec<Error>>();
|
.collect::<Vec<Error>>();
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ impl Interpreter {
|
|||||||
let mut value = None;
|
let mut value = None;
|
||||||
|
|
||||||
for statement in statements {
|
for statement in statements {
|
||||||
value = match statement.run(&self.context) {
|
value = match statement.node.run(&self.context) {
|
||||||
Ok(action) => match action {
|
Ok(action) => match action {
|
||||||
Action::Break => None,
|
Action::Break => None,
|
||||||
Action::Return(value) => Some(value),
|
Action::Return(value) => Some(value),
|
||||||
|
@ -12,7 +12,7 @@ pub type DustParser<'src> = Boxed<
|
|||||||
'src,
|
'src,
|
||||||
'src,
|
'src,
|
||||||
ParserInput<'src>,
|
ParserInput<'src>,
|
||||||
Vec<Statement>,
|
Vec<Positioned<Statement>>,
|
||||||
extra::Err<Rich<'src, Token<'src>, SimpleSpan>>,
|
extra::Err<Rich<'src, Token<'src>, SimpleSpan>>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ pub type ParserInput<'src> =
|
|||||||
|
|
||||||
pub fn parse<'src>(
|
pub fn parse<'src>(
|
||||||
tokens: &'src [(Token<'src>, SimpleSpan)],
|
tokens: &'src [(Token<'src>, SimpleSpan)],
|
||||||
) -> Result<Vec<Statement>, Vec<Error>> {
|
) -> Result<Vec<Positioned<Statement>>, Vec<Error>> {
|
||||||
parser()
|
parser()
|
||||||
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
|
||||||
.into_result()
|
.into_result()
|
||||||
@ -111,6 +111,9 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Control(Control::Colon)).ignore_then(r#type)
|
just(Token::Control(Control::Colon)).ignore_then(r#type)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let positioned_type =
|
||||||
|
type_specification.map_with(|r#type, state| r#type.positioned(state.span()));
|
||||||
|
|
||||||
let statement = recursive(|statement| {
|
let statement = recursive(|statement| {
|
||||||
let block = statement
|
let block = statement
|
||||||
.clone()
|
.clone()
|
||||||
@ -122,6 +125,10 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
)
|
)
|
||||||
.map(|statements| Block::new(statements));
|
.map(|statements| Block::new(statements));
|
||||||
|
|
||||||
|
let positioned_block = block
|
||||||
|
.clone()
|
||||||
|
.map_with(|block, state| block.positioned(state.span()));
|
||||||
|
|
||||||
let expression = recursive(|expression| {
|
let expression = recursive(|expression| {
|
||||||
let identifier_expression = identifier
|
let identifier_expression = identifier
|
||||||
.clone()
|
.clone()
|
||||||
@ -154,10 +161,17 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
|
|
||||||
let map_assignment = identifier
|
let map_assignment = identifier
|
||||||
.clone()
|
.clone()
|
||||||
.then(type_specification.clone().or_not())
|
.then(
|
||||||
|
type_specification
|
||||||
|
.map_with(|r#type, state| r#type.positioned(state.span()))
|
||||||
|
.clone()
|
||||||
|
.or_not(),
|
||||||
|
)
|
||||||
.then_ignore(just(Token::Operator(Operator::Assign)))
|
.then_ignore(just(Token::Operator(Operator::Assign)))
|
||||||
.then(expression.clone())
|
.then(expression.clone())
|
||||||
.map(|((identifier, r#type), expression)| (identifier, r#type, expression));
|
.map_with(|((identifier, r#type), expression), state| {
|
||||||
|
(identifier, r#type, expression.positioned(state.span()))
|
||||||
|
});
|
||||||
|
|
||||||
let map = map_assignment
|
let map = map_assignment
|
||||||
.separated_by(just(Token::Control(Control::Comma)).or_not())
|
.separated_by(just(Token::Control(Control::Comma)).or_not())
|
||||||
@ -180,11 +194,11 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
)
|
)
|
||||||
.then(type_specification.clone())
|
.then(type_specification.clone())
|
||||||
.then(block.clone())
|
.then(block.clone())
|
||||||
.map(|((parameters, return_type), body)| {
|
.map_with(|((parameters, return_type), body), state| {
|
||||||
Expression::Value(ValueNode::Function {
|
Expression::Value(ValueNode::Function {
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type: return_type.positioned(state.span()),
|
||||||
body,
|
body: body.positioned(state.span()),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.boxed();
|
.boxed();
|
||||||
@ -216,7 +230,8 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Control(Control::ParenOpen)),
|
just(Token::Control(Control::ParenOpen)),
|
||||||
just(Token::Control(Control::ParenClose)),
|
just(Token::Control(Control::ParenClose)),
|
||||||
),
|
),
|
||||||
));
|
))
|
||||||
|
.map_with(|expression, state| expression.positioned(state.span()));
|
||||||
|
|
||||||
use Operator::*;
|
use Operator::*;
|
||||||
|
|
||||||
@ -280,6 +295,7 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
|
|
||||||
choice((
|
choice((
|
||||||
function,
|
function,
|
||||||
|
function_call,
|
||||||
range,
|
range,
|
||||||
logic_math_and_index,
|
logic_math_and_index,
|
||||||
identifier_expression,
|
identifier_expression,
|
||||||
@ -290,17 +306,22 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
.boxed()
|
.boxed()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let positioned_expression = expression
|
||||||
|
.clone()
|
||||||
|
.map_with(|expression, state| expression.positioned(state.span()));
|
||||||
|
|
||||||
let expression_statement = expression
|
let expression_statement = expression
|
||||||
.clone()
|
.clone()
|
||||||
.map_with(|expression, state| Statement::expression(expression, state.span()))
|
.map_with(|expression, state| {
|
||||||
|
Statement::Expression(expression.positioned(state.span()))
|
||||||
|
})
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let r#break =
|
let r#break = just(Token::Keyword("break")).to(Statement::Break);
|
||||||
just(Token::Keyword("break")).map_with(|_, state| Statement::r#break(state.span()));
|
|
||||||
|
|
||||||
let assignment = identifier
|
let assignment = identifier
|
||||||
.clone()
|
.clone()
|
||||||
.then(type_specification.clone().or_not())
|
.then(positioned_type.clone().or_not())
|
||||||
.then(choice((
|
.then(choice((
|
||||||
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
|
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
|
||||||
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
|
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
|
||||||
@ -308,16 +329,18 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
)))
|
)))
|
||||||
.then(statement.clone())
|
.then(statement.clone())
|
||||||
.map_with(|(((identifier, r#type), operator), statement), state| {
|
.map_with(|(((identifier, r#type), operator), statement), state| {
|
||||||
Statement::assignment(
|
Statement::Assignment(Assignment::new(
|
||||||
Assignment::new(identifier, r#type, operator, statement),
|
identifier,
|
||||||
state.span(),
|
r#type,
|
||||||
)
|
operator,
|
||||||
|
statement.positioned(state.span()),
|
||||||
|
))
|
||||||
})
|
})
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let block_statement = block
|
let block_statement = block
|
||||||
.clone()
|
.clone()
|
||||||
.map_with(|block, state| Statement::block(block, state.span()));
|
.map_with(|block, state| Statement::Block(block));
|
||||||
|
|
||||||
let r#loop = statement
|
let r#loop = statement
|
||||||
.clone()
|
.clone()
|
||||||
@ -328,29 +351,24 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))),
|
just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))),
|
||||||
just(Token::Control(Control::CurlyClose)),
|
just(Token::Control(Control::CurlyClose)),
|
||||||
)
|
)
|
||||||
.map_with(|statements, state| Statement::r#loop(Loop::new(statements), state.span()))
|
.map_with(|statements, state| Statement::Loop(Loop::new(statements)))
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let r#while = just(Token::Keyword("while"))
|
let r#while = just(Token::Keyword("while"))
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.then(block.clone())
|
.then(block.clone())
|
||||||
.map_with(|(expression, block), state| {
|
.map_with(|(expression, block), state| Statement::While(While::new(expression, block)));
|
||||||
Statement::r#while(While::new(expression, block), state.span())
|
|
||||||
});
|
|
||||||
|
|
||||||
let if_else = just(Token::Keyword("if"))
|
let if_else = just(Token::Keyword("if"))
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(positioned_expression.clone())
|
||||||
.then(block.clone())
|
.then(positioned_block.clone())
|
||||||
.then(
|
.then(
|
||||||
just(Token::Keyword("else"))
|
just(Token::Keyword("else"))
|
||||||
.ignore_then(block.clone())
|
.ignore_then(positioned_block.clone())
|
||||||
.or_not(),
|
.or_not(),
|
||||||
)
|
)
|
||||||
.map_with(|((if_expression, if_block), else_block), state| {
|
.map_with(|((if_expression, if_block), else_block), state| {
|
||||||
Statement::if_else(
|
Statement::IfElse(IfElse::new(if_expression, if_block, else_block))
|
||||||
IfElse::new(if_expression, if_block, else_block),
|
|
||||||
state.span(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
@ -367,13 +385,15 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
.boxed()
|
.boxed()
|
||||||
});
|
});
|
||||||
|
|
||||||
statement.repeated().collect().boxed()
|
statement
|
||||||
|
.map_with(|statement, state| statement.positioned(state.span()))
|
||||||
|
.repeated()
|
||||||
|
.collect()
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use tests::statement::StatementInner;
|
|
||||||
|
|
||||||
use crate::lexer::lex;
|
use crate::lexer::lex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user