1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::AST;
use std::{char, iter::Iterator, str};

pub fn string_refine(h: &str, text: &str) -> AST {
    let data = text.to_string();
    return match h {
        "" => AST::String(data),
        _ => AST::StringLiteral { handler: h.to_string(), data },
    };
}

pub fn unescape(s: &str) -> String {
    let mut chars = s.chars().enumerate();
    let mut res = String::with_capacity(s.len());
    while let Some((_, c)) = chars.next() {
        // when in a single quote, no escapes are possible
        if c == '\\' {
            match chars.next() {
                None => ' ',
                Some((_, c2)) => {
                    res.push(match c2 {
                        'a' => '\u{07}',
                        'b' => '\u{08}',
                        'v' => '\u{0B}',
                        'f' => '\u{0C}',
                        'n' => '\n',
                        'r' => '\r',
                        't' => '\t',
                        'e' | 'E' => '\u{1B}',
                        '\\' => '\\',
                        '\'' => '\'',
                        '"' => '"',
                        '$' => '$',
                        '`' => '`',
                        ' ' => ' ',
                        'u' => match parse_unicode(&mut chars) {
                            Ok(c3) => c3,
                            Err(_) => ' ',
                        },
                        _ => ' ',
                    });
                    continue;
                }
            };
        }
        res.push(c);
    }
    return res;
}

#[rustfmt::skip]
pub fn parse_unicode<I>(chars: &mut I) -> Result<char, String>
where
    I: Iterator<Item = (usize, char)>,
{
    match chars.next() {
        Some((_, '{')) => {}
        _ => {
            return Err("expected '{{' character in unicode escape".to_string());
        }
    }

    let unicode_seq: String = chars
        .take_while(|&(_, c)| c != '}')
        .map(|(_, c)| c)
        .collect();

    u32::from_str_radix(&unicode_seq, 16)
        .map_err(|e| format!("could not parse {} as u32 hex: {}", unicode_seq, e))
        .and_then(|u| char::from_u32(u).ok_or_else(|| format!("could not parse {} as a unicode char", u)))
}