diff --git a/CHANGELOG.md b/CHANGELOG.md index f841457..4df02d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +* Fix incorrect parsing of string literals containing "verus!{" * Support automatic formatting of the `seq!` macro # v0.3.4 diff --git a/src/verus-minimal.pest b/src/verus-minimal.pest index 1102311..2a28443 100644 --- a/src/verus-minimal.pest +++ b/src/verus-minimal.pest @@ -20,6 +20,31 @@ COMMENT = @{ | ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) } +string = @{ + "\"" ~ ("\\\"" | !"\"" ~ ANY)* ~ "\"" +} + +raw_string = @{ + "r" ~ PUSH("#"*) ~ "\"" // push the number signs onto the stack + ~ raw_string_interior + ~ "\"" ~ POP // match a quotation mark and the number signs +} +raw_string_interior = { + ( + !("\"" ~ PEEK) // unless the next character is a quotation mark + // followed by the correct amount of number signs, + ~ ANY // consume one character + )* +} + +byte_string = @{ + "b" ~ string +} + +raw_byte_string = @{ + "b" ~ raw_string +} + multiline_comment = @{ "/*" ~ (multiline_comment | (!"*/" ~ ANY))* ~ "*/" } @@ -34,7 +59,7 @@ file = { /// Region of code that doesn't contain any Verus macro use whatsoever non_verus = @{ - (!("verus!" ~ WHITESPACE* ~ "{") ~ ANY)* + (!("verus!" ~ WHITESPACE* ~ "{") ~ (string | raw_string | byte_string | raw_byte_string | ANY))* } /// An actual use of the `verus! { ... }` macro diff --git a/src/verus.pest b/src/verus.pest index ee28f09..f5ce001 100644 --- a/src/verus.pest +++ b/src/verus.pest @@ -72,9 +72,9 @@ file = { /// someone might define a macro-rules macro _outside_ the verus! macro, but use /// a verus! inside of the macro body itself, to generate Verus code; if that /// happens, then we need to make sure that we aren't accidentally starting -/// parsing in the middle of the macro_rules macro body itself. +/// parsing in the middle of the macro_rules macro body itself. Similarly, strings. non_verus = @{ - (!("verus!" ~ WHITESPACE* ~ "{") ~ (macro_rules | ANY))* + (!("verus!" ~ WHITESPACE* ~ "{") ~ (macro_rules | string | raw_string | byte_string | raw_byte_string | ANY))* } /// An actual use of the `verus! { ... }` macro diff --git a/tests/rustfmt-matching.rs b/tests/rustfmt-matching.rs index c9375c5..c06b9dc 100644 --- a/tests/rustfmt-matching.rs +++ b/tests/rustfmt-matching.rs @@ -430,3 +430,13 @@ fn test() { "#; compare(file); } + +#[test] +fn rust_verus_bang_in_string() { + let file = r#" +fn test() { + println!("verus!{{{}}}", "Hello"); +} +"#; + compare(file); +}