blob: 9704fc454b47e81822ac8a8ba2712e92e14d6dc2 (
plain) (
blame)
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
72
73
74
75
76
77
78
79
80
|
use crate::*;
pub fn parse_packed_binary_literal(string: &str, parent: &Tokeniser) -> PackedBinaryLiteral {
use PackedBinaryLiteralParseError as ParseError;
use PackedBinaryLiteralParseErrorVariant as ParseErrorVar;
let mut value = 0;
let mut bits = 0;
let mut name = '\0';
let mut fields: Vec<BitField> = Vec::new();
let mut errors: Vec<ParseError> = Vec::new();
macro_rules! push_field {
($source:expr) => {
if fields.iter().any(|f| f.name == name) {
let variant = ParseErrorVar::DuplicateFieldName(name);
errors.push(ParseError { source: $source, variant });
} else {
fields.push(BitField { name, source: $source, bits, shift: 0 });
}
};
}
let mut t = Tokeniser::new_child(string, parent);
t.position.to_next_char(); // skip opening hash character
while let Some(c) = t.eat_char() {
// Ignore underscores.
if c == '_' {
t.prev_position = t.prev_prev_position;
continue;
}
// Add a bit to the value;
value <<= 1;
for field in &mut fields {
field.shift += 1;
}
// Extend the current field.
if c == name {
bits += 1;
continue;
}
// Commit the current field.
if bits > 0 {
push_field!(t.mark_prev_end_position());
bits = 0;
name = '\0';
}
// Parse bit literals.
if c == '0' {
continue;
}
if c == '1' {
value |= 1;
continue;
}
t.mark_prev_start_position();
if c.is_alphabetic() {
name = c;
bits = 1;
continue;
} else {
let source = t.mark_end_position();
errors.push(ParseError { source, variant: ParseErrorVar::InvalidCharacter(c) });
}
}
// Commit the final field.
if bits > 0 {
push_field!(t.mark_end_position());
}
PackedBinaryLiteral { value, fields, errors }
}
|