1use std::ops::{Deref, DerefMut};
2
3use swc_common::{Span, Spanned, DUMMY_SP};
4use swc_css_ast::*;
5
6use super::{
7 input::{Input, InputType, ParserInput},
8 Ctx, Error, PResult, Parse, Parser,
9};
10use crate::{error::ErrorKind, parser::BlockContentsGrammar};
11
12impl<I> Parser<I>
13where
14 I: ParserInput,
15{
16 #[inline]
18 pub(super) fn with_ctx(&mut self, ctx: Ctx) -> WithCtx<I> {
19 let orig_ctx = self.ctx;
20
21 self.ctx = ctx;
22
23 WithCtx {
24 orig_ctx,
25 inner: self,
26 }
27 }
28
29 #[inline]
30 pub(super) fn parse_as<T>(&mut self) -> PResult<T>
31 where
32 Self: Parse<T>,
33 {
34 self.parse()
35 }
36
37 pub(super) fn try_parse<Ret>(
38 &mut self,
39 op: impl FnOnce(&mut Parser<I>) -> PResult<Ret>,
40 ) -> Option<Ret> {
41 let mut parser = self.clone();
42
43 match op(&mut parser) {
44 Ok(v) => {
45 *self = parser;
46 Some(v)
47 }
48 Err(..) => None,
49 }
50 }
51
52 pub(super) fn create_locv(&self, children: Vec<ComponentValue>) -> ListOfComponentValues {
53 let span = match (children.first(), children.last()) {
54 (Some(first), Some(last)) => Span::new(first.span_lo(), last.span_hi()),
55 _ => DUMMY_SP,
56 };
57
58 ListOfComponentValues { span, children }
59 }
60
61 pub(super) fn parse_according_to_grammar<T>(
62 &mut self,
63 list_of_component_values: &ListOfComponentValues,
64 op: impl FnOnce(&mut Parser<Input>) -> PResult<T>,
65 ) -> PResult<T> {
66 let lexer = Input::new(InputType::ListOfComponentValues(list_of_component_values));
67 let mut parser = Parser::new(lexer, self.config);
68 let res = op(&mut parser.with_ctx(self.ctx));
69
70 self.errors.extend(parser.take_errors());
71
72 res
73 }
74
75 pub(super) fn canonicalize_at_rule_prelude(&mut self, mut at_rule: AtRule) -> PResult<AtRule> {
76 let normalized_at_rule_name = match &at_rule.name {
77 AtRuleName::Ident(Ident { value, .. }) => value.to_ascii_lowercase(),
78 AtRuleName::DashedIdent(_) => return Ok(at_rule),
79 };
80
81 let list_of_component_values = match at_rule.prelude {
82 Some(at_rule_prelude) => match *at_rule_prelude {
83 AtRulePrelude::ListOfComponentValues(list_of_component_values) => {
84 list_of_component_values
85 }
86 _ => {
87 unreachable!();
88 }
89 },
90 _ => {
91 unreachable!();
92 }
93 };
94
95 at_rule.prelude = match self
96 .parse_according_to_grammar(&list_of_component_values, |parser| {
97 parser.parse_at_rule_prelude(&normalized_at_rule_name)
98 }) {
99 Ok(at_rule_prelude) => match at_rule_prelude {
100 Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList(name_list)))
101 if name_list.name_list.len() > 1 && at_rule.block.is_some() =>
102 {
103 self.errors.push(Error::new(
104 name_list.span,
105 ErrorKind::Expected("only one name"),
106 ));
107
108 Some(Box::new(AtRulePrelude::ListOfComponentValues(
109 list_of_component_values,
110 )))
111 }
112 None if normalized_at_rule_name == "layer" && at_rule.block.is_none() => {
113 self.errors.push(Error::new(
114 at_rule.span,
115 ErrorKind::Expected("at least one name"),
116 ));
117
118 Some(Box::new(AtRulePrelude::ListOfComponentValues(
119 list_of_component_values,
120 )))
121 }
122 _ => at_rule_prelude.map(Box::new),
123 },
124 Err(err) => {
125 if *err.kind() != ErrorKind::Ignore {
126 self.errors.push(err);
127 }
128
129 if !list_of_component_values.children.is_empty() {
130 Some(Box::new(AtRulePrelude::ListOfComponentValues(
131 list_of_component_values,
132 )))
133 } else {
134 None
135 }
136 }
137 };
138
139 Ok(at_rule)
140 }
141
142 pub(super) fn canonicalize_at_rule_block(&mut self, mut at_rule: AtRule) -> PResult<AtRule> {
143 let normalized_at_rule_name = match &at_rule.name {
144 AtRuleName::Ident(Ident { value, .. }) => value.to_ascii_lowercase(),
145 AtRuleName::DashedIdent(_) => return Ok(at_rule),
146 };
147
148 let mut block = match at_rule.block {
149 Some(simple_block) => simple_block,
150 _ => {
151 unreachable!();
152 }
153 };
154
155 let list_of_component_values = self.create_locv(block.value);
156
157 block.value = match self.parse_according_to_grammar(&list_of_component_values, |parser| {
158 parser.parse_at_rule_block(&normalized_at_rule_name)
159 }) {
160 Ok(block_contents) => block_contents,
161 Err(err) => {
162 if *err.kind() != ErrorKind::Ignore {
163 self.errors.push(err);
164 }
165
166 list_of_component_values.children
167 }
168 };
169
170 at_rule.block = Some(block);
171
172 Ok(at_rule)
173 }
174
175 pub(super) fn canonicalize_qualified_rule_prelude(
176 &mut self,
177 mut qualified_rule: QualifiedRule,
178 ) -> PResult<QualifiedRule> {
179 let list_of_component_values = match qualified_rule.prelude {
180 QualifiedRulePrelude::ListOfComponentValues(list_of_component_values) => {
181 list_of_component_values
182 }
183 _ => {
184 unreachable!();
185 }
186 };
187
188 qualified_rule.prelude = if self.ctx.in_keyframes_at_rule {
189 QualifiedRulePrelude::ListOfComponentValues(list_of_component_values)
190 } else if self.ctx.mixed_with_declarations {
191 match self.parse_according_to_grammar::<RelativeSelectorList>(
192 &list_of_component_values,
193 |parser| parser.parse(),
194 ) {
195 Ok(relative_selector_list) => {
196 QualifiedRulePrelude::RelativeSelectorList(relative_selector_list)
197 }
198 Err(err) => {
199 self.errors.push(err);
200
201 QualifiedRulePrelude::ListOfComponentValues(list_of_component_values)
202 }
203 }
204 } else {
205 match self
206 .parse_according_to_grammar::<SelectorList>(&list_of_component_values, |parser| {
207 parser.parse()
208 }) {
209 Ok(selector_list) => QualifiedRulePrelude::SelectorList(selector_list),
210 Err(err) => {
211 self.errors.push(err);
212
213 QualifiedRulePrelude::ListOfComponentValues(list_of_component_values)
214 }
215 }
216 };
217
218 Ok(qualified_rule)
219 }
220
221 pub(super) fn canonicalize_qualified_rule_block(
222 &mut self,
223 mut qualified_rule: QualifiedRule,
224 ) -> PResult<QualifiedRule> {
225 qualified_rule.block.value = match self.ctx.block_contents_grammar {
226 BlockContentsGrammar::RuleList if self.ctx.in_keyframes_at_rule => self
227 .parse_according_to_grammar(
228 &self.create_locv(qualified_rule.block.value),
229 |parser| {
230 parser
231 .with_ctx(Ctx {
232 block_contents_grammar: BlockContentsGrammar::DeclarationList,
233 ..parser.ctx
234 })
235 .parse_as::<Vec<DeclarationOrAtRule>>()
236 },
237 )?
238 .into_iter()
239 .map(ComponentValue::from)
240 .collect(),
241 _ => self
242 .parse_according_to_grammar(
243 &self.create_locv(qualified_rule.block.value),
244 |parser| {
245 parser
246 .with_ctx(Ctx {
247 block_contents_grammar: BlockContentsGrammar::StyleBlock,
248 ..parser.ctx
249 })
250 .parse_as::<Vec<StyleBlock>>()
251 },
252 )?
253 .into_iter()
254 .map(ComponentValue::from)
255 .collect(),
256 };
257
258 Ok(qualified_rule)
259 }
260
261 pub(super) fn canonicalize_function_value(
262 &mut self,
263 mut function: Function,
264 ) -> PResult<Function> {
265 let locv = self.create_locv(function.value);
266
267 function.value = match self.parse_according_to_grammar(&locv, |parser| {
268 parser.parse_function_values(&function.name)
269 }) {
270 Ok(values) => values,
271 Err(err) => {
272 if *err.kind() != ErrorKind::Ignore {
273 self.errors.push(err);
274 }
275
276 locv.children
277 }
278 };
279
280 Ok(function)
281 }
282
283 pub(super) fn canonicalize_declaration_value(
284 &mut self,
285 mut declaration: Declaration,
286 ) -> PResult<Declaration> {
287 let locv = self.create_locv(declaration.value);
288
289 let value = self.parse_according_to_grammar(&locv, |parser| {
290 let mut values = Vec::new();
291
292 loop {
293 if is!(parser, EOF) {
294 break;
295 }
296
297 values.push(parser.parse_generic_value()?);
298 }
299
300 Ok(values)
301 });
302 declaration.value = match value {
303 Ok(values) => values,
304 Err(err) => {
305 if *err.kind() != ErrorKind::Ignore {
306 self.errors.push(err);
307 }
308
309 locv.children
310 }
311 };
312
313 Ok(declaration)
314 }
315
316 pub(super) fn try_to_parse_legacy_nesting(&mut self) -> Option<QualifiedRule> {
317 let state = self.input.state();
318 let qualified_rule = self
319 .with_ctx(Ctx {
320 block_contents_grammar: BlockContentsGrammar::StyleBlock,
321 mixed_with_declarations: true,
322 ..self.ctx
323 })
324 .parse_as::<QualifiedRule>();
325
326 match qualified_rule {
327 Ok(qualified_rule) => Some(qualified_rule),
328 _ => {
329 self.input.reset(&state);
330
331 None
332 }
333 }
334 }
335
336 pub(super) fn try_to_parse_declaration_in_parens(&mut self) -> Option<Declaration> {
337 let mut temporary_list = ListOfComponentValues {
338 span: Default::default(),
339 children: Vec::new(),
340 };
341
342 while !is_one_of!(self, ")", EOF) {
343 let component_value = match self.parse_as::<ComponentValue>() {
344 Ok(component_value) => component_value,
345 Err(_) => return None,
346 };
347
348 temporary_list.children.push(component_value);
349 }
350
351 self.parse_according_to_grammar::<Declaration>(&temporary_list, |parser| parser.parse_as())
352 .ok()
353 }
354
355 pub(super) fn parse_declaration_from_temporary_list(
356 &mut self,
357 temporary_list: &ListOfComponentValues,
358 ) -> PResult<Declaration> {
359 self.parse_according_to_grammar::<Declaration>(temporary_list, |parser| parser.parse_as())
360 }
361
362 pub(super) fn validate_declaration_value(
368 &mut self,
369 component_value: &ComponentValue,
370 ) -> PResult<()> {
371 let ComponentValue::PreservedToken(preserved_token) = component_value else {
372 return Ok(());
373 };
374
375 let kind = match preserved_token.token {
376 Token::BadString { .. } => ErrorKind::Unexpected("bad string in declaration value"),
377 Token::BadUrl { .. } => ErrorKind::Unexpected("bad url in declaration value"),
378 Token::RParen => ErrorKind::Unexpected("')' in declaration value"),
379 Token::RBracket => ErrorKind::Unexpected("']' in declaration value"),
380 Token::RBrace => ErrorKind::Unexpected("'}' in declaration value"),
381 Token::Semi => ErrorKind::Unexpected("';' in declaration value"),
382 Token::Delim { value: '!' } => ErrorKind::Unexpected("'!' in declaration value"),
383 _ => return Ok(()),
384 };
385
386 Err(Error::new(preserved_token.span, kind))
387 }
388}
389
390pub(super) struct WithCtx<'w, I: 'w + ParserInput> {
391 inner: &'w mut Parser<I>,
392 orig_ctx: Ctx,
393}
394
395impl<I: ParserInput> Deref for WithCtx<'_, I> {
396 type Target = Parser<I>;
397
398 fn deref(&self) -> &Parser<I> {
399 self.inner
400 }
401}
402impl<I: ParserInput> DerefMut for WithCtx<'_, I> {
403 fn deref_mut(&mut self) -> &mut Parser<I> {
404 self.inner
405 }
406}
407
408impl<I: ParserInput> Drop for WithCtx<'_, I> {
409 fn drop(&mut self) {
410 self.inner.ctx = self.orig_ctx;
411 }
412}