Skip to content

Commit

Permalink
Improve Escape Sequences in String Literals (#659)
Browse files Browse the repository at this point in the history
  • Loading branch information
InsertCreativityHere committed Oct 3, 2023
1 parent 293f61f commit 8b63a5a
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/parsers/slice/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ Attribute: WeakPtr<Attribute> = {
}

AttributeArgument: String = {
<sl: string_literal> => sl.replace('\\', ""),
<sl: string_literal> => unescape_string_literal(sl),
<i: identifier> => i.to_owned(),
}

Expand Down
16 changes: 16 additions & 0 deletions src/parsers/slice/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,22 @@ fn construct_attribute(
parser.ast.add_element(OwnedPtr::new(attribute))
}

fn unescape_string_literal(s: &str) -> String {
// Flag that stores whether the next character we read is being escaped.
let mut is_escaped = false;
s.chars()
.filter(|c| {
// If `c` is a backslash, and it isn't already escaped (ie: "\\"), then it is an escape character.
let is_escape_character = *c == '\\' && !is_escaped;
// Set `is_escaped` accordingly, so we know if the next character is being escaped.
is_escaped = is_escape_character;

// Return false for escape characters to filter them out of the string.
!is_escape_character
})
.collect()
}

fn try_parse_integer(parser: &mut Parser, s: &str, span: Span) -> Integer<i128> {
// Remove any underscores from the integer literal before trying to parse it.
let sanitized = s.replace('_', "");
Expand Down
4 changes: 2 additions & 2 deletions tests/parser_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn string_literals_support_character_escaping() {
let slice = r#"
module Test
[deprecated("This is a \"bad\" type.")]
[deprecated("This is a backslash\"\\\"\n.")]
struct Foo {}
"#;

Expand All @@ -73,7 +73,7 @@ fn string_literals_support_character_escaping() {
// Assert
let struct_def = ast.find_element::<Struct>("Test::Foo").unwrap();
let deprecated = struct_def.find_attribute::<attributes::Deprecated>().unwrap();
assert_eq!(deprecated.reason, Some("This is a \"bad\" type.".to_owned()))
assert_eq!(deprecated.reason, Some("This is a backslash\"\\\"n.".to_owned()))
}

#[test]
Expand Down

0 comments on commit 8b63a5a

Please sign in to comment.