tiger_lib/
block.rs

1//! [`Block`] is the core type to represent Pdx script code
2
3use crate::date::Date;
4use crate::macros::MACRO_MAP;
5use crate::parse::pdxfile::{MacroComponent, MacroComponentKind, PdxfileMemory, parse_pdx_macro};
6use crate::token::{Loc, Token};
7
8mod blockitem;
9mod bv;
10mod comparator;
11mod field;
12
13pub use crate::block::blockitem::BlockItem;
14pub use crate::block::bv::BV;
15pub use crate::block::comparator::{Comparator, Eq};
16pub use crate::block::field::Field;
17
18/// This type represents the most basic structural element of Pdx script code.
19/// Blocks are delimited by `{` and `}`. An entire file is also a `Block`.
20///
21/// A `Block` can contain a mix of these kinds of items:
22///
23/// * Assignments: `key = value`
24/// * Definitions: `key = { ... }`
25/// * Loose sub-blocks: `{ ... } { ... } ...`
26/// * Loose values: `value value ...`
27/// * Comparisons: `key < value` for a variety of comparators, including `=` for equality
28/// * `key < { ... }` is accepted by the parser but is not used anywhere
29///
30/// The same key can occur multiple times in a block. If a single field is requested and its key
31/// occurs multiple times, the last instance is returned (which is how the game usually resolves
32/// this).
33#[derive(Clone, Debug)]
34pub struct Block {
35    /// The contents of this block.
36    v: Vec<BlockItem>,
37    /// The `tag` is a short string that precedes a block, as in `color = hsv { 0.5 0.5 1.0 }`.
38    /// Only a small number of hardcoded tags are parsed this way.
39    /// It is in a `Box` to save space in blocks that don't have a tag, which is most of them.
40    pub tag: Option<Box<Token>>,
41    /// The location of the start of the block. Used mostly for error reporting.
42    pub loc: Loc,
43    /// If the block is a top-level block and contains macro substitutions, this field will
44    /// hold the original source for re-parsing.
45    /// The source has already been split into a vec that alternates content with macro parameters.
46    /// It is in a `Box` to save space (80 bytes) from blocks that don't contain macro substitutions,
47    /// which is most of them.
48    pub source: Option<Box<(Vec<MacroComponent>, PdxfileMemory)>>,
49}
50
51impl Block {
52    /// Open a new `Block` at the given location.
53    pub fn new(loc: Loc) -> Self {
54        Block { v: Vec::new(), tag: None, loc, source: None }
55    }
56
57    /// Add a loose value to this `Block`. Mostly used by the parser.
58    #[allow(dead_code)]
59    pub fn add_value(&mut self, value: Token) {
60        self.v.push(BlockItem::Value(value));
61    }
62
63    /// Add a loose sub-block to this `Block`. Mostly used by the parser.
64    #[allow(dead_code)]
65    pub fn add_block(&mut self, block: Block) {
66        self.v.push(BlockItem::Block(block));
67    }
68
69    /// Add a `key = value` or `key = { ... }` field to this `Block`.
70    /// Mostly used by the parser.
71    #[allow(dead_code)] // used only by json parser
72    pub fn add_key_bv(&mut self, key: Token, cmp: Comparator, value: BV) {
73        self.v.push(BlockItem::Field(Field(key, cmp, value)));
74    }
75
76    /// Add a `BlockItem` to this `Block`.
77    /// It can contain any of the variations of things that a `Block` can hold.
78    pub fn add_item(&mut self, item: BlockItem) {
79        self.v.push(item);
80    }
81
82    /// Add a `BlockItem` to this `Block`.
83    /// If it is a `BlockItem::Block` and the previous item is a `key = tag`,
84    /// where the tag is one of a predefined set of strings, then combine
85    /// the block with that previous item.
86    pub fn add_item_check_tag(&mut self, item: BlockItem) {
87        if let BlockItem::Block(mut block) = item {
88            if let Some(BlockItem::Field(Field(key, cmp, BV::Value(value)))) = self.v.last() {
89                if value.is("hsv")
90                    || value.is("rgb")
91                    || value.is("hsv360")
92                    || value.is("cylindrical")
93                    || value.is("cartesian")
94                {
95                    let key = key.clone();
96                    let cmp = *cmp;
97                    block.tag = Some(Box::new(value.clone()));
98                    self.v.pop();
99                    self.v.push(BlockItem::Field(Field(key, cmp, BV::Block(block))));
100                    return;
101                }
102            }
103            self.v.push(BlockItem::Block(block));
104        } else {
105            self.v.push(item);
106        }
107    }
108
109    /// Combine two blocks by adding the contents of `other` to this block.
110    /// To avoid lots of cloning, `other` will be emptied in the process.
111    #[cfg(any(feature = "ck3", feature = "vic3", feature = "eu5"))]
112    pub fn append(&mut self, other: &mut Block) {
113        self.v.append(&mut other.v);
114    }
115
116    /// Get the value of a single `name = value` assignment.
117    pub fn get_field_value(&self, name: &str) -> Option<&Token> {
118        for item in self.v.iter().rev() {
119            if let BlockItem::Field(Field(key, _, bv)) = item {
120                if key.is(name) {
121                    match bv {
122                        BV::Value(t) => return Some(t),
123                        BV::Block(_) => (),
124                    }
125                }
126            }
127        }
128        None
129    }
130
131    /// Check if `name` is a field that has the literal string `value` as its value.
132    pub fn field_value_is(&self, name: &str, value: &str) -> bool {
133        if let Some(token) = self.get_field_value(name) { token.is(value) } else { false }
134    }
135
136    /// Get the value of a literal boolean field
137    pub fn get_field_bool(&self, name: &str) -> Option<bool> {
138        self.get_field_value(name).map(|t| t.is("yes"))
139    }
140
141    /// Get the value of a literal integer field
142    #[allow(dead_code)] // Not used by all games
143    pub fn get_field_integer(&self, name: &str) -> Option<i64> {
144        self.get_field_value(name).and_then(Token::get_integer)
145    }
146
147    /// Get the value of a literal date field
148    #[allow(dead_code)] // Not used by all games
149    pub fn get_field_date(&self, name: &str) -> Option<Date> {
150        self.get_field_value(name).and_then(Token::get_date)
151    }
152
153    /// Get all the values of `name = value` assignments in this block
154    ///
155    /// TODO: should be an iterator
156    pub fn get_field_values(&self, name: &str) -> Vec<&Token> {
157        let mut vec = Vec::new();
158        for (key, token) in self.iter_assignments() {
159            if key.is(name) {
160                vec.push(token);
161            }
162        }
163        vec
164    }
165
166    /// Get the block of a `name = { ... }` definition
167    pub fn get_field_block(&self, name: &str) -> Option<&Block> {
168        for item in self.v.iter().rev() {
169            if let BlockItem::Field(Field(key, _, bv)) = item {
170                if key.is(name) {
171                    match bv {
172                        BV::Value(_) => (),
173                        BV::Block(b) => return Some(b),
174                    }
175                }
176            }
177        }
178        None
179    }
180
181    /// Get all the blocks of `name = { ... }` definitions in this block
182    pub fn get_field_blocks(&self, name: &str) -> Vec<&Block> {
183        let mut vec = Vec::new();
184        for (key, block) in self.iter_definitions() {
185            if key.is(name) {
186                vec.push(block);
187            }
188        }
189        vec
190    }
191
192    /// Get the values of a single `name = { value value ... }` list
193    pub fn get_field_list(&self, name: &str) -> Option<Vec<Token>> {
194        for item in self.v.iter().rev() {
195            if let BlockItem::Field(Field(key, _, bv)) = item {
196                if key.is(name) {
197                    match bv {
198                        BV::Value(_) => (),
199                        BV::Block(b) => {
200                            return Some(b.iter_values().cloned().collect());
201                        }
202                    }
203                }
204            }
205        }
206        None
207    }
208
209    /// Get the combined values of any number of `name = { value value ... }` list
210    #[allow(dead_code)] // not used by all games
211    pub fn get_multi_field_list(&self, name: &str) -> Vec<Token> {
212        let mut vec = Vec::new();
213        for item in &self.v {
214            if let BlockItem::Field(Field(key, _, bv)) = item {
215                if key.is(name) {
216                    match bv {
217                        BV::Value(_) => (),
218                        BV::Block(b) => {
219                            vec.extend(b.iter_values().cloned());
220                        }
221                    }
222                }
223            }
224        }
225        vec
226    }
227
228    /// Get the value or block on the right-hand side of a field `name`.
229    pub fn get_field(&self, name: &str) -> Option<&BV> {
230        for item in self.v.iter().rev() {
231            if let BlockItem::Field(Field(key, _, bv)) = item {
232                if key.is(name) {
233                    return Some(bv);
234                }
235            }
236        }
237        None
238    }
239
240    /// Get the key of a field `name` in the `Block`. The string value of the key will be equal to
241    /// `name`, but it can be useful to get this key as a `Token` with its location.
242    pub fn get_key(&self, name: &str) -> Option<&Token> {
243        for item in self.v.iter().rev() {
244            if let BlockItem::Field(Field(key, _, _)) = item {
245                if key.is(name) {
246                    return Some(key);
247                }
248            }
249        }
250        None
251    }
252
253    /// Get all the keys of fields with key `name`. The string values of these keys will be equal
254    /// to `name`, but it can be useful to get these keys as `Token` with their locations.
255    pub fn get_keys(&self, name: &str) -> Vec<&Token> {
256        let mut vec = Vec::new();
257        for Field(key, _, _) in self.iter_fields() {
258            if key.is(name) {
259                vec.push(key);
260            }
261        }
262        vec
263    }
264
265    /// Return true iff the `name` occurs in this block at least once as a field key.
266    pub fn has_key(&self, name: &str) -> bool {
267        self.get_key(name).is_some()
268    }
269
270    #[cfg(feature = "vic3")]
271    pub fn has_key_recursive(&self, name: &str) -> bool {
272        for item in &self.v {
273            match item {
274                BlockItem::Field(Field(key, _, bv)) => {
275                    if key.is(name) {
276                        return true;
277                    }
278                    if let Some(block) = bv.get_block() {
279                        if block.has_key_recursive(name) {
280                            return true;
281                        }
282                    }
283                }
284                BlockItem::Block(block) => {
285                    if block.has_key_recursive(name) {
286                        return true;
287                    }
288                }
289                BlockItem::Value(_) => (),
290            }
291        }
292        false
293    }
294
295    /// Return the number of times `name` occurs in this block as a field key.
296    #[allow(dead_code)] // Not used by all games
297    pub fn count_keys(&self, name: &str) -> usize {
298        let mut count = 0;
299        for Field(key, _, _) in self.iter_fields() {
300            if key.is(name) {
301                count += 1;
302            }
303        }
304        count
305    }
306
307    /// Return the number of items in this block.
308    pub fn num_items(&self) -> usize {
309        self.v.len()
310    }
311
312    /// Return an iterator over the contents of this block.
313    pub fn iter_items(&self) -> std::slice::Iter<'_, BlockItem> {
314        self.v.iter()
315    }
316
317    /// Return a destructive iterator over the contents of this block.
318    /// It will give ownership of the returned `BlockItem` objects.
319    pub fn drain(&mut self) -> std::vec::Drain<'_, BlockItem> {
320        self.v.drain(..)
321    }
322
323    /// Return an iterator over all the `key = ...` fields in this block, ignoring the loose values
324    /// and loose blocks.
325    pub fn iter_fields(&self) -> IterFields<'_> {
326        IterFields { iter: self.v.iter(), warn: false }
327    }
328
329    /// Return an iterator over all the `key = ...` fields in this block, while warning about loose values
330    /// and loose blocks.
331    #[allow(dead_code)] // Not used by all games
332    pub fn iter_fields_warn(&self) -> IterFields<'_> {
333        IterFields { iter: self.v.iter(), warn: true }
334    }
335
336    /// Return an iterator over all the `key = value` fields in this block, ignoring other kinds of contents.
337    pub fn iter_assignments(&self) -> IterAssignments<'_> {
338        IterAssignments { iter: self.v.iter(), warn: false }
339    }
340
341    /// Return an iterator over all the `key = value` fields in this block, while warning about
342    /// every other kind of content.
343    #[allow(dead_code)] // It's here for symmetry
344    pub fn iter_assignments_warn(&self) -> IterAssignments<'_> {
345        IterAssignments { iter: self.v.iter(), warn: true }
346    }
347
348    /// Return an iterator over all the `key = { ... }` fields in this block, ignoring other kinds of contents.
349    pub fn iter_definitions(&self) -> IterDefinitions<'_> {
350        IterDefinitions { iter: self.v.iter(), warn: false }
351    }
352
353    /// Return an iterator over all the `key = { ... }` fields in this block, while warning about
354    /// every other kind of content.
355    pub fn iter_definitions_warn(&self) -> IterDefinitions<'_> {
356        IterDefinitions { iter: self.v.iter(), warn: true }
357    }
358
359    /// Return an iterator over all the `key = value` and `key = { ... }` fields in this block,
360    /// ignoring every other kind of content.
361    /// It differs from [`Block::iter_fields`] in that it requires the comparator to be `=`.
362    #[allow(dead_code)] // It's here for symmetry
363    pub fn iter_assignments_and_definitions(&self) -> IterAssignmentsAndDefinitions<'_> {
364        IterAssignmentsAndDefinitions { iter: self.v.iter(), warn: false }
365    }
366
367    /// Return an iterator over all the `key = value` and `key = { ... }` fields in this block,
368    /// while warning about every other kind of content.
369    /// It differs from [`Block::iter_fields_warn`] in that it requires the comparator to be `=`.
370    pub fn iter_assignments_and_definitions_warn(&self) -> IterAssignmentsAndDefinitions<'_> {
371        IterAssignmentsAndDefinitions { iter: self.v.iter(), warn: true }
372    }
373
374    /// Like [`Block::iter_definitions_warn`] but it's a destructive iterator that gives ownership
375    /// over the returned definitions.
376    pub fn drain_definitions_warn(&mut self) -> DrainDefinitions<'_> {
377        DrainDefinitions { iter: self.v.drain(..) }
378    }
379
380    /// Like [`Block::iter_assignments_warn`] but it's a destructive iterator that gives ownership
381    /// over the returned assignments.
382    #[allow(dead_code)] // Not used by all games
383    pub fn drain_assignments_warn(&mut self) -> DrainAssignments<'_> {
384        DrainAssignments { iter: self.v.drain(..) }
385    }
386
387    /// Iterate over the loose values in the block.
388    pub fn iter_values(&self) -> IterValues<'_> {
389        IterValues { iter: self.v.iter(), warn: false }
390    }
391
392    /// Iterate over the loose values in the block, while warning about everything else.
393    pub fn iter_values_warn(&self) -> IterValues<'_> {
394        IterValues { iter: self.v.iter(), warn: true }
395    }
396
397    /// Iterate over the loose sub-blocks in the block.
398    #[allow(dead_code)]
399    pub fn iter_blocks(&self) -> IterBlocks<'_> {
400        IterBlocks { iter: self.v.iter(), warn: false }
401    }
402
403    /// Iterate over the loose sub-blocks in the block, while warning about everything else.
404    #[allow(dead_code)] // It's here for symmetry
405    pub fn iter_blocks_warn(&self) -> IterBlocks<'_> {
406        IterBlocks { iter: self.v.iter(), warn: true }
407    }
408
409    /// Search through the history fields in this block and return the block or value the
410    /// field `name` would have at the given `date`. The field value that's directly in this block,
411    /// not in any history block, is considered to be the field value at the beginning of time.
412    /// History fields are ones that have a date as the key, like `900.1.1 = { ... }`.
413    #[allow(dead_code)] // Not used by all games
414    pub fn get_field_at_date(&self, name: &str, date: Date) -> Option<&BV> {
415        let mut found_date: Option<Date> = None;
416        let mut found: Option<&BV> = None;
417
418        for Field(key, _, bv) in self.iter_fields() {
419            if key.is(name) && found_date.is_none() {
420                found = Some(bv);
421            } else if let Ok(isdate) = Date::try_from(key) {
422                if isdate <= date && (found_date.is_none() || found_date.unwrap() < isdate) {
423                    if let Some(value) = bv.get_block().and_then(|b| b.get_field(name)) {
424                        found_date = Some(isdate);
425                        found = Some(value);
426                    }
427                }
428            }
429        }
430        found
431    }
432
433    /// Just like [`Block::get_field_at_date`] but only for fields that have values (not blocks).
434    #[allow(dead_code)] // Not used by all games
435    pub fn get_field_value_at_date(&self, name: &str, date: Date) -> Option<&Token> {
436        self.get_field_at_date(name, date).and_then(BV::get_value)
437    }
438
439    /// Return a sorted vector of macro parameters taken by this block.
440    /// Macro parameters are between `$` like `$CHARACTER$`.
441    pub fn macro_parms(&self) -> Vec<&'static str> {
442        if let Some(block_source) = &self.source {
443            let (ref source, _) = **block_source;
444            let mut vec = source
445                .iter()
446                .filter(|mc| mc.kind() == MacroComponentKind::Macro)
447                .map(|mc| mc.token().as_str())
448                .collect::<Vec<_>>();
449            vec.sort_unstable();
450            vec.dedup();
451            vec
452        } else {
453            Vec::new()
454        }
455    }
456
457    /// Expand a block that has macro parameters by substituting arguments for those parameters,
458    /// then re-parsing the script, that links the expanded content back to `loc`.
459    pub fn expand_macro(
460        &self,
461        args: &[(&str, Token)],
462        loc: Loc,
463        global: &PdxfileMemory,
464    ) -> Option<Block> {
465        let link_index = MACRO_MAP.get_or_insert_loc(loc);
466        if let Some(block_source) = &self.source {
467            let (ref source, ref local) = **block_source;
468            let mut content = Vec::new();
469            for part in source {
470                let token = part.token();
471                match part.kind() {
472                    MacroComponentKind::Source => {
473                        content.push(token.clone().linked(Some(link_index)));
474                    }
475                    MacroComponentKind::Macro => {
476                        for (arg, val) in args {
477                            if token.is(arg) {
478                                // Make the replacement be a token that has the substituted content, but the original's loc,
479                                // and a loc.link back to the caller's parameter. This gives the best error messages.
480                                let mut val = val.clone();
481                                let orig_loc = val.loc;
482                                val.loc = token.loc;
483                                val.loc.column -= 1; // point at the $, it looks better
484                                val.loc.link_idx = Some(MACRO_MAP.get_or_insert_loc(orig_loc));
485                                content.push(val);
486                                break;
487                            }
488                        }
489                    }
490                }
491            }
492            Some(parse_pdx_macro(&content, global, local))
493        } else {
494            None
495        }
496    }
497
498    /// Return true iff this block has the same block items in the same order as `other`,
499    /// including equivalence of blocks inside them.
500    pub fn equivalent(&self, other: &Self) -> bool {
501        if self.v.len() != other.v.len() {
502            return false;
503        }
504        for i in 0..self.v.len() {
505            if !self.v[i].equivalent(&other.v[i]) {
506                return false;
507            }
508        }
509        true
510    }
511
512    /// Create a version of this block where the `tag` is combined with a token that follows it.
513    /// Example: `color1 = list colorlist` becomes `color1 = list"colorlist` (where the `"` character
514    /// is used as the separator because it can't show up in normal parsing).
515    ///
516    /// This function is used as a last resort when validating awkward syntax.
517    #[allow(dead_code)]
518    pub fn condense_tag(self, tag: &str) -> Self {
519        let mut other = Block::new(self.loc);
520        let mut reserve: Option<(Token, Comparator, Token)> = None;
521        for item in self.v {
522            if let Some((rkey, rcmp, mut rtoken)) = reserve {
523                if let BlockItem::Value(token) = item {
524                    // Combine current value with reserved assignment
525                    rtoken.combine(&token, '"');
526                    other.add_key_bv(rkey, rcmp, BV::Value(rtoken));
527                    reserve = None;
528                    // This consumed the current item
529                    continue;
530                }
531                other.add_key_bv(rkey, rcmp, BV::Value(rtoken));
532                reserve = None;
533            }
534            if let BlockItem::Field(Field(key, cmp, bv)) = item {
535                match bv {
536                    BV::Value(token) => {
537                        if token.is(tag) {
538                            reserve = Some((key, cmp, token));
539                            continue;
540                        }
541                        other.add_key_bv(key, cmp, BV::Value(token));
542                    }
543                    BV::Block(block) => {
544                        other.add_key_bv(key, cmp, BV::Block(block.condense_tag(tag)));
545                    }
546                }
547            } else {
548                other.add_item(item);
549            }
550        }
551        other
552    }
553}
554
555/// An iterator for (key, value) pairs. It is returned by [`Block::iter_assignments`].
556#[derive(Clone, Debug)]
557pub struct IterAssignments<'a> {
558    iter: std::slice::Iter<'a, BlockItem>,
559    warn: bool,
560}
561
562impl<'a> Iterator for IterAssignments<'a> {
563    type Item = (&'a Token, &'a Token);
564
565    fn next(&mut self) -> Option<Self::Item> {
566        for item in self.iter.by_ref() {
567            if self.warn {
568                item.expect_assignment();
569            }
570            if let Some((key, token)) = item.get_assignment() {
571                return Some((key, token));
572            }
573        }
574        None
575    }
576}
577
578/// An iterator for (key, block) pairs. It is returned by [`Block::iter_definitions`].
579#[derive(Clone, Debug)]
580pub struct IterDefinitions<'a> {
581    iter: std::slice::Iter<'a, BlockItem>,
582    warn: bool,
583}
584
585impl<'a> Iterator for IterDefinitions<'a> {
586    type Item = (&'a Token, &'a Block);
587
588    fn next(&mut self) -> Option<Self::Item> {
589        for item in self.iter.by_ref() {
590            if self.warn {
591                item.expect_definition();
592            }
593            if let Some((key, block)) = item.get_definition() {
594                return Some((key, block));
595            }
596        }
597        None
598    }
599}
600
601/// An iterator for (key, bv) pairs. It is returned by [`Block::iter_assignments_and_definitions`].
602#[derive(Clone, Debug)]
603pub struct IterAssignmentsAndDefinitions<'a> {
604    iter: std::slice::Iter<'a, BlockItem>,
605    warn: bool,
606}
607
608impl<'a> Iterator for IterAssignmentsAndDefinitions<'a> {
609    type Item = (&'a Token, &'a BV);
610
611    fn next(&mut self) -> Option<Self::Item> {
612        for item in self.iter.by_ref() {
613            if self.warn {
614                item.expect_field();
615            }
616            if let BlockItem::Field(field) = item {
617                if !field.is_eq() {
618                    if self.warn {
619                        field.expect_eq();
620                    }
621                    continue;
622                }
623                return Some((field.key(), field.bv()));
624            }
625        }
626        None
627    }
628}
629
630/// An iterator for (key, block) pairs that transfers ownership.
631/// It is returned by [`Block::drain_definitions_warn`].
632#[derive(Debug)]
633pub struct DrainDefinitions<'a> {
634    iter: std::vec::Drain<'a, BlockItem>,
635}
636
637impl Iterator for DrainDefinitions<'_> {
638    type Item = (Token, Block);
639
640    fn next(&mut self) -> Option<Self::Item> {
641        for item in self.iter.by_ref() {
642            if let Some((key, block)) = item.expect_into_definition() {
643                return Some((key, block));
644            }
645        }
646        None
647    }
648}
649
650/// An iterator for (key, value) pairs that transfers ownership.
651/// It is returned by [`Block::drain_assignments_warn`].
652#[derive(Debug)]
653pub struct DrainAssignments<'a> {
654    iter: std::vec::Drain<'a, BlockItem>,
655}
656
657impl Iterator for DrainAssignments<'_> {
658    type Item = (Token, Token);
659
660    fn next(&mut self) -> Option<Self::Item> {
661        for item in self.iter.by_ref() {
662            if let Some((key, value)) = item.expect_into_assignment() {
663                return Some((key, value));
664            }
665        }
666        None
667    }
668}
669
670/// An iterator for [`Field`] structs, returning the fields of a block.
671/// It is returned by [`Block::iter_fields`].
672#[derive(Clone, Debug)]
673pub struct IterFields<'a> {
674    iter: std::slice::Iter<'a, BlockItem>,
675    warn: bool,
676}
677
678impl<'a> Iterator for IterFields<'a> {
679    type Item = &'a Field;
680
681    fn next(&mut self) -> Option<Self::Item> {
682        for item in self.iter.by_ref() {
683            if self.warn {
684                item.expect_field();
685            }
686            if let BlockItem::Field(field) = item {
687                return Some(field);
688            }
689        }
690        None
691    }
692}
693
694/// An iterator for values (tokens), returning the loose values of a block.
695/// It is returned by [`Block::iter_values`].
696#[derive(Clone, Debug)]
697pub struct IterValues<'a> {
698    iter: std::slice::Iter<'a, BlockItem>,
699    warn: bool,
700}
701
702impl<'a> Iterator for IterValues<'a> {
703    type Item = &'a Token;
704
705    fn next(&mut self) -> Option<Self::Item> {
706        for item in self.iter.by_ref() {
707            if self.warn {
708                item.expect_value();
709            }
710            if let BlockItem::Value(value) = item {
711                return Some(value);
712            }
713        }
714        None
715    }
716}
717
718/// An iterator returning the loose sub-blocks of a block.
719/// It is returned by [`Block::iter_blocks`].
720#[derive(Clone, Debug)]
721pub struct IterBlocks<'a> {
722    iter: std::slice::Iter<'a, BlockItem>,
723    warn: bool,
724}
725
726impl<'a> Iterator for IterBlocks<'a> {
727    type Item = &'a Block;
728
729    fn next(&mut self) -> Option<Self::Item> {
730        for item in self.iter.by_ref() {
731            if self.warn {
732                item.expect_block();
733            }
734            if let BlockItem::Block(block) = item {
735                return Some(block);
736            }
737        }
738        None
739    }
740}