Allow escaping quotes in strings.

This commit is contained in:
Stephen Chung 2020-04-11 12:46:10 +08:00
parent c1b16b1a35
commit d73cfb6da5
4 changed files with 22 additions and 2 deletions

View File

@ -1076,7 +1076,21 @@ hex ('`\x`_xx_') escape sequences.
Hex sequences map to ASCII characters, while '`\u`' maps to 16-bit common Unicode code points and '`\U`' maps the full, Hex sequences map to ASCII characters, while '`\u`' maps to 16-bit common Unicode code points and '`\U`' maps the full,
32-bit extended Unicode code points. 32-bit extended Unicode code points.
Internally Rhai strings are stored as UTF-8 just like Rust (they _are_ Rust `String`s!), but there are major differences. Standard escape sequences:
| Escape sequence | Meaning |
| --------------- | ------------------------------ |
| `\\` | back-slash `\` |
| `\t` | tab |
| `\r` | carriage-return `CR` |
| `\n` | line-feed `LF` |
| `\"` | double-quote `"` in strings |
| `\'` | single-quote `'` in characters |
| `\x`_xx_ | Unicode in 2-digit hex |
| `\u`_xxxx_ | Unicode in 4-digit hex |
| `\U`_xxxxxxxx_ | Unicode in 8-digit hex |
Internally Rhai strings are stored as UTF-8 just like Rust (they _are_ Rust `String`'s!), but there are major differences.
In Rhai a string is the same as an array of Unicode characters and can be directly indexed (unlike Rust). In Rhai a string is the same as an array of Unicode characters and can be directly indexed (unlike Rust).
This is similar to most other languages where strings are internally represented not as UTF-8 but as arrays of multi-byte This is similar to most other languages where strings are internally represented not as UTF-8 but as arrays of multi-byte
Unicode characters. Unicode characters.

View File

@ -978,7 +978,10 @@ impl<'a> TokenIterator<'a> {
} }
// \{enclosing_char} - escaped // \{enclosing_char} - escaped
ch if enclosing_char == ch && !escape.is_empty() => result.push(ch), ch if enclosing_char == ch && !escape.is_empty() => {
escape.clear();
result.push(ch)
}
// Close wrapper // Close wrapper
ch if enclosing_char == ch && escape.is_empty() => break, ch if enclosing_char == ch && escape.is_empty() => break,

View File

@ -5,6 +5,8 @@ fn test_chars() -> Result<(), EvalAltResult> {
let engine = Engine::new(); let engine = Engine::new();
assert_eq!(engine.eval::<char>("'y'")?, 'y'); assert_eq!(engine.eval::<char>("'y'")?, 'y');
assert_eq!(engine.eval::<char>(r"'\''")?, '\'');
assert_eq!(engine.eval::<char>(r#"'"'"#)?, '"');
assert_eq!(engine.eval::<char>("'\\u2764'")?, '❤'); assert_eq!(engine.eval::<char>("'\\u2764'")?, '❤');
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]

View File

@ -12,6 +12,7 @@ fn test_string() -> Result<(), EvalAltResult> {
engine.eval::<String>(r#""Test string: \x58""#)?, engine.eval::<String>(r#""Test string: \x58""#)?,
"Test string: X" "Test string: X"
); );
assert_eq!(engine.eval::<String>(r#""\"hello\"""#)?, r#""hello""#);
assert_eq!(engine.eval::<String>(r#""foo" + "bar""#)?, "foobar"); assert_eq!(engine.eval::<String>(r#""foo" + "bar""#)?, "foobar");