1 | //! Parser for format descriptions. |
2 | |
3 | macro_rules! version { |
4 | ($range:expr) => { |
5 | $range.contains(&VERSION) |
6 | }; |
7 | } |
8 | |
9 | mod ast; |
10 | mod format_item; |
11 | mod lexer; |
12 | mod public; |
13 | |
14 | pub(crate) fn parse_with_version( |
15 | version: Option<crate::FormatDescriptionVersion>, |
16 | s: &[u8], |
17 | proc_span: proc_macro::Span, |
18 | ) -> Result<Vec<public::OwnedFormatItem>, crate::Error> { |
19 | match version { |
20 | Some(crate::FormatDescriptionVersion::V1) | None => parse::<1>(s, proc_span), |
21 | Some(crate::FormatDescriptionVersion::V2) => parse::<2>(s, proc_span), |
22 | } |
23 | } |
24 | |
25 | fn parse<const VERSION: u8>( |
26 | s: &[u8], |
27 | proc_span: proc_macro::Span, |
28 | ) -> Result<Vec<public::OwnedFormatItem>, crate::Error> { |
29 | let mut lexed: Lexed> = lexer::lex::<VERSION>(input:s, proc_span); |
30 | let ast: impl Iterator- >
= ast::parse::<_, VERSION>(&mut lexed); |
31 | let format_items: impl Iterator- >
= format_item::parse(ast); |
32 | Ok(format_itemsimpl Iterator- >
|
33 | .map(|res: Result- , Error>
| res.map(op:Into::into)) |
34 | .collect::<Result<_, _>>()?) |
35 | } |
36 | |
37 | #[derive (Clone, Copy)] |
38 | struct Location { |
39 | byte: u32, |
40 | proc_span: proc_macro::Span, |
41 | } |
42 | |
43 | impl Location { |
44 | fn to(self, end: Self) -> Span { |
45 | Span { start: self, end } |
46 | } |
47 | |
48 | #[must_use = "this does not modify the original value" ] |
49 | fn offset(&self, offset: u32) -> Self { |
50 | Self { |
51 | byte: self.byte + offset, |
52 | proc_span: self.proc_span, |
53 | } |
54 | } |
55 | |
56 | fn error(self, message: &'static str) -> Error { |
57 | Error { |
58 | message, |
59 | _span: unused(Span { |
60 | start: self, |
61 | end: self, |
62 | }), |
63 | proc_span: self.proc_span, |
64 | } |
65 | } |
66 | } |
67 | |
68 | #[derive (Clone, Copy)] |
69 | struct Span { |
70 | #[allow (clippy::missing_docs_in_private_items)] |
71 | start: Location, |
72 | #[allow (clippy::missing_docs_in_private_items)] |
73 | end: Location, |
74 | } |
75 | |
76 | impl Span { |
77 | #[must_use = "this does not modify the original value" ] |
78 | const fn shrink_to_start(&self) -> Self { |
79 | Self { |
80 | start: self.start, |
81 | end: self.start, |
82 | } |
83 | } |
84 | |
85 | #[must_use = "this does not modify the original value" ] |
86 | const fn shrink_to_end(&self) -> Self { |
87 | Self { |
88 | start: self.end, |
89 | end: self.end, |
90 | } |
91 | } |
92 | |
93 | #[must_use = "this does not modify the original value" ] |
94 | const fn shrink_to_before(&self, pos: u32) -> Self { |
95 | Self { |
96 | start: self.start, |
97 | end: Location { |
98 | byte: self.start.byte + pos - 1, |
99 | proc_span: self.start.proc_span, |
100 | }, |
101 | } |
102 | } |
103 | |
104 | #[must_use = "this does not modify the original value" ] |
105 | fn shrink_to_after(&self, pos: u32) -> Self { |
106 | Self { |
107 | start: Location { |
108 | byte: self.start.byte + pos + 1, |
109 | proc_span: self.start.proc_span, |
110 | }, |
111 | end: self.end, |
112 | } |
113 | } |
114 | |
115 | fn error(self, message: &'static str) -> Error { |
116 | Error { |
117 | message, |
118 | _span: unused(self), |
119 | proc_span: self.start.proc_span, |
120 | } |
121 | } |
122 | } |
123 | |
124 | #[derive (Clone, Copy)] |
125 | struct Spanned<T> { |
126 | value: T, |
127 | span: Span, |
128 | } |
129 | |
130 | impl<T> core::ops::Deref for Spanned<T> { |
131 | type Target = T; |
132 | |
133 | fn deref(&self) -> &Self::Target { |
134 | &self.value |
135 | } |
136 | } |
137 | |
138 | trait SpannedValue: Sized { |
139 | fn spanned(self, span: Span) -> Spanned<Self>; |
140 | } |
141 | |
142 | impl<T> SpannedValue for T { |
143 | fn spanned(self, span: Span) -> Spanned<Self> { |
144 | Spanned { value: self, span } |
145 | } |
146 | } |
147 | |
148 | struct Error { |
149 | message: &'static str, |
150 | _span: Unused<Span>, |
151 | proc_span: proc_macro::Span, |
152 | } |
153 | |
154 | impl From<Error> for crate::Error { |
155 | fn from(error: Error) -> Self { |
156 | Self::Custom { |
157 | message: error.message.into(), |
158 | span_start: Some(error.proc_span), |
159 | span_end: Some(error.proc_span), |
160 | } |
161 | } |
162 | } |
163 | |
164 | struct Unused<T>(core::marker::PhantomData<T>); |
165 | |
166 | #[allow (clippy::missing_const_for_fn)] // false positive |
167 | fn unused<T>(_: T) -> Unused<T> { |
168 | Unused(core::marker::PhantomData) |
169 | } |
170 | |