blob: 18f8da743379b2049f25b08f04b161d193522166 (
plain) (
tree)
|
|
use crate::*;
/// t is a Tokeniser over the characters of the PBL, excluding the leading hash.
pub fn parse_packed_binary_literal(mut t: Tokeniser, source: SourceSpan) -> PackedBinaryLiteral {
use PackedBinaryLiteralParseError as ParseError;
use PackedBinaryLiteralParseErrorVariant as ParseErrorVar;
let mut value = 0;
let mut bits = 0;
let mut field_bits = 0;
let mut name = '\0';
let mut fields: Vec<BitField> = Vec::new();
let mut errors: Vec<ParseError> = Vec::new();
macro_rules! push_field {
() => {
if fields.iter().any(|f| f.name == name) {
let variant = ParseErrorVar::DuplicateFieldName(name);
errors.push(ParseError { source: t.get_source(), variant });
} else {
fields.push(BitField { name, source: t.get_source(), bits: field_bits, shift: 0 });
}
};
}
while let Some(c) = t.eat_char() {
// Ignore underscores.
if c == '_' {
t.mark.undo();
continue;
}
// Add a bit to the value;
value <<= 1;
bits += 1;
for field in &mut fields {
field.shift += 1;
}
// Extend the current field.
if c == name {
field_bits += 1;
continue;
}
// Commit the current field.
if field_bits > 0 {
t.mark_end_prev();
push_field!();
field_bits = 0;
name = '\0';
}
// Parse bit literals.
if c == '0' {
continue;
}
if c == '1' {
value |= 1;
continue;
}
t.mark_start_prev();
if c.is_alphabetic() {
name = c;
field_bits = 1;
continue;
} else {
let source = t.get_source();
let variant = ParseErrorVar::InvalidCharacter(c);
errors.push(ParseError { source, variant });
}
}
// Commit the final field.
for field in &mut fields {
field.shift += 1;
}
if field_bits > 0 {
push_field!();
}
PackedBinaryLiteral { source, bits, value, fields, errors }
}
|