]> git.proxmox.com Git - rustc.git/blob - vendor/time/src/format_description/parse/ast.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / vendor / time / src / format_description / parse / ast.rs
1 //! AST for parsing format descriptions.
2
3 use alloc::string::String;
4 use alloc::vec::Vec;
5 use core::iter;
6 use core::iter::Peekable;
7
8 use super::{lexer, Error, Location, Span};
9
10 /// One part of a complete format description.
11 #[allow(variant_size_differences)]
12 pub(super) enum Item<'a> {
13 /// A literal string, formatted and parsed as-is.
14 Literal {
15 /// The string itself.
16 value: &'a [u8],
17 /// Where the string originates from in the format string.
18 _span: Span,
19 },
20 /// A sequence of brackets. The first acts as the escape character.
21 EscapedBracket {
22 /// The first bracket.
23 _first: Location,
24 /// The second bracket.
25 _second: Location,
26 },
27 /// Part of a type, along with its modifiers.
28 Component {
29 /// Where the opening bracket was in the format string.
30 _opening_bracket: Location,
31 /// Whitespace between the opening bracket and name.
32 _leading_whitespace: Option<Whitespace<'a>>,
33 /// The name of the component.
34 name: Name<'a>,
35 /// The modifiers for the component.
36 modifiers: Vec<Modifier<'a>>,
37 /// Whitespace between the modifiers and closing bracket.
38 _trailing_whitespace: Option<Whitespace<'a>>,
39 /// Where the closing bracket was in the format string.
40 _closing_bracket: Location,
41 },
42 }
43
44 /// Whitespace within a component.
45 pub(super) struct Whitespace<'a> {
46 /// The whitespace itself.
47 pub(super) _value: &'a [u8],
48 /// Where the whitespace was in the format string.
49 pub(super) span: Span,
50 }
51
52 /// The name of a component.
53 pub(super) struct Name<'a> {
54 /// The name itself.
55 pub(super) value: &'a [u8],
56 /// Where the name was in the format string.
57 pub(super) span: Span,
58 }
59
60 /// A modifier for a component.
61 pub(super) struct Modifier<'a> {
62 /// Whitespace preceding the modifier.
63 pub(super) _leading_whitespace: Whitespace<'a>,
64 /// The key of the modifier.
65 pub(super) key: Key<'a>,
66 /// Where the colon of the modifier was in the format string.
67 pub(super) _colon: Location,
68 /// The value of the modifier.
69 pub(super) value: Value<'a>,
70 }
71
72 /// The key of a modifier.
73 pub(super) struct Key<'a> {
74 /// The key itself.
75 pub(super) value: &'a [u8],
76 /// Where the key was in the format string.
77 pub(super) span: Span,
78 }
79
80 /// The value of a modifier.
81 pub(super) struct Value<'a> {
82 /// The value itself.
83 pub(super) value: &'a [u8],
84 /// Where the value was in the format string.
85 pub(super) span: Span,
86 }
87
88 /// Parse the provided tokens into an AST.
89 pub(super) fn parse<'a>(
90 tokens: impl Iterator<Item = lexer::Token<'a>>,
91 ) -> impl Iterator<Item = Result<Item<'a>, Error>> {
92 let mut tokens = tokens.peekable();
93 iter::from_fn(move || {
94 Some(match tokens.next()? {
95 lexer::Token::Literal { value, span } => Ok(Item::Literal { value, _span: span }),
96 lexer::Token::Bracket {
97 kind: lexer::BracketKind::Opening,
98 location,
99 } => {
100 // escaped bracket
101 if let Some(&lexer::Token::Bracket {
102 kind: lexer::BracketKind::Opening,
103 location: second_location,
104 }) = tokens.peek()
105 {
106 tokens.next(); // consume
107 Ok(Item::EscapedBracket {
108 _first: location,
109 _second: second_location,
110 })
111 }
112 // component
113 else {
114 parse_component(location, &mut tokens)
115 }
116 }
117 lexer::Token::Bracket {
118 kind: lexer::BracketKind::Closing,
119 location: _,
120 } => unreachable!(
121 "internal error: closing bracket should have been consumed by `parse_component`",
122 ),
123 lexer::Token::ComponentPart {
124 kind: _,
125 value: _,
126 span: _,
127 } => unreachable!(
128 "internal error: component part should have been consumed by `parse_component`",
129 ),
130 })
131 })
132 }
133
134 /// Parse a component. This assumes that the opening bracket has already been consumed.
135 fn parse_component<'a>(
136 opening_bracket: Location,
137 tokens: &mut Peekable<impl Iterator<Item = lexer::Token<'a>>>,
138 ) -> Result<Item<'a>, Error> {
139 let leading_whitespace = if let Some(&lexer::Token::ComponentPart {
140 kind: lexer::ComponentKind::Whitespace,
141 value,
142 span,
143 }) = tokens.peek()
144 {
145 tokens.next(); // consume
146 Some(Whitespace {
147 _value: value,
148 span,
149 })
150 } else {
151 None
152 };
153
154 let name = if let Some(&lexer::Token::ComponentPart {
155 kind: lexer::ComponentKind::NotWhitespace,
156 value,
157 span,
158 }) = tokens.peek()
159 {
160 tokens.next(); // consume
161 Name { value, span }
162 } else {
163 let span = leading_whitespace.map_or_else(
164 || Span {
165 start: opening_bracket,
166 end: opening_bracket,
167 },
168 |whitespace| whitespace.span.shrink_to_end(),
169 );
170 return Err(Error {
171 _inner: span.error("expected component name"),
172 public: crate::error::InvalidFormatDescription::MissingComponentName {
173 index: span.start_byte(),
174 },
175 });
176 };
177
178 let mut modifiers = Vec::new();
179 let trailing_whitespace = loop {
180 let whitespace = if let Some(&lexer::Token::ComponentPart {
181 kind: lexer::ComponentKind::Whitespace,
182 value,
183 span,
184 }) = tokens.peek()
185 {
186 tokens.next(); // consume
187 Whitespace {
188 _value: value,
189 span,
190 }
191 } else {
192 break None;
193 };
194
195 if let Some(&lexer::Token::ComponentPart {
196 kind: lexer::ComponentKind::NotWhitespace,
197 value,
198 span,
199 }) = tokens.peek()
200 {
201 tokens.next(); // consume
202
203 let colon_index = match value.iter().position(|&b| b == b':') {
204 Some(index) => index,
205 None => {
206 return Err(Error {
207 _inner: span.error("modifier must be of the form `key:value`"),
208 public: crate::error::InvalidFormatDescription::InvalidModifier {
209 value: String::from_utf8_lossy(value).into_owned(),
210 index: span.start_byte(),
211 },
212 });
213 }
214 };
215 let key = &value[..colon_index];
216 let value = &value[colon_index + 1..];
217
218 if key.is_empty() {
219 return Err(Error {
220 _inner: span.shrink_to_start().error("expected modifier key"),
221 public: crate::error::InvalidFormatDescription::InvalidModifier {
222 value: String::new(),
223 index: span.start_byte(),
224 },
225 });
226 }
227 if value.is_empty() {
228 return Err(Error {
229 _inner: span.shrink_to_end().error("expected modifier value"),
230 public: crate::error::InvalidFormatDescription::InvalidModifier {
231 value: String::new(),
232 index: span.shrink_to_end().start_byte(),
233 },
234 });
235 }
236
237 modifiers.push(Modifier {
238 _leading_whitespace: whitespace,
239 key: Key {
240 value: key,
241 span: span.subspan(..colon_index),
242 },
243 _colon: span.start.offset(colon_index),
244 value: Value {
245 value,
246 span: span.subspan(colon_index + 1..),
247 },
248 });
249 } else {
250 break Some(whitespace);
251 }
252 };
253
254 let closing_bracket = if let Some(&lexer::Token::Bracket {
255 kind: lexer::BracketKind::Closing,
256 location,
257 }) = tokens.peek()
258 {
259 tokens.next(); // consume
260 location
261 } else {
262 return Err(Error {
263 _inner: opening_bracket.error("unclosed bracket"),
264 public: crate::error::InvalidFormatDescription::UnclosedOpeningBracket {
265 index: opening_bracket.byte,
266 },
267 });
268 };
269
270 Ok(Item::Component {
271 _opening_bracket: opening_bracket,
272 _leading_whitespace: leading_whitespace,
273 name,
274 modifiers,
275 _trailing_whitespace: trailing_whitespace,
276 _closing_bracket: closing_bracket,
277 })
278 }