1use erl_tokenize::tokens::{AtomToken, IntegerToken, StringToken, SymbolToken, VariableToken};
2use erl_tokenize::values::Symbol;
3use erl_tokenize::{LexicalToken, Position, PositionRange};
4
5use self::parts::RecordFieldDecl;
6use crate::cst::clauses::{FunDeclClause, SpecClause};
7use crate::cst::commons::parts::{Args, Clauses, ModulePrefix, NameAndArity};
8use crate::cst::commons::{ProperList, Tuple};
9use crate::cst::Type;
10use crate::traits::{Parse, TokenRead};
11use crate::{Parser, Result};
12
13pub mod parts;
14
15#[derive(Debug, Clone)]
17pub struct ModuleAttr {
18 pub _hyphen: SymbolToken,
19 pub _module: AtomToken,
20 pub _open: SymbolToken,
21 pub module_name: AtomToken,
22 pub _close: SymbolToken,
23 pub _dot: SymbolToken,
24}
25impl Parse for ModuleAttr {
26 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
27 where
28 T: TokenRead,
29 {
30 let this = ModuleAttr {
31 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
32 _module: track!(parser.expect("module"))?,
33 _open: track!(parser.expect(&Symbol::OpenParen))?,
34 module_name: track!(parser.parse())?,
35 _close: track!(parser.expect(&Symbol::CloseParen))?,
36 _dot: track!(parser.expect(&Symbol::Dot))?,
37 };
38 {
39 let module = &this.module_name;
40 let reader = parser.reader_mut();
41 let module_string = StringToken::from_value(module.value(), module.start_position());
42 reader.define_macro("MODULE", vec![module.clone().into()]);
43 reader.define_macro("MODULE_STRING", vec![module_string.into()]);
44 }
45 Ok(this)
46 }
47}
48impl PositionRange for ModuleAttr {
49 fn start_position(&self) -> Position {
50 self._hyphen.start_position()
51 }
52 fn end_position(&self) -> Position {
53 self._dot.end_position()
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct ExportAttr {
60 pub _hyphen: SymbolToken,
61 pub _export: AtomToken,
62 pub _open: SymbolToken,
63 pub exports: ProperList<NameAndArity>,
64 pub _close: SymbolToken,
65 pub _dot: SymbolToken,
66}
67impl Parse for ExportAttr {
68 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
69 where
70 T: TokenRead,
71 {
72 Ok(ExportAttr {
73 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
74 _export: track!(parser.expect("export"))?,
75 _open: track!(parser.expect(&Symbol::OpenParen))?,
76 exports: track!(parser.parse())?,
77 _close: track!(parser.expect(&Symbol::CloseParen))?,
78 _dot: track!(parser.expect(&Symbol::Dot))?,
79 })
80 }
81}
82impl PositionRange for ExportAttr {
83 fn start_position(&self) -> Position {
84 self._hyphen.start_position()
85 }
86 fn end_position(&self) -> Position {
87 self._dot.end_position()
88 }
89}
90
91#[derive(Debug, Clone)]
93pub struct ExportTypeAttr {
94 pub _hyphen: SymbolToken,
95 pub _export_type: AtomToken,
96 pub _open: SymbolToken,
97 pub exports: ProperList<NameAndArity>,
98 pub _close: SymbolToken,
99 pub _dot: SymbolToken,
100}
101impl Parse for ExportTypeAttr {
102 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
103 where
104 T: TokenRead,
105 {
106 Ok(ExportTypeAttr {
107 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
108 _export_type: track!(parser.expect("export_type"))?,
109 _open: track!(parser.expect(&Symbol::OpenParen))?,
110 exports: track!(parser.parse())?,
111 _close: track!(parser.expect(&Symbol::CloseParen))?,
112 _dot: track!(parser.expect(&Symbol::Dot))?,
113 })
114 }
115}
116impl PositionRange for ExportTypeAttr {
117 fn start_position(&self) -> Position {
118 self._hyphen.start_position()
119 }
120 fn end_position(&self) -> Position {
121 self._dot.end_position()
122 }
123}
124
125#[derive(Debug, Clone)]
127pub struct ImportAttr {
128 pub _hyphen: SymbolToken,
129 pub _import: AtomToken,
130 pub _open: SymbolToken,
131 pub module_name: AtomToken,
132 pub _comma: SymbolToken,
133 pub imports: ProperList<NameAndArity>,
134 pub _close: SymbolToken,
135 pub _dot: SymbolToken,
136}
137impl Parse for ImportAttr {
138 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
139 where
140 T: TokenRead,
141 {
142 Ok(ImportAttr {
143 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
144 _import: track!(parser.expect("import"))?,
145 _open: track!(parser.expect(&Symbol::OpenParen))?,
146 module_name: track!(parser.parse())?,
147 _comma: track!(parser.expect(&Symbol::Comma))?,
148 imports: track!(parser.parse())?,
149 _close: track!(parser.expect(&Symbol::CloseParen))?,
150 _dot: track!(parser.expect(&Symbol::Dot))?,
151 })
152 }
153}
154impl PositionRange for ImportAttr {
155 fn start_position(&self) -> Position {
156 self._hyphen.start_position()
157 }
158 fn end_position(&self) -> Position {
159 self._dot.end_position()
160 }
161}
162
163#[derive(Debug, Clone)]
165pub struct FileAttr {
166 pub _hyphen: SymbolToken,
167 pub _file: AtomToken,
168 pub _open: SymbolToken,
169 pub file_name: StringToken,
170 pub _comma: SymbolToken,
171 pub line_num: IntegerToken,
172 pub _close: SymbolToken,
173 pub _dot: SymbolToken,
174}
175impl Parse for FileAttr {
176 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
177 where
178 T: TokenRead,
179 {
180 Ok(FileAttr {
181 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
182 _file: track!(parser.expect("file"))?,
183 _open: track!(parser.expect(&Symbol::OpenParen))?,
184 file_name: track!(parser.parse())?,
185 _comma: track!(parser.expect(&Symbol::Comma))?,
186 line_num: track!(parser.parse())?,
187 _close: track!(parser.expect(&Symbol::CloseParen))?,
188 _dot: track!(parser.expect(&Symbol::Dot))?,
189 })
190 }
191}
192impl PositionRange for FileAttr {
193 fn start_position(&self) -> Position {
194 self._hyphen.start_position()
195 }
196 fn end_position(&self) -> Position {
197 self._dot.end_position()
198 }
199}
200
201#[derive(Debug, Clone)]
203pub struct WildAttr {
204 pub _hyphen: SymbolToken,
205 pub attr_name: AtomToken,
206 pub _open: SymbolToken,
207 pub attr_value: Vec<LexicalToken>,
208 pub _close: SymbolToken,
209 pub _dot: SymbolToken,
210}
211impl Parse for WildAttr {
212 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
213 where
214 T: TokenRead,
215 {
216 let _hyphen = track!(parser.expect(&Symbol::Hyphen))?;
217 let attr_name = track!(parser.parse())?;
218 let _open = track!(parser.expect(&Symbol::OpenParen))?;
219
220 let count = parser.peek(|parser| {
221 for i in 0.. {
222 let v = track!(parser.parse::<LexicalToken>())?
223 .as_symbol_token()
224 .map(SymbolToken::value);
225 if v == Some(Symbol::Dot) {
226 use std::cmp;
227 return Ok(cmp::max(i, 1) - 1);
228 }
229 }
230 unreachable!()
231 });
232 let attr_value = (0..track!(count)?)
233 .map(|_| parser.parse().expect("Never fails"))
234 .collect();
235 Ok(WildAttr {
236 _hyphen,
237 attr_name,
238 _open,
239 attr_value,
240 _close: track!(parser.expect(&Symbol::CloseParen))?,
241 _dot: track!(parser.expect(&Symbol::Dot))?,
242 })
243 }
244}
245impl PositionRange for WildAttr {
246 fn start_position(&self) -> Position {
247 self._hyphen.start_position()
248 }
249 fn end_position(&self) -> Position {
250 self._dot.end_position()
251 }
252}
253
254#[derive(Debug, Clone)]
256pub struct FunSpec {
257 pub _hyphen: SymbolToken,
258 pub _spec: AtomToken,
259 pub module: Option<ModulePrefix<AtomToken>>,
260 pub fun_name: AtomToken,
261 pub clauses: Clauses<SpecClause>,
262 pub _dot: SymbolToken,
263}
264impl Parse for FunSpec {
265 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
266 where
267 T: TokenRead,
268 {
269 Ok(FunSpec {
270 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
271 _spec: track!(parser.expect("spec"))?,
272 module: track!(parser.parse())?,
273 fun_name: track!(parser.parse())?,
274 clauses: track!(parser.parse())?,
275 _dot: track!(parser.expect(&Symbol::Dot))?,
276 })
277 }
278}
279impl PositionRange for FunSpec {
280 fn start_position(&self) -> Position {
281 self._hyphen.start_position()
282 }
283 fn end_position(&self) -> Position {
284 self._dot.end_position()
285 }
286}
287
288#[derive(Debug, Clone)]
290pub struct CallbackSpec {
291 pub _hyphen: SymbolToken,
292 pub _spec: AtomToken,
293 pub callback_name: AtomToken,
294 pub clauses: Clauses<SpecClause>,
295 pub _dot: SymbolToken,
296}
297impl Parse for CallbackSpec {
298 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
299 where
300 T: TokenRead,
301 {
302 Ok(CallbackSpec {
303 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
304 _spec: track!(parser.expect("callback"))?,
305 callback_name: track!(parser.parse())?,
306 clauses: track!(parser.parse())?,
307 _dot: track!(parser.expect(&Symbol::Dot))?,
308 })
309 }
310}
311impl PositionRange for CallbackSpec {
312 fn start_position(&self) -> Position {
313 self._hyphen.start_position()
314 }
315 fn end_position(&self) -> Position {
316 self._dot.end_position()
317 }
318}
319
320#[derive(Debug, Clone)]
322pub struct FunDecl {
323 pub clauses: Clauses<FunDeclClause>,
324 pub _dot: SymbolToken,
325}
326impl Parse for FunDecl {
327 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
328 where
329 T: TokenRead,
330 {
331 Ok(FunDecl {
332 clauses: track!(parser.parse())?,
333 _dot: track!(parser.expect(&Symbol::Dot))?,
334 })
335 }
336}
337impl PositionRange for FunDecl {
338 fn start_position(&self) -> Position {
339 self.clauses.start_position()
340 }
341 fn end_position(&self) -> Position {
342 self._dot.end_position()
343 }
344}
345
346#[derive(Debug, Clone)]
348pub struct RecordDecl {
349 pub _hyphen: SymbolToken,
350 pub _record: AtomToken,
351 pub _open: SymbolToken,
352 pub record_name: AtomToken,
353 pub _comma: SymbolToken,
354 pub fields: Tuple<RecordFieldDecl>,
355 pub _close: SymbolToken,
356 pub _dot: SymbolToken,
357}
358impl Parse for RecordDecl {
359 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
360 where
361 T: TokenRead,
362 {
363 Ok(RecordDecl {
364 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
365 _record: track!(parser.expect("record"))?,
366 _open: track!(parser.expect(&Symbol::OpenParen))?,
367 record_name: track!(parser.parse())?,
368 _comma: track!(parser.expect(&Symbol::Comma))?,
369 fields: track!(parser.parse())?,
370 _close: track!(parser.expect(&Symbol::CloseParen))?,
371 _dot: track!(parser.expect(&Symbol::Dot))?,
372 })
373 }
374}
375impl PositionRange for RecordDecl {
376 fn start_position(&self) -> Position {
377 self._hyphen.start_position()
378 }
379 fn end_position(&self) -> Position {
380 self._dot.end_position()
381 }
382}
383
384#[derive(Debug, Clone)]
386pub struct TypeDecl {
387 pub _hyphen: SymbolToken,
388 pub type_kind: AtomToken,
389 pub type_name: AtomToken,
390 pub variables: Args<VariableToken>,
391 pub _double_colon: SymbolToken,
392 pub ty: Type,
393 pub _dot: SymbolToken,
394}
395impl Parse for TypeDecl {
396 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
397 where
398 T: TokenRead,
399 {
400 Ok(TypeDecl {
401 _hyphen: track!(parser.expect(&Symbol::Hyphen))?,
402 type_kind: track!(parser.expect_any(&["type", "opaque"]))?,
403 type_name: track!(parser.parse())?,
404 variables: track!(parser.parse())?,
405 _double_colon: track!(parser.expect(&Symbol::DoubleColon))?,
406 ty: track!(parser.parse())?,
407 _dot: track!(parser.expect(&Symbol::Dot))?,
408 })
409 }
410}
411impl PositionRange for TypeDecl {
412 fn start_position(&self) -> Position {
413 self._hyphen.start_position()
414 }
415 fn end_position(&self) -> Position {
416 self._dot.end_position()
417 }
418}