cairo_lang_syntax_codegen/
spec.rs1#[derive(Clone)]
3pub struct Node {
4 pub name: String,
5 pub kind: NodeKind,
6}
7
8#[derive(Clone)]
10pub enum Variants {
11 List(Vec<Variant>),
13 AllTokens,
15}
16#[derive(Clone)]
17pub enum NodeKind {
18 Enum { variants: Variants, missing_variant: Option<Variant> },
19 Struct { members: Vec<Member> },
20 Terminal { is_keyword: bool, members: Vec<Member> },
21 List { element_type: String },
22 SeparatedList { element_type: String, separator_type: String },
23 Token { is_keyword: bool },
24}
25#[derive(Clone)]
26pub struct Member {
27 pub name: String,
28 pub kind: String,
29 pub key: bool,
32}
33#[derive(Clone)]
34pub struct Variant {
35 pub name: String,
36 pub kind: String,
37}
38
39pub struct StructBuilder {
43 name: String,
44 members: Vec<Member>,
45 is_terminal: bool,
46 is_keyword: bool,
47}
48impl StructBuilder {
49 pub fn new(name: &str) -> Self {
50 Self { name: name.into(), members: Vec::new(), is_terminal: false, is_keyword: false }
51 }
52 pub fn new_terminal(name: &str, is_keyword: bool) -> Self {
53 Self { name: name.into(), members: Vec::new(), is_terminal: true, is_keyword }
54 }
55 pub fn node(mut self, field: &str, kind: &str) -> StructBuilder {
56 self.members.push(Member { name: field.into(), kind: kind.into(), key: false });
57 self
58 }
59 pub fn key_node(mut self, field: &str, kind: &str) -> StructBuilder {
60 self.members.push(Member { name: field.into(), kind: kind.into(), key: true });
61 self
62 }
63 pub fn build(self) -> Node {
64 Node {
65 name: self.name,
66 kind: if self.is_terminal {
67 NodeKind::Terminal { is_keyword: self.is_keyword, members: self.members }
68 } else {
69 NodeKind::Struct { members: self.members }
70 },
71 }
72 }
73}
74pub struct EnumBuilder {
76 name: String,
77 variants: Vec<Variant>,
78 missing_variant: Option<Variant>,
79}
80impl EnumBuilder {
81 pub fn new(name: &str) -> Self {
82 Self { name: name.into(), variants: Vec::new(), missing_variant: None }
83 }
84 pub fn missing(mut self, name: &str) -> EnumBuilder {
85 let kind_name = self.name.clone() + name;
86 self.missing_variant = Some(Variant { name: name.to_string(), kind: kind_name });
87 self
88 }
89 pub fn node(self, name: &str) -> EnumBuilder {
90 let kind_name = self.name.clone() + name;
91 self.node_with_explicit_kind(name, &kind_name)
92 }
93 pub fn node_with_explicit_kind(mut self, name: &str, kind: &str) -> EnumBuilder {
94 self.variants.push(Variant { name: name.to_string(), kind: kind.to_string() });
95 self
96 }
97 pub fn build(mut self) -> Node {
98 if let Some(member) = &self.missing_variant {
99 self.variants.push(member.clone());
100 }
101 Node {
102 name: self.name,
103 kind: NodeKind::Enum {
104 variants: Variants::List(self.variants),
105 missing_variant: self.missing_variant,
106 },
107 }
108 }
109}
110
111#[derive(Default)]
113pub struct NodesAggregator {
114 nodes: Vec<Node>,
115}
116impl NodesAggregator {
117 pub fn get(self) -> Vec<Node> {
119 self.nodes
120 }
121
122 pub fn add_struct(mut self, builder: StructBuilder) -> Self {
124 self.nodes.push(builder.build());
125 self
126 }
127
128 pub fn add_enum(mut self, builder: EnumBuilder) -> Self {
130 self.nodes.push(builder.build());
131 self
132 }
133
134 pub fn add_list(mut self, name: &str, element_type: &str) -> Self {
136 self.nodes.push(Node {
137 name: name.into(),
138 kind: NodeKind::List { element_type: element_type.into() },
139 });
140 self
141 }
142
143 pub fn add_separated_list(
145 mut self,
146 name: &str,
147 element_type: &str,
148 separator_type: &str,
149 ) -> Self {
150 self.nodes.push(Node {
151 name: name.into(),
152 kind: NodeKind::SeparatedList {
153 element_type: element_type.into(),
154 separator_type: separator_type.into(),
155 },
156 });
157 self
158 }
159
160 pub fn add_token(mut self, pure_name: &str) -> Self {
162 self.nodes.push(Node {
163 name: format!("Token{pure_name}"),
164 kind: NodeKind::Token { is_keyword: false },
165 });
166 self
167 }
168
169 pub fn add_keyword_token(mut self, pure_name: &str) -> Self {
171 self.nodes.push(Node {
172 name: format!("Token{pure_name}"),
173 kind: NodeKind::Token { is_keyword: true },
174 });
175 self
176 }
177
178 pub fn add_terminal(self, pure_name: &str, is_keyword: bool) -> Self {
180 self.add_struct(
181 StructBuilder::new_terminal(format!("Terminal{pure_name}").as_str(), is_keyword)
182 .node("leading_trivia", "Trivia")
183 .node("token", format!("Token{pure_name}").as_str())
184 .node("trailing_trivia", "Trivia"),
185 )
186 }
187
188 pub fn add_keyword_token_and_terminal(self, pure_name: &str) -> Self {
191 self.add_keyword_token(pure_name).add_terminal(pure_name, true)
192 }
193
194 pub fn add_token_and_terminal(self, pure_name: &str) -> Self {
197 self.add_token(pure_name).add_terminal(pure_name, false)
198 }
199
200 pub fn add_option(self, name: &str) -> Self {
208 self.add_enum(
209 EnumBuilder::new(format!("Option{name}").as_str())
210 .node("Empty")
211 .node_with_explicit_kind(name, name),
212 )
213 .add_struct(StructBuilder::new(format!("Option{name}Empty").as_str()))
214 }
215
216 pub fn add_all_tokens_enum(mut self, name: &str) -> Self {
218 self.nodes.push(Node {
219 name: name.into(),
220 kind: NodeKind::Enum { variants: Variants::AllTokens, missing_variant: None },
221 });
222 self
223 }
224}