}
}
+ for (k, v) in headers
+ .file_attributes
+ .iter()
+ .flat_map(|map| map.0 .0.iter())
+ {
+ dictionary.attributes.insert(k.clone(), v.clone());
+ }
+
+ for attr_set in headers
+ .variable_attributes
+ .iter()
+ .flat_map(|record| record.0.iter())
+ {
+ if let Some((_, variable)) = dictionary
+ .variables
+ .get_full_mut2(&attr_set.long_var_name.0)
+ {
+ for (k, v) in attr_set.attributes.0.iter() {
+ variable.attributes.insert(k.clone(), v.clone());
+ }
+ } else {
+ warn(Error::TBD);
+ }
+ }
+
let metadata = Metadata::decode(&headers, warn);
Ok((dictionary, metadata))
}
Split,
}
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum DictClass {
- Ordinary,
- System,
- Scratch,
-}
-
-impl DictClass {
- pub fn must_leave(self) -> bool {
- self == DictClass::Scratch
- }
-}
-
-impl From<&Identifier> for DictClass {
- fn from(id: &Identifier) -> Self {
- if id.0.starts_with('$') {
- Self::System
- } else if id.0.starts_with('#') {
- Self::Scratch
- } else {
- Self::Ordinary
- }
- }
-}
-
#[derive(Clone, Debug)]
pub struct Variable {
pub name: Identifier,
pub alignment: Alignment,
pub leave: bool,
pub short_names: Vec<Identifier>,
- pub attributes: HashSet<ByIdentifier<Attribute>>,
+ pub attributes: HashMap<Identifier, Vec<String>>,
}
impl Variable {
pub fn new(name: Identifier, width: VarWidth) -> Self {
let var_type = VarType::from_width(width);
- let leave = DictClass::from(&name).must_leave();
+ let leave = name.class().must_leave();
Self {
name,
width,
alignment: Alignment::default_for_type(var_type),
leave,
short_names: Vec::new(),
- attributes: HashSet::new(),
+ attributes: HashMap::new(),
}
}
}
}
-#[derive(Clone, Debug)]
-pub struct Attribute {
- pub name: Identifier,
- pub values: Vec<String>,
-}
-
-impl HasIdentifier for Attribute {
- fn identifier(&self) -> &UniCase<String> {
- &self.name.0
- }
-}
-
#[derive(Clone, Debug)]
pub struct MultipleResponseSet {
pub name: Identifier,
use thiserror::Error as ThisError;
use unicase::UniCase;
-use crate::dictionary::DictClass;
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Class {
+ /// No distinguishing prefix.
+ Ordinary,
+
+ /// Starting with `$`.
+ System,
+
+ /// Starting with `#`.
+ Scratch,
+
+ /// Starting with `!`.
+ Macro,
+}
+
+impl Class {
+ pub fn must_leave(self) -> bool {
+ self == Self::Scratch
+ }
+}
+
+impl From<&Identifier> for Class {
+ fn from(id: &Identifier) -> Self {
+ if id.0.starts_with('$') {
+ Self::System
+ } else if id.0.starts_with('#') {
+ Self::Scratch
+ } else if id.0.starts_with('!') {
+ Self::Macro
+ } else {
+ Self::Ordinary
+ }
+ }
+}
pub trait IdentifierChar {
/// Returns true if `self` is an ASCII character that may be the first
pub fn new(s: impl Into<UniCase<String>>) -> Result<Self, Error> {
Self::from_encoding(s, UTF_8)
}
- pub fn from_encoding(s: impl Into<UniCase<String>>, encoding: &'static Encoding) -> Result<Identifier, Error> {
+
+ pub fn from_encoding(
+ s: impl Into<UniCase<String>>,
+ encoding: &'static Encoding,
+ ) -> Result<Identifier, Error> {
let s: UniCase<String> = s.into();
Self::is_plausible(&s)?;
let identifier = Identifier(s);
}
pub fn must_be_ordinary(self) -> Result<Self, Error> {
- match DictClass::from(&self) {
- DictClass::Ordinary => Ok(self),
+ match Class::from(&self) {
+ Class::Ordinary => Ok(self),
_ => {
let s = self.0.into_inner();
let first = s.chars().next().unwrap();
}
}
}
+
+ pub fn class(&self) -> Class {
+ self.into()
+ }
}
impl PartialEq<str> for Identifier {
}
#[derive(Clone, Debug)]
-pub struct VariableAttributeRecord(Vec<VarAttributeSet>);
+pub struct VariableAttributeRecord(pub Vec<VarAttributeSet>);
impl VariableAttributeRecord {
fn decode(source: &TextRecord, decoder: &Decoder) -> Self {