MCPcopy Create free account
hub / github.com/csskit/csskit / parse

Method parse

crates/csskit_ast/src/selector/query.rs:139–224  ·  view source on GitHub ↗
(p: &mut Parser<'a, I>)

Source from the content-addressed store, hash-verified

137
138impl<'a> Parse<'a> for QueryCompoundSelector<'a> {
139 fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
140 where
141 I: Iterator<Item = Cursor> + Clone,
142 {
143 let mut parts = Vec::new_in(p.bump());
144 let mut metadata = QuerySelectorMetadata::default();
145
146 // Build segments in forward order. Each segment stores the combinator that follows it.
147 let mut segments: SmallVec<[SelectorSegment; 4]> = SmallVec::new();
148 let mut segment_start = 0u16;
149
150 // Track rightmost segment's type for rightmost_type_id computation
151 let mut rightmost_type: Option<NodeId> = None;
152 let mut rightmost_has_wildcard = false;
153
154 // Track leading combinator (for :has() inner selectors)
155 let mut leading_combinator: Option<QueryCombinator> = None;
156
157 // Trim leading whitespace
158 p.consume_trivia();
159
160 // Parse components incrementally, building metadata and segments as we go
161 while let Some(component) = Self::parse_compound_selector_part(p)? {
162 // Handle combinators separately - don't add to parts
163 if let Some(combinator) = component.as_combinator() {
164 let segment_end = parts.len() as u16;
165 if segment_start < segment_end {
166 // Emit the segment that just ended, with this combinator following it
167 segments.push(SelectorSegment {
168 start: segment_start,
169 end: segment_end,
170 combinator: Some(combinator),
171 });
172 segment_start = segment_end;
173 rightmost_type = None;
174 rightmost_has_wildcard = false;
175 } else if segments.is_empty() && leading_combinator.is_none() {
176 leading_combinator = Some(combinator);
177 }
178 metadata = metadata.merge(component.self_metadata());
179 continue;
180 }
181
182 // Track type/wildcard for rightmost_type_id computation
183 match &component {
184 QuerySelectorComponent::Type(t) => {
185 let c: Cursor = t.0.into();
186 let node_id = CsskitAtomSet::from_bits(c.atom_bits()).to_node_id();
187 if rightmost_type.is_none() {
188 rightmost_type = node_id;
189 }
190 // Mark selector as invalid if type is unknown
191 if node_id.is_none() {
192 metadata.is_invalid = true;
193 }
194 // Accumulate at-rule filter for all type selectors in the compound selector
195 if let Some(at_rule_id) = node_id.and_then(|id| id.to_at_rule_id()) {
196 metadata.at_rule_filter |= at_rule_id;

Callers 1

Calls 14

ErrClass · 0.85
consume_triviaMethod · 0.80
as_combinatorMethod · 0.80
to_at_rule_idMethod · 0.80
peek_nMethod · 0.80
isMethod · 0.80
set_stateMethod · 0.80
bumpMethod · 0.45
lenMethod · 0.45
is_emptyMethod · 0.45
mergeMethod · 0.45
self_metadataMethod · 0.45

Tested by

no test coverage detected