tangled
alpha
login
or
join now
tjh.dev
/
um32
1
fork
atom
Implementation of the UM-32 "Universal Machine" as described by the
Cult of the Bound Variable
1
fork
atom
overview
issues
pulls
pipelines
move `unescape_str` into `parse` module
tjh
1 year ago
3ed9dee0
16c843c7
+45
-62
3 changed files
expand all
collapse all
unified
split
src
asm
parse.rs
lib.rs
str.rs
+45
-2
src/asm/parse.rs
···
1
1
use super::Token;
2
2
use crate::Register;
3
3
use logos::{Logos, Source};
4
4
-
use std::{borrow::Cow, collections::HashMap, iter::Peekable, ops::Range};
4
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
683
-
let unescaped = crate::str::unescape_str(value).map_err(|_| Error::eof())?;
683
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
697
+
698
698
+
#[derive(Debug)]
699
699
+
#[allow(unused)]
700
700
+
pub struct InvalidCharacterEscape(pub char, pub usize);
701
701
+
702
702
+
pub fn unescape_str(s: &str) -> Result<Cow<str>, InvalidCharacterEscape> {
703
703
+
fn escape_inner(c: &str, i: &mut CharIndices<'_>) -> Result<String, InvalidCharacterEscape> {
704
704
+
let mut buffer = c.to_owned();
705
705
+
let mut in_escape = true;
706
706
+
707
707
+
for (index, c) in i {
708
708
+
match (in_escape, c) {
709
709
+
(false, '\\') => {
710
710
+
in_escape = true;
711
711
+
continue;
712
712
+
}
713
713
+
(false, c) => buffer.push(c),
714
714
+
(true, '\\') => buffer.push('\\'),
715
715
+
(true, 'n') => buffer.push('\n'),
716
716
+
(true, '0') => buffer.push('\0'),
717
717
+
(true, '"') => buffer.push('"'),
718
718
+
(true, '\'') => buffer.push('\''),
719
719
+
(true, 'r') => buffer.push('\r'),
720
720
+
(true, 't') => buffer.push('\t'),
721
721
+
(true, c) => Err(InvalidCharacterEscape(c, index))?,
722
722
+
}
723
723
+
724
724
+
in_escape = false;
725
725
+
}
726
726
+
727
727
+
Ok(buffer)
728
728
+
}
729
729
+
730
730
+
let mut char_indicies = s.char_indices();
731
731
+
for (index, c) in &mut char_indicies {
732
732
+
let scanned = &s[..index];
733
733
+
if c == '\\' {
734
734
+
return Ok(Cow::Owned(escape_inner(scanned, &mut char_indicies)?));
735
735
+
}
736
736
+
}
737
737
+
738
738
+
Ok(Cow::Borrowed(s))
739
739
+
}
-1
src/lib.rs
···
4
4
pub mod asm;
5
5
pub mod ops;
6
6
pub mod reg;
7
7
-
pub mod str;
8
7
9
8
use ops::Operation;
10
9
use reg::Register;
-59
src/str.rs
···
1
1
-
use std::{borrow::Cow, str::CharIndices};
2
2
-
3
3
-
#[derive(Debug)]
4
4
-
pub struct InvalidCharacterEscape(pub char, pub usize);
5
5
-
6
6
-
pub fn unescape_str(s: &str) -> Result<Cow<str>, InvalidCharacterEscape> {
7
7
-
fn escape_inner(c: &str, i: &mut CharIndices<'_>) -> Result<String, InvalidCharacterEscape> {
8
8
-
let mut buffer = c.to_owned();
9
9
-
let mut in_escape = true;
10
10
-
11
11
-
for (index, c) in i {
12
12
-
match (in_escape, c) {
13
13
-
(false, '\\') => {
14
14
-
in_escape = true;
15
15
-
continue;
16
16
-
}
17
17
-
(false, c) => buffer.push(c),
18
18
-
(true, '\\') => buffer.push('\\'),
19
19
-
(true, 'n') => buffer.push('\n'),
20
20
-
(true, '0') => buffer.push('\0'),
21
21
-
(true, '"') => buffer.push('"'),
22
22
-
(true, '\'') => buffer.push('\''),
23
23
-
(true, 'r') => buffer.push('\r'),
24
24
-
(true, 't') => buffer.push('\t'),
25
25
-
(true, c) => Err(InvalidCharacterEscape(c, index))?,
26
26
-
}
27
27
-
28
28
-
in_escape = false;
29
29
-
}
30
30
-
31
31
-
Ok(buffer)
32
32
-
}
33
33
-
34
34
-
let mut char_indicies = s.char_indices();
35
35
-
for (index, c) in &mut char_indicies {
36
36
-
let scanned = &s[..index];
37
37
-
if c == '\\' {
38
38
-
return Ok(Cow::Owned(escape_inner(scanned, &mut char_indicies)?));
39
39
-
}
40
40
-
}
41
41
-
42
42
-
Ok(Cow::Borrowed(s))
43
43
-
}
44
44
-
45
45
-
#[cfg(test)]
46
46
-
mod tests {
47
47
-
use std::borrow::Cow;
48
48
-
49
49
-
use super::unescape_str;
50
50
-
51
51
-
#[test]
52
52
-
fn no_unescapes() {
53
53
-
let s = "Hello, this string should have no characters that need unescaping.";
54
54
-
let u = unescape_str(s).unwrap();
55
55
-
56
56
-
assert!(matches!(u, Cow::Borrowed(_)));
57
57
-
assert_eq!(s, u);
58
58
-
}
59
59
-
}