summaryrefslogtreecommitdiff
path: root/src/tokens/packed_binary_literal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tokens/packed_binary_literal.rs')
-rw-r--r--src/tokens/packed_binary_literal.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/tokens/packed_binary_literal.rs b/src/tokens/packed_binary_literal.rs
new file mode 100644
index 0000000..1252398
--- /dev/null
+++ b/src/tokens/packed_binary_literal.rs
@@ -0,0 +1,60 @@
+use crate::*;
+
+
+pub struct PackedBinaryLiteral {
+ pub value: usize,
+ pub fields: Vec<BitField>,
+ pub errors: Vec<PackedBinaryLiteralParseError>,
+}
+
+impl PackedBinaryLiteral {
+ pub fn from_str(string: &str, parent: &Tokeniser) -> Self {
+ parse_packed_binary_literal(string, parent)
+ }
+}
+
+pub struct BitField {
+ pub name: char,
+ pub source: SourceSpan,
+ /// Length of field in bits
+ pub bits: usize,
+ /// Distance to left-shift field in value
+ pub shift: usize,
+}
+
+pub struct PackedBinaryLiteralParseError {
+ pub source: SourceSpan,
+ pub variant: PackedBinaryLiteralParseErrorVariant,
+}
+
+pub enum PackedBinaryLiteralParseErrorVariant {
+ DuplicateFieldName(char),
+ InvalidCharacter(char),
+}
+
+
+impl std::fmt::Display for PackedBinaryLiteral {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ if self.value == 0 {
+ write!(f, "0")?;
+ } else {
+ let bitcount = (self.value.ilog2() + 1) as usize;
+ 'bit: for i in (0..bitcount).rev() {
+ if (i+1) % 4 == 0 {
+ write!(f, "_")?;
+ }
+ for field in &self.fields {
+ if i <= field.bits + field.shift - 1 && i >= field.shift {
+ write!(f, "{}", field.name)?;
+ continue 'bit;
+ }
+ }
+ match (self.value >> i) & 1 {
+ 0 => write!(f, "0")?,
+ _ => write!(f, "1")?,
+ }
+ }
+ }
+ return Ok(());
+ }
+}