+45
-2
src/asm/parse.rs
+45
-2
src/asm/parse.rs
···
1
1
use super::Token;
2
2
use crate::Register;
3
3
use logos::{Logos, Source};
4
-
use std::{borrow::Cow, collections::HashMap, iter::Peekable, ops::Range};
4
+
use std::{borrow::Cow, collections::HashMap, iter::Peekable, ops::Range, str::CharIndices};
5
5
6
6
pub fn parse(_unit: impl std::fmt::Display, source: &str) -> Result<ParsedProgram, Error> {
7
7
Parser::new(source).parse()
···
680
680
{
681
681
match tokens.next() {
682
682
Some((Token::String(value), span)) => {
683
-
let unescaped = crate::str::unescape_str(value).map_err(|_| Error::eof())?;
683
+
let unescaped = unescape_str(value).map_err(|_| Error::eof())?;
684
684
Ok((unescaped, span))
685
685
}
686
686
Some((token, span)) => Err(Error::new(
···
694
694
fn merge_spans(start: &Range<usize>, end: &Range<usize>) -> Range<usize> {
695
695
start.start..end.end
696
696
}
697
+
698
+
#[derive(Debug)]
699
+
#[allow(unused)]
700
+
pub struct InvalidCharacterEscape(pub char, pub usize);
701
+
702
+
pub fn unescape_str(s: &str) -> Result<Cow<str>, InvalidCharacterEscape> {
703
+
fn escape_inner(c: &str, i: &mut CharIndices<'_>) -> Result<String, InvalidCharacterEscape> {
704
+
let mut buffer = c.to_owned();
705
+
let mut in_escape = true;
706
+
707
+
for (index, c) in i {
708
+
match (in_escape, c) {
709
+
(false, '\\') => {
710
+
in_escape = true;
711
+
continue;
712
+
}
713
+
(false, c) => buffer.push(c),
714
+
(true, '\\') => buffer.push('\\'),
715
+
(true, 'n') => buffer.push('\n'),
716
+
(true, '0') => buffer.push('\0'),
717
+
(true, '"') => buffer.push('"'),
718
+
(true, '\'') => buffer.push('\''),
719
+
(true, 'r') => buffer.push('\r'),
720
+
(true, 't') => buffer.push('\t'),
721
+
(true, c) => Err(InvalidCharacterEscape(c, index))?,
722
+
}
723
+
724
+
in_escape = false;
725
+
}
726
+
727
+
Ok(buffer)
728
+
}
729
+
730
+
let mut char_indicies = s.char_indices();
731
+
for (index, c) in &mut char_indicies {
732
+
let scanned = &s[..index];
733
+
if c == '\\' {
734
+
return Ok(Cow::Owned(escape_inner(scanned, &mut char_indicies)?));
735
+
}
736
+
}
737
+
738
+
Ok(Cow::Borrowed(s))
739
+
}
-1
src/lib.rs
-1
src/lib.rs
-59
src/str.rs
-59
src/str.rs
···
1
-
use std::{borrow::Cow, str::CharIndices};
2
-
3
-
#[derive(Debug)]
4
-
pub struct InvalidCharacterEscape(pub char, pub usize);
5
-
6
-
pub fn unescape_str(s: &str) -> Result<Cow<str>, InvalidCharacterEscape> {
7
-
fn escape_inner(c: &str, i: &mut CharIndices<'_>) -> Result<String, InvalidCharacterEscape> {
8
-
let mut buffer = c.to_owned();
9
-
let mut in_escape = true;
10
-
11
-
for (index, c) in i {
12
-
match (in_escape, c) {
13
-
(false, '\\') => {
14
-
in_escape = true;
15
-
continue;
16
-
}
17
-
(false, c) => buffer.push(c),
18
-
(true, '\\') => buffer.push('\\'),
19
-
(true, 'n') => buffer.push('\n'),
20
-
(true, '0') => buffer.push('\0'),
21
-
(true, '"') => buffer.push('"'),
22
-
(true, '\'') => buffer.push('\''),
23
-
(true, 'r') => buffer.push('\r'),
24
-
(true, 't') => buffer.push('\t'),
25
-
(true, c) => Err(InvalidCharacterEscape(c, index))?,
26
-
}
27
-
28
-
in_escape = false;
29
-
}
30
-
31
-
Ok(buffer)
32
-
}
33
-
34
-
let mut char_indicies = s.char_indices();
35
-
for (index, c) in &mut char_indicies {
36
-
let scanned = &s[..index];
37
-
if c == '\\' {
38
-
return Ok(Cow::Owned(escape_inner(scanned, &mut char_indicies)?));
39
-
}
40
-
}
41
-
42
-
Ok(Cow::Borrowed(s))
43
-
}
44
-
45
-
#[cfg(test)]
46
-
mod tests {
47
-
use std::borrow::Cow;
48
-
49
-
use super::unescape_str;
50
-
51
-
#[test]
52
-
fn no_unescapes() {
53
-
let s = "Hello, this string should have no characters that need unescaping.";
54
-
let u = unescape_str(s).unwrap();
55
-
56
-
assert!(matches!(u, Cow::Borrowed(_)));
57
-
assert_eq!(s, u);
58
-
}
59
-
}