Skip to content

Commit a19155c

Browse files
committed
Add test cases for freestanding \ followed by escaped reference symbol
Reclass's reference parsing only requires double-escaped backslashes 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\\`.
1 parent 112b22a commit a19155c

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

src/refs/parser.rs

+63
Original file line numberDiff line numberDiff line change
@@ -544,4 +544,67 @@ mod test_parser_funcs {
544544
Ok(("", Token::literal_from_str("foo}bar")))
545545
);
546546
}
547+
548+
#[test]
549+
fn test_parse_escape_then_double_escaped_ref() {
550+
// Reclass's reference parsing only requires double-escaped backslashes when they precede a
551+
// reference opening or closing symbol. Other backslashes don't need to be escaped. The
552+
// parser will try to parse backslashes as single characters first, and will only interpret
553+
// them as escape characters when they precede a reference opening or closing symbol.
554+
//
555+
// Therefore the string `\\\${foo}` is parsed as a freestanding `\` followed by a
556+
// double-escaped reference resulting in `\\` followed by the contents of `${foo}` once
557+
// interpolated.
558+
let refstr = r#"\\\${foo}"#.to_string();
559+
assert_eq!(
560+
parse_ref(&refstr),
561+
Ok((
562+
"",
563+
Token::Combined(vec![
564+
Token::literal_from_str(r"\\"),
565+
Token::Ref(vec![Token::literal_from_str("foo")])
566+
])
567+
))
568+
)
569+
}
570+
571+
#[test]
572+
fn test_parse_escape_escape_then_double_escaped_ref() {
573+
// Reclass's reference parsing only requires double-escaped backslashes when they precede a
574+
// reference opening or closing symbol. Other backslashes don't need to be escaped. The
575+
// parser will try to parse backslashes as single characters first, and will only interpret
576+
// them as escape characters when they precede a reference opening or closing symbol.
577+
//
578+
// Therefore the string `\\\\${foo}` is parsed as two freestanding `\` followed by a
579+
// double-escaped reference resulting in `\\\` followed by the contents of `${foo}` once
580+
// interpolated.
581+
let refstr = r#"\\\\${foo}"#.to_string();
582+
assert_eq!(
583+
parse_ref(&refstr),
584+
Ok((
585+
"",
586+
Token::Combined(vec![
587+
Token::literal_from_str(r"\\\"),
588+
Token::Ref(vec![Token::literal_from_str("foo")])
589+
])
590+
))
591+
)
592+
}
593+
594+
#[test]
595+
fn test_parse_escape_then_double_escaped_ref_close() {
596+
// Reclass's reference parsing only requires double-escaped backslashes when they precede a
597+
// reference opening or closing symbol. Other backslashes don't need to be escaped. The
598+
// parser will try to parse backslashes as single characters first, and will only interpret
599+
// them as escape characters when they precede a reference opening or closing symbol.
600+
//
601+
// Therefore the string `${foo\\\}` is parsed as a reference to `foo\\`. The first `\` in
602+
// the reference is parsed as a freestanding `\` and the following `\\` is parsed as a
603+
// double-escaped reference closing symbol.
604+
let refstr = r#"${foo\\\}"#.to_string();
605+
assert_eq!(
606+
parse_ref(&refstr),
607+
Ok(("", Token::Ref(vec![Token::literal_from_str(r"foo\\")])))
608+
)
609+
}
547610
}

0 commit comments

Comments
 (0)