Skip to content

Commit

Permalink
Add test cases for freestanding \ followed by escaped reference symbol
Browse files Browse the repository at this point in the history
Reclass's reference parsing only requires escaping backslashes that
should be literals when they precede a reference opening or closing
symbol. Other backslashes don't need to be escaped. The parser will try
to parse backslashes as single characters first, and will only interpret
them as escape characters when they precede a reference opening or
closing symbol.

We add three test cases which illustrate this behavior: `\\\${foo}`
which is parsed as a single `\` followed by a double-escaped reference,
`\\\\${foo}` which is parsed as two `\` followed by a double-escaped
reference, and `${foo\\\}` which is parsed as a reference to `foo\\`.
  • Loading branch information
simu committed Aug 30, 2023
1 parent 112b22a commit 622235e
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions src/refs/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,4 +544,70 @@ mod test_parser_funcs {
Ok(("", Token::literal_from_str("foo}bar")))
);
}

#[test]
fn test_parse_escape_then_double_escaped_ref() {
// Reclass's reference parsing only requires escaping backslashes that should be literals
// when they precede a reference opening or closing symbol. Other backslashes don't need to
// be escaped. The parser will try to parse backslashes as single characters first, and
// will only interpret them as escape characters when they precede a reference opening or
// closing symbol.
//
// Therefore the string `\\\${foo}` is parsed as a freestanding `\` followed by a
// double-escaped reference resulting in `\\` followed by the contents of `${foo}` once
// interpolated.
let refstr = r#"\\\${foo}"#.to_string();
assert_eq!(
parse_ref(&refstr),
Ok((
"",
Token::Combined(vec![
Token::literal_from_str(r"\\"),
Token::Ref(vec![Token::literal_from_str("foo")])
])
))
)
}

#[test]
fn test_parse_escape_escape_then_double_escaped_ref() {
// Reclass's reference parsing only requires escaping backslashes that should be literals
// when they precede a reference opening or closing symbol. Other backslashes don't need to
// be escaped. The parser will try to parse backslashes as single characters first, and
// will only interpret them as escape characters when they precede a reference opening or
// closing symbol.
//
// Therefore the string `\\\\${foo}` is parsed as two freestanding `\` followed by a
// double-escaped reference resulting in `\\\` followed by the contents of `${foo}` once
// interpolated.
let refstr = r#"\\\\${foo}"#.to_string();
assert_eq!(
parse_ref(&refstr),
Ok((
"",
Token::Combined(vec![
Token::literal_from_str(r"\\\"),
Token::Ref(vec![Token::literal_from_str("foo")])
])
))
)
}

#[test]
fn test_parse_escape_then_double_escaped_ref_close() {
// Reclass's reference parsing only requires escaping backslashes that should be literals
// when they precede a reference opening or closing symbol. Other backslashes don't need to
// be escaped. The parser will try to parse backslashes as single characters first, and
// will only interpret them as escape characters when they precede a reference opening or
// closing symbol.
//
// Therefore the string `${foo\\\}` is parsed as a reference to `foo\\`. The first `\` in
// the reference is parsed as a freestanding `\` and the following `\\` is parsed as a
// double-escaped reference closing symbol.
let refstr = r#"${foo\\\}"#.to_string();
assert_eq!(
parse_ref(&refstr),
Ok(("", Token::Ref(vec![Token::literal_from_str(r"foo\\")])))
)
}
}

0 comments on commit 622235e

Please sign in to comment.