microcad_lang/syntax/
attribute.rs1use crate::{src_ref::*, syntax::*};
7use derive_more::{Deref, DerefMut};
8
9#[derive(Debug, Clone)]
11pub enum AttributeCommand {
12 Call(Option<Identifier>, Option<ArgumentList>),
14 Expression(Expression),
16}
17
18impl std::fmt::Display for AttributeCommand {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 match &self {
21 AttributeCommand::Call(id, argument_list) => {
22 write!(
23 f,
24 "{id}{argument_list}",
25 id = match id {
26 Some(id) => format!("{id}"),
27 None => String::new(),
28 },
29 argument_list = match argument_list {
30 Some(argument_list) => format!("({argument_list})"),
31 None => String::new(),
32 }
33 )
34 }
35 AttributeCommand::Expression(expression) => write!(f, "{expression}"),
36 }
37 }
38}
39
40impl SrcReferrer for AttributeCommand {
41 fn src_ref(&self) -> SrcRef {
42 match &self {
43 AttributeCommand::Call(identifier, argument_list) => {
44 match (identifier, argument_list) {
45 (None, None) => unreachable!("Invalid AttributeCommand::Call"),
46 (None, Some(arguments)) => arguments.src_ref(),
47 (Some(identifier), None) => identifier.src_ref(),
48 (Some(identifier), Some(arguments)) => SrcRef::merge(identifier, arguments),
49 }
50 }
51 AttributeCommand::Expression(expression) => expression.src_ref(),
52 }
53 }
54}
55
56#[derive(Debug, Clone)]
58pub struct Attribute {
59 pub id: Identifier,
61 pub commands: Vec<AttributeCommand>,
63 pub is_inner: bool,
65 pub src_ref: SrcRef,
67}
68
69impl Attribute {
70 pub fn single_command(&self) -> Option<&AttributeCommand> {
72 match self.commands.len() {
73 1 => self.commands.first(),
74 _ => None,
75 }
76 }
77}
78
79impl TreeDisplay for Attribute {
80 fn tree_print(&self, f: &mut std::fmt::Formatter, depth: TreeState) -> std::fmt::Result {
81 writeln!(f, "{:depth$}Attribute: {self}", "")
82 }
83}
84
85impl std::fmt::Display for Attribute {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 match self.is_inner {
88 true => write!(f, "#![")?,
89 false => write!(f, "#[")?,
90 }
91 match self.commands.is_empty() {
92 true => write!(f, "{}", self.id)?,
93 false => write!(
94 f,
95 "{} = {}",
96 self.id,
97 self.commands
98 .iter()
99 .map(|command| command.to_string())
100 .collect::<Vec<_>>()
101 .join(", ")
102 )?,
103 }
104 writeln!(f, "]")
105 }
106}
107
108impl SrcReferrer for Attribute {
109 fn src_ref(&self) -> crate::src_ref::SrcRef {
110 self.src_ref.clone()
111 }
112}
113
114#[derive(Debug, Clone, Default, Deref, DerefMut)]
116pub struct AttributeList(Vec<Attribute>);
117
118impl std::fmt::Display for AttributeList {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 self.0.iter().try_for_each(|attr| writeln!(f, "{attr}"))
121 }
122}
123
124impl SrcReferrer for AttributeList {
125 fn src_ref(&self) -> SrcRef {
126 if self.0.is_empty() {
127 SrcRef(None)
128 } else {
129 SrcRef::merge(
130 &self.0.first().expect("One element").src_ref(),
131 &self.0.last().expect("Second element").src_ref(),
132 )
133 }
134 }
135}