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 = Vec::new(); let mut errors: Vec = 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 } }