1use erl_tokenize::tokens::{AtomToken, SymbolToken};
2use erl_tokenize::values::Symbol;
3use erl_tokenize::{LexicalToken, Position, PositionRange};
4use std::fmt;
5
6use crate::directives;
7use crate::token_reader::{ReadFrom, TokenReader};
8use crate::{Error, Result};
9
10#[derive(Debug, Clone)]
12#[allow(missing_docs)]
13#[allow(clippy::large_enum_variant)]
14pub enum Directive {
15 Include(directives::Include),
16 IncludeLib(directives::IncludeLib),
17 Define(directives::Define),
18 Undef(directives::Undef),
19 Ifdef(directives::Ifdef),
20 Ifndef(directives::Ifndef),
21 Else(directives::Else),
22 Endif(directives::Endif),
23 Error(directives::Error),
24 Warning(directives::Warning),
25}
26impl PositionRange for Directive {
27 fn start_position(&self) -> Position {
28 match *self {
29 Directive::Include(ref t) => t.start_position(),
30 Directive::IncludeLib(ref t) => t.start_position(),
31 Directive::Define(ref t) => t.start_position(),
32 Directive::Undef(ref t) => t.start_position(),
33 Directive::Ifdef(ref t) => t.start_position(),
34 Directive::Ifndef(ref t) => t.start_position(),
35 Directive::Else(ref t) => t.start_position(),
36 Directive::Endif(ref t) => t.start_position(),
37 Directive::Error(ref t) => t.start_position(),
38 Directive::Warning(ref t) => t.start_position(),
39 }
40 }
41 fn end_position(&self) -> Position {
42 match *self {
43 Directive::Include(ref t) => t.end_position(),
44 Directive::IncludeLib(ref t) => t.end_position(),
45 Directive::Define(ref t) => t.end_position(),
46 Directive::Undef(ref t) => t.end_position(),
47 Directive::Ifdef(ref t) => t.end_position(),
48 Directive::Ifndef(ref t) => t.end_position(),
49 Directive::Else(ref t) => t.end_position(),
50 Directive::Endif(ref t) => t.end_position(),
51 Directive::Error(ref t) => t.end_position(),
52 Directive::Warning(ref t) => t.end_position(),
53 }
54 }
55}
56impl fmt::Display for Directive {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 match *self {
59 Directive::Include(ref t) => t.fmt(f),
60 Directive::IncludeLib(ref t) => t.fmt(f),
61 Directive::Define(ref t) => t.fmt(f),
62 Directive::Undef(ref t) => t.fmt(f),
63 Directive::Ifdef(ref t) => t.fmt(f),
64 Directive::Ifndef(ref t) => t.fmt(f),
65 Directive::Else(ref t) => t.fmt(f),
66 Directive::Endif(ref t) => t.fmt(f),
67 Directive::Error(ref t) => t.fmt(f),
68 Directive::Warning(ref t) => t.fmt(f),
69 }
70 }
71}
72impl ReadFrom for Directive {
73 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
74 where
75 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
76 {
77 let _hyphen: SymbolToken = reader.read_expected(&Symbol::Hyphen)?;
78 let name: AtomToken = reader
79 .try_read()?
80 .ok_or_else(|| Error::unexpected_token(_hyphen.clone().into(), "-{DIRECTIVE_NAME}"))?;
81
82 reader.unread_token(name.clone().into());
83 reader.unread_token(_hyphen.into());
84 match name.value() {
85 "include" => reader.read().map(Directive::Include),
86 "include_lib" => reader.read().map(Directive::IncludeLib),
87 "define" => reader.read().map(Directive::Define),
88 "undef" => reader.read().map(Directive::Undef),
89 "ifdef" => reader.read().map(Directive::Ifdef),
90 "ifndef" => reader.read().map(Directive::Ifndef),
91 "else" => reader.read().map(Directive::Else),
92 "endif" => reader.read().map(Directive::Endif),
93 "error" => reader.read().map(Directive::Error),
94 "warning" => reader.read().map(Directive::Warning),
95 _ => {
96 let _hyphen: SymbolToken = reader.read_expected(&Symbol::Hyphen)?;
97 Err(Error::unexpected_token(_hyphen.into(), "-{DIRECTIVE_NAME}"))
98 }
99 }
100 }
101}