libreda_lefdef/
def_parser.rs

1// Copyright (c) 2021-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Parser for DEF (Design Exchange Format).
7
8// TODO: Remove this once this module is finished.
9#![allow(unused_variables)]
10
11use crate::common::*;
12use crate::def_ast::*;
13use crate::stream_parser::LefDefLexer;
14pub use crate::stream_parser::LefDefParseError;
15use itertools::PeekingNext;
16use libreda_db::prelude as db;
17use libreda_stream_parser::{tokenize, Tokenized};
18use std::collections::BTreeMap;
19use std::io::Read;
20use std::str::FromStr;
21
22/// Configuration for the DEF reader.
23#[derive(Copy, Clone, Default, Debug)]
24pub struct DEFReaderConfig {
25    /// Ignore errors that still allow to parse the rest of the DEF file.
26    pub ignore_non_fatal_errors: bool,
27}
28
29/// Parse a DEF file from byte stream.
30pub fn read_def_bytes<R: Read>(reader: &mut R) -> Result<DEF, LefDefParseError> {
31    read_def_chars(reader.bytes().map(|b| b.unwrap() as char))
32}
33
34/// Parse a DEF file from byte stream.
35pub fn read_def_bytes_with_config<R: Read>(
36    config: &DEFReaderConfig,
37    reader: &mut R,
38) -> Result<DEF, LefDefParseError> {
39    read_def_chars_with_config(config, reader.bytes().map(|b| b.unwrap() as char))
40}
41
42/// Parse a DEF file from an iterator over `char`s.
43/// This calls `read_def_with_config()` with default configuration options.
44pub fn read_def_chars<I>(chars: I) -> Result<DEF, LefDefParseError>
45where
46    I: Iterator<Item = char>,
47{
48    read_def_chars_with_config(&DEFReaderConfig::default(), chars)
49}
50
51/// Parse a DEF file from an iterator over `char`s.
52pub fn read_def_chars_with_config<I>(
53    config: &DEFReaderConfig,
54    chars: I,
55) -> Result<DEF, LefDefParseError>
56where
57    I: Iterator<Item = char>,
58{
59    let mut line_num = 1;
60    let mut char_num = 1; // Position on the line.
61
62    // Count newlines.
63    let line_count = chars.inspect(|&c| {
64        char_num += 1;
65        if c == '\n' {
66            line_num += 1;
67            char_num = 0;
68        }
69    });
70
71    let result = read_def_impl(config, line_count);
72
73    if result.is_err() {
74        log::error!("DEF error on line: {} (at {})", line_num, char_num);
75    }
76
77    result
78}
79
80/// Read wiring statement.
81/// Tokens must start with one of COVER, FIXED, ROUTED or NOSHIELD.
82fn read_regular_wiring<I: Iterator<Item = char> + PeekingNext>(
83    tk: &mut Tokenized<I, LefDefLexer>,
84) -> Result<RegularWiring, LefDefParseError> {
85    let wiring_class: WiringClass = tk.take_and_parse()?;
86
87    let mut wiring = RegularWiring {
88        class: wiring_class,
89        wiring: vec![],
90    };
91
92    // Read wiring segments.
93    loop {
94        let layer_name = tk.take_str()?;
95
96        let mut wiring_statement = RegularWiringStatement {
97            start_layer_name: layer_name,
98            style_num: 0,
99            taper_rule: None,
100            routing_points: vec![],
101        };
102
103        if tk.test_str("TAPER")? {
104        } else if tk.test_str("TAPERRULE")? {
105            wiring_statement.taper_rule = Some(tk.take_str()?);
106        }
107
108        if tk.test_str("STYLE")? {
109            wiring_statement.style_num = tk.take_and_parse()?;
110        }
111
112        // The previous point of the path.
113        // This is used to resolve implicit coordinates like `( 0 0 ) ( * 1 )`.
114        let mut prev_point: Option<(db::Coord, db::Coord)> = None;
115
116        // Read a point of the form `( x y [extvalue] )`.
117        // x and y can be `*` and refer to the previous value.
118        fn read_path_point<T: FromStr + Copy, I: Iterator<Item = char> + PeekingNext>(
119            tk: &mut Tokenized<I, LefDefLexer>,
120            prev_point: &Option<(T, T)>,
121        ) -> Result<((T, T), Option<T>), LefDefParseError> {
122            // Read point.
123            tk.expect_str("(")?;
124            let x = if tk.test_str("*")? {
125                // Implicit x-coordinate.
126                prev_point
127                    .ok_or(LefDefParseError::Other(
128                        "x-coordinate not yet defined. Cannot use '*'.",
129                    ))?
130                    .0
131            } else {
132                // Explicit y-coordinate.
133                tk.take_and_parse()?
134            };
135            let y = if tk.test_str("*")? {
136                // Implicit y-coordinate.
137                prev_point
138                    .ok_or(LefDefParseError::Other(
139                        "x-coordinate not yet defined. Cannot use '*'.",
140                    ))?
141                    .1
142            } else {
143                // Explicit y-coordinate.
144                tk.take_and_parse()?
145            };
146
147            let ext_value = if !tk.test_str(")")? {
148                // There's an optional [extValue].
149                let ext_value = tk.take_and_parse()?;
150                tk.expect_str(")")?;
151                Some(ext_value)
152            } else {
153                None
154            };
155
156            Ok(((x, y), ext_value))
157        }
158
159        // Read the first point.
160        let (p, extvalue) = read_path_point(tk, &prev_point)?;
161        wiring_statement.routing_points.push(RoutingPoint::Point {
162            point: p.into(),
163            ext_value: None,
164            mask_num: None,
165        });
166        prev_point = Some(p);
167
168        // Read path points.
169        // TODO
170        while !tk.peeking_test_str(";")? && !tk.peeking_test_str("NEW")? {
171            let mut mask_num: Option<u8> = None;
172            let mut via_mask_num: Option<ViaMaskNum> = None;
173
174            if tk.test_str("VIRTUAL")? {
175                // Read the virtual point.
176                let (p, _extvalue) = read_path_point(tk, &prev_point)?;
177                // extvalue should be `None`.
178                prev_point = Some(p);
179                wiring_statement
180                    .routing_points
181                    .push(RoutingPoint::Virtual(p.into()));
182            } else {
183                let mut expect_via = false;
184                if tk.test_str("MASK")? {
185                    if tk.current_token_str().map(|s| s.len()) == Some(3) {
186                        // This is a 3-letter via mask number.
187                        via_mask_num = Some(tk.take_and_parse()?);
188                        expect_via = true;
189                    } else {
190                        // Single-digit mask number.
191                        mask_num = Some(tk.take_and_parse()?);
192                    }
193                }
194
195                if expect_via || !tk.peeking_test_str("(")? {
196                    if !expect_via && tk.test_str("RECT")? {
197                        // Draw a rectangle from the current point to the values defined by the deltas.
198                        tk.expect_str("(")?;
199                        let delta_x1: db::Coord = tk.take_and_parse()?;
200                        let delta_y1: db::Coord = tk.take_and_parse()?;
201                        let delta_x2: db::Coord = tk.take_and_parse()?;
202                        let delta_y2: db::Coord = tk.take_and_parse()?;
203                        tk.expect_str(")")?;
204
205                        let d1 = db::Vector::new(delta_x1, delta_y1);
206                        let d2 = db::Vector::new(delta_x2, delta_y2);
207
208                        let current_point: db::Point<_> = prev_point
209                            .ok_or_else(|| LefDefParseError::Other("Appearance of 'RECT' in a route but no current path point is defined.".into()))?
210                            .into();
211
212                        let rect = db::Rect::new(current_point + d1, current_point + d2);
213                        todo!("Store the rectangle");
214                        wiring_statement
215                            .routing_points
216                            .push(RoutingPoint::Rect { rect, mask_num });
217                    } else {
218                        // Via extension.
219                        let via_name = tk.take_str()?;
220                        let orient: Option<Orient> = if !tk.peeking_test_str("NEW")?
221                            && !tk.peeking_test_str(";")?
222                            && !tk.peeking_test_str("(")?
223                            && !tk.peeking_test_str("+")?
224                        {
225                            Some(tk.take_and_parse()?)
226                        } else {
227                            None
228                        };
229
230                        wiring_statement.routing_points.push(RoutingPoint::Via {
231                            via_name,
232                            orient,
233                            via_mask_num,
234                        });
235                    }
236                } else {
237                    let (p, ext_value) = read_path_point(tk, &prev_point)?;
238                    prev_point = Some(p.into());
239
240                    wiring_statement.routing_points.push(RoutingPoint::Point {
241                        point: p.into(),
242                        ext_value,
243                        mask_num,
244                    });
245                }
246            }
247        }
248
249        // Store the wiring statement.
250        wiring.wiring.push(wiring_statement);
251
252        if !tk.test_str("NEW")? {
253            break;
254        } else {
255            // NEW -> Continue with reading next wiring statement.
256        }
257    }
258
259    return Ok(wiring);
260}
261
262/// Read DEF VIAS - via declarations.
263fn read_vias<I: Iterator<Item = char> + PeekingNext>(
264    tk: &mut Tokenized<I, LefDefLexer>,
265) -> Result<BTreeMap<String, ViaDefinition>, LefDefParseError> {
266    let mut via_definitions: BTreeMap<String, ViaDefinition> = Default::default();
267
268    tk.expect_str("VIAS")?;
269    let num_vias: u32 = tk.take_and_parse()?;
270    tk.expect_str(";")?;
271
272    while tk.test_str("-")? {
273        let via_name = tk.take_str()?;
274
275        while tk.test_str("+")? {
276            if tk.test_str("VIARULE")? {
277                return Err(LefDefParseError::NotImplemented("VIAS/VIARULE"));
278            } else {
279                let mut via_geometries = Vec::new();
280
281                if tk.test_str("RECT")? {
282                    let layer = tk.take_str()?;
283                    let mask_num = if tk.test_str("MASK")? {
284                        Some(tk.take_and_parse()?)
285                    } else {
286                        None
287                    };
288                    let (p1, p2) = read_rect(tk)?;
289                    let rect = db::Rect::new(p1, p2);
290                    via_geometries.push(ViaGeometry {
291                        layer,
292                        mask_num,
293                        shape: RectOrPolygon::Rect(rect),
294                    });
295                } else if tk.test_str("POLYGON")? {
296                    let layer = tk.take_str()?;
297                    let mask_num = if tk.test_str("MASK")? {
298                        Some(tk.take_and_parse()?)
299                    } else {
300                        None
301                    };
302                    let points: Vec<(db::Coord, _)> = read_polygon(tk)?;
303                    let points = points.into_iter().map(|p| p.into()).collect();
304                    let polygon = db::SimplePolygon::new(points);
305                    via_geometries.push(ViaGeometry {
306                        layer,
307                        mask_num,
308                        shape: RectOrPolygon::Polygon(polygon),
309                    });
310                } else {
311                    return Err(LefDefParseError::UnexpectedToken(
312                        "RECT, POLYGON".into(),
313                        tk.take_str()?,
314                    ));
315                }
316
317                let via_def = ViaDefinition::ViaGeometry(via_geometries);
318                via_definitions.insert(via_name.clone(), via_def);
319            }
320        }
321        tk.expect_str(";")?;
322    }
323
324    tk.expect_str("END")?;
325    tk.expect_str("VIAS")?;
326
327    Ok(via_definitions)
328}
329
330/// Parse a DEF file from an iterator over `char`s.
331fn read_def_impl<I>(config: &DEFReaderConfig, chars: I) -> Result<DEF, LefDefParseError>
332where
333    I: Iterator<Item = char>,
334{
335    let mut design = DEF::default();
336
337    // Token stream.
338    let mut tk = tokenize(chars, LefDefLexer {});
339    tk.advance();
340
341    loop {
342        if tk.test_str("END")? {
343            // End of DEF file.
344            tk.expect_str("DESIGN")?;
345            break;
346        } else if tk.test_str("VERSION")? {
347            let version = tk.take_str()?;
348            design.version = Some(version);
349            tk.expect_str(";")?;
350        } else if tk.test_str("BUSBITCHARS")? {
351            let chars = tk.take_str()?;
352
353            if chars.len() == 2 {
354                let start = chars.chars().nth(0).unwrap();
355                let end = chars.chars().nth(1).unwrap();
356
357                if start == end {
358                    log::error!("Bus bit chars cannot be equal: {}", start);
359                    return Err(LefDefParseError::IllegalBusBitChars(start, end));
360                }
361
362                log::debug!("Bus bit chars: '{}' '{}'", start, end);
363                design.busbitchars = (start, end);
364            } else {
365                return Err(LefDefParseError::InvalidCharacter); // TODO: More precise error.
366            }
367
368            tk.expect_str(";")?;
369        } else if tk.test_str("NAMESCASESENSITIVE")? {
370            tk.expect_str("ON")
371                .map_err(|_| LefDefParseError::Other("Support only NAMESCASESENSITIVE ON."))?;
372            // TODO: OFF is not supported.
373            tk.expect_str(";")?;
374        } else if tk.test_str("DIVIDERCHAR")? {
375            let divchar = tk.take_str()?;
376
377            if divchar.len() == 1 {
378                design.dividerchar = divchar.chars().nth(0).unwrap();
379                log::debug!("Divider char: '{}'", design.dividerchar);
380            } else {
381                return Err(LefDefParseError::InvalidCharacter); // TODO: More precise error.
382            }
383
384            tk.expect_str(";")?;
385        } else if tk.test_str("DESIGN")? {
386            let design_name = tk.take_str()?;
387            tk.expect_str(";")?;
388            design.design_name = Some(design_name);
389        } else if tk.test_str("TECHNOLOGY")? {
390            let tech_name = tk.take_str()?;
391            tk.expect_str(";")?;
392            design.technology = Some(tech_name);
393        } else if tk.test_str("UNITS")? {
394            tk.expect_str("DISTANCE")?;
395            tk.expect_str("MICRONS")?;
396            let units = tk.take_and_parse()?;
397            tk.expect_str(";")?;
398            design.units = units;
399        } else if tk.test_str("HISTORY")? {
400            let mut text = String::new();
401            // Read all text until ';'.
402            while !tk.test_str(";")? {
403                if let Some(s) = tk.current_token_str() {
404                    if !text.is_empty() {
405                        text.push(' '); // Put a space between words.
406                    }
407                    text.extend(s.chars());
408                }
409                tk.advance();
410            }
411            design.history.push(text);
412        } else if tk.test_str("PROPERTYDEFINITIONS")? {
413            loop {
414                if tk.test_str("END")? {
415                    tk.expect_str("PROPERTYDEFINITIONS")?;
416                    break;
417                } else {
418                    let property_object_type: DEFPropertyObjectType = tk.take_and_parse()?;
419                    let property_name = tk.take_str()?;
420                    let property_type: PropertyType = tk.take_and_parse()?;
421
422                    // Read allowed range of property value.
423                    let mut range = None;
424                    let mut default_value = None;
425                    match property_type {
426                        PropertyType::Integer => {
427                            if tk.test_str("RANGE")? {
428                                // Limit of property values.
429                                let min = tk.take_and_parse()?;
430                                let max = tk.take_and_parse()?;
431
432                                range = Some((PropertyValue::Int(min), PropertyValue::Int(max)));
433                            }
434
435                            if !tk.peeking_test_str(";")? {
436                                let default = tk.take_and_parse()?;
437                                default_value = Some(PropertyValue::Int(default));
438                            }
439                            tk.expect_str(";")?;
440                        }
441                        PropertyType::Real => {
442                            if tk.test_str("RANGE")? {
443                                // Limit of property values.
444                                let min = tk.take_and_parse()?;
445                                let max = tk.take_and_parse()?;
446
447                                range = Some((PropertyValue::Real(min), PropertyValue::Real(max)));
448                            }
449                            if !tk.peeking_test_str(";")? {
450                                let default = tk.take_and_parse()?;
451                                default_value = Some(PropertyValue::Real(default));
452                            }
453                        }
454                        PropertyType::String => {
455                            // No limits defined.
456
457                            if !tk.peeking_test_str(";")? {
458                                let default = tk.take_str()?;
459                                default_value = Some(PropertyValue::String(default));
460                            }
461                        }
462                    }
463                    tk.expect_str(";")?;
464
465                    let property_definition = DEFPropertyDefinition {
466                        object_type: property_object_type,
467                        property_type,
468                        range,
469                        default_value,
470                    };
471
472                    // TODO: Store property definition.
473                    design
474                        .property_definitions
475                        .insert(property_name, property_definition);
476                }
477            }
478            log::warn!("Skipping PROPERTYDEFINITIONS.");
479        } else if tk.test_str("DIEAREA")? {
480            // Die area can be a rectangle or a rectilinear polygon.
481            let points = read_polygon(&mut tk)?;
482            let points: Vec<db::Point<db::SInt>> = points.into_iter().map(|p| p.into()).collect();
483
484            let die_area = if points.len() < 2 {
485                // Illegal die area.
486                log::error!("DIEAREA must consist of two or more points.");
487                return Err(LefDefParseError::Other(
488                    "Illegal die area. Must have two or more vertices.",
489                ));
490            } else if points.len() == 2 {
491                // Is a rectangle.
492                let rect: db::Rect<db::SInt> = db::Rect::new(points[0], points[1]);
493                let poly = db::SimpleRPolygon::from(rect);
494                poly
495            } else {
496                // Is a polygon.
497                let poly = db::SimpleRPolygon::try_new(&points);
498                if poly.is_none() {
499                    log::error!("DIEAREA polygon is not rectilinear.");
500                }
501                if config.ignore_non_fatal_errors {
502                    poly.unwrap_or(db::SimpleRPolygon::empty())
503                } else {
504                    poly.ok_or(LefDefParseError::Other(
505                        "DIEAREA polygon is not rectilinear.",
506                    ))?
507                }
508            };
509            design.die_area = Some(die_area);
510        } else if tk.test_str("ROW")? {
511            let row_name = tk.take_str()?;
512            let site_name = tk.take_str()?;
513            let orig_x: db::Coord = tk.take_and_parse()?;
514            let orig_y: db::Coord = tk.take_and_parse()?;
515            // Orientation of all sites in the row.
516            let site_orient: Orient = tk.take_and_parse()?;
517            let mut step_pattern = RowStepPattern::default();
518            if tk.test_str("DO")? {
519                step_pattern.num_x = tk.take_and_parse()?;
520                tk.expect_str("BY")?;
521                step_pattern.num_y = tk.take_and_parse()?;
522                if tk.test_str("STEP")? {
523                    let step_x = tk.take_and_parse()?;
524                    let step_y = tk.take_and_parse()?;
525                    step_pattern.step = Some((step_x, step_y));
526                }
527            }
528            // Read custom properties.
529            let mut properties = BTreeMap::new();
530            while tk.test_str("+")? {
531                tk.expect_str("PROPERTY")?;
532                while !tk.peeking_test_str("+")? {
533                    if let Some((name, value)) =
534                        read_def_property(&mut design.property_definitions, &mut tk)?
535                    {
536                        // Store property.
537                        properties.insert(name, value);
538                    }
539                }
540            }
541
542            // Create the row data structure.
543            let row = Row {
544                site_name,
545                orig: (orig_x, orig_y),
546                site_orient,
547                step_pattern,
548                properties,
549            };
550
551            tk.expect_str(";")?;
552
553            // Store the row.
554            design.rows.insert(row_name, row);
555        } else if tk.test_str("TRACKS")? {
556            let is_horizontal = tk.test_str("Y")?;
557            if !is_horizontal {
558                tk.expect_str("X")?;
559            }
560            // X or Y coordinate of the row.
561            let start = tk.take_and_parse()?;
562            tk.expect_str("DO")?;
563            let num_tracks = tk.take_and_parse()?;
564            tk.expect_str("STEP")?;
565            let step = tk.take_and_parse()?; // Space between tracks.
566
567            let mask = if tk.test_str("MASK")? {
568                let mask_num = tk.take_and_parse()?;
569                let same_mask = tk.test_str("SAMEMASK")?;
570                Some((mask_num, same_mask))
571            } else {
572                None
573            };
574
575            let mut layers = Vec::new();
576            if tk.test_str("LAYER")? {
577                while !tk.peeking_test_str(";")? {
578                    // Routing layers used for this tracks.
579                    let layer_name = tk.take_str()?;
580                    layers.push(layer_name);
581                }
582            }
583
584            tk.expect_str(";")?;
585
586            let tracks = Tracks {
587                is_horizontal,
588                start,
589                num_tracks,
590                step,
591                mask,
592                layers,
593            };
594
595            // Store track.
596            design.tracks.push(tracks);
597        } else if tk.test_str("GCELLGRID")? {
598            let is_horizontal = tk.test_str("Y")?;
599            if !is_horizontal {
600                tk.expect_str("X")?;
601            }
602
603            // X or Y coordinate of the row.
604            let start: db::SInt = tk.take_and_parse()?;
605            tk.expect_str("DO")?;
606            let num_tracks: u32 = tk.take_and_parse()?;
607            tk.expect_str("STEP")?;
608            let space: db::SInt = tk.take_and_parse()?; // Space between tracks.
609
610            tk.expect_str(";")?;
611
612            // TODO: Store grid information.
613            design.gcell_grid.push(());
614        } else if tk.peeking_test_str("VIAS")? {
615            design.vias = read_vias(&mut tk)?;
616        } else if tk.test_str("STYLES")? {
617            return Err(LefDefParseError::NotImplemented("STYLES"));
618        } else if tk.test_str("NONDEFAULTRULES")? {
619            return Err(LefDefParseError::NotImplemented("NONDEFAULTRULES"));
620        } else if tk.test_str("REGIONS")? {
621            let _num_regions: u32 = tk.take_and_parse()?;
622
623            while tk.test_str("-")? {
624                let mut region = Region::default();
625                let region_name = tk.take_str()?;
626                while !tk.peeking_test_str("+")? {
627                    // Read rectangles.
628                    let p1 = read_point(&mut tk)?;
629                    let p2 = read_point(&mut tk)?;
630                    let rect: db::Rect<db::SInt> = db::Rect::new(p1, p2);
631                    region.regions.push(rect);
632                }
633
634                while tk.test_str("+")? {
635                    if tk.test_str("TYPE")? {
636                        region.region_type = Some(tk.take_and_parse()?);
637                    } else if tk.test_str("PROPERTY")? {
638                        while !tk.peeking_test_str("+")? {
639                            if let Some((name, value)) =
640                                read_def_property(&mut design.property_definitions, &mut tk)?
641                            {
642                                // TODO: Store property. Name and type must match the property definitions.
643                            }
644                        }
645                    }
646                }
647
648                design.regions.insert(region_name, region);
649            }
650
651            tk.expect_str("END")?;
652            tk.expect_str("REGIONS")?;
653        } else if tk.test_str("COMPONENTMASKSHIFT")? {
654            return Err(LefDefParseError::NotImplemented("COMPONENTMASKSHIFT"));
655        } else if tk.test_str("COMPONENTS")? {
656            let num_components: u32 = tk.take_and_parse()?;
657            design.components.reserve(num_components as usize);
658            tk.expect_str(";")?;
659
660            while tk.test_str("-")? {
661                let mut component = Component::default();
662
663                component.name = tk.take_str()?;
664                component.model_name = tk.take_str()?;
665
666                while tk.test_str("+")? {
667                    if tk.test_str("EEQMASTER")? {
668                        component.eeq_master = Some(tk.take_str()?);
669                    } else if tk.test_str("SOURCE")? {
670                        component.source = tk.take_and_parse()?;
671                    } else if tk.test_str("FIXED")? {
672                        // Cannot be moved by automatic tools.
673                        let point: (db::SInt, db::SInt) = read_point(&mut tk)?;
674                        let orient: Orient = tk.take_and_parse()?;
675                        component.position = Some((point.into(), orient, true));
676                    } else if tk.test_str("COVER")? {
677                        // Cannot be moved by automatic tools nor interactive commands.
678                        let point: (db::SInt, db::SInt) = read_point(&mut tk)?;
679                        let orient: Orient = tk.take_and_parse()?;
680                        component.position = Some((point.into(), orient, true));
681                    } else if tk.test_str("PLACED")? {
682                        // Cannot be moved by automatic tools.
683                        let point: (db::SInt, db::SInt) = read_point(&mut tk)?;
684                        let orient: Orient = tk.take_and_parse()?;
685                        component.position = Some((point.into(), orient, false));
686                    } else if tk.test_str("UNPLACED")? {
687                        // Component is not placed yet.
688                        component.position = None;
689                    } else if tk.test_str("HALO")? {
690                        let soft = tk.test_str("SOFT")?;
691                        let left = tk.take_and_parse()?;
692                        let bottom = tk.take_and_parse()?;
693                        let right = tk.take_and_parse()?;
694                        let top = tk.take_and_parse()?;
695                        component.halo = Some((soft, left, bottom, right, top));
696                    } else if tk.test_str("ROUTEHALO")? {
697                        let halo_dist: db::SInt = tk.take_and_parse()?;
698                        let min_layer = tk.take_str()?;
699                        let max_layer = tk.take_str()?;
700                        // TODO
701                    } else if tk.test_str("WEIGHT")? {
702                        // Specify how close the component should stay near
703                        // to the original location during automated placement.
704                        // Default is 0.
705                        component.weight = tk.take_and_parse()?;
706                    } else if tk.test_str("REGION")? {
707                        // Name of the region in which the component should be placed.
708                        // If the bounding box of the component is larger than the region
709                        // issue an error message and ignore this argument.
710
711                        let region_name = tk.take_str()?;
712
713                        if let Some(region) = design.regions.get(&region_name) {
714                            // TODO.
715                            component.region = Some(region_name);
716                        } else {
717                            // Ignore the region statement.
718                            log::error!(
719                                "Ignore region statement. No such region: '{}'",
720                                &region_name
721                            );
722                        }
723                    } else if tk.test_str("PROPERTY")? {
724                        while !tk.peeking_test_str("+")? {
725                            if let Some((name, value)) =
726                                read_def_property(&mut design.property_definitions, &mut tk)?
727                            {
728                                // Store property.
729                                component.properties.insert(name, value);
730                            }
731                        }
732                    } else {
733                        return Err(LefDefParseError::UnknownToken(
734                            tk.current_token_str().unwrap(),
735                        ));
736                    }
737                }
738
739                tk.expect_str(";")?;
740
741                design.components.push(component);
742            }
743            tk.expect_str("END")?;
744            tk.expect_str("COMPONENTS")?;
745        } else if tk.test_str("PINS")? {
746            let num_pins: usize = tk.take_and_parse()?;
747            tk.expect_str(";")?;
748
749            while tk.test_str("-")? {
750                let mut pin = Pin::default();
751                pin.pin_name = tk.take_str()?;
752                tk.expect_str("+")?;
753                tk.expect_str("NET")?;
754                pin.net_name = tk.take_str()?;
755
756                let mut current_port: Option<PinPort> = None;
757
758                while tk.test_str("+")? {
759                    if tk.test_str("SPECIAL")? {
760                        pin.special = true;
761                    } else if tk.test_str("DIRECTION")? {
762                        pin.direction = Some(tk.take_and_parse()?);
763                    } else if tk.test_str("NETEXPR")? {
764                        pin.net_expr = Some(tk.take_str()?);
765                    } else if tk.test_str("SUPPLYSENSITIVITY")? {
766                        pin.supply_sensitivity = Some(tk.take_str()?);
767                    } else if tk.test_str("GROUNDSENSITIVITY")? {
768                        pin.ground_sensitivity = Some(tk.take_str()?);
769                    } else if tk.test_str("USE")? {
770                        pin.signal_use = tk.take_and_parse()?;
771                    } else if tk.test_str("PORT")? {
772                        if let Some(port) = current_port.take() {
773                            pin.ports.push(port);
774                        };
775                        current_port = Some(PinPort::default()); // Define a new port.
776                        let port = current_port.as_mut().unwrap();
777                    } else if tk.test_str("LAYER")? {
778                        let layer_name = tk.take_str()?;
779
780                        let mask_num = if tk.test_str("MASK")? {
781                            Some(tk.take_and_parse()?)
782                        } else {
783                            None
784                        };
785
786                        let mut spacing_or_width = None;
787                        if tk.test_str("SPACING")? {
788                            let min_spacing = tk.take_and_parse()?;
789                            spacing_or_width =
790                                Some(SpacingOrDesignRuleWidth::MinSpacing(min_spacing));
791                        }
792                        if tk.test_str("DESIGNRULEWIDTH")? {
793                            let effective_width = tk.take_and_parse()?;
794                            spacing_or_width =
795                                Some(SpacingOrDesignRuleWidth::DesignRuleWidth(effective_width));
796                        }
797
798                        let p1: (db::SInt, db::SInt) = read_point(&mut tk)?;
799                        let p2: (db::SInt, db::SInt) = read_point(&mut tk)?;
800                        let rect = db::Rect::new(p1, p2);
801
802                        current_port
803                            .get_or_insert(Default::default())
804                            .port_statements
805                            .push(PinPortStatement::Layer {
806                                layer_name,
807                                mask_num,
808                                spacing_or_width,
809                                rect,
810                            });
811                    } else if tk.test_str("POLYGON")? {
812                        let layer_name = tk.take_str()?;
813
814                        let mask_num = if tk.test_str("MASK")? {
815                            Some(tk.take_and_parse()?)
816                        } else {
817                            None
818                        };
819
820                        let mut spacing_or_width = None;
821                        if tk.test_str("SPACING")? {
822                            let min_spacing = tk.take_and_parse()?;
823                            spacing_or_width =
824                                Some(SpacingOrDesignRuleWidth::MinSpacing(min_spacing));
825                        }
826                        if tk.test_str("DESIGNRULEWIDTH")? {
827                            let effective_width = tk.take_and_parse()?;
828                            spacing_or_width =
829                                Some(SpacingOrDesignRuleWidth::DesignRuleWidth(effective_width));
830                        }
831
832                        let points = read_polygon(&mut tk)?;
833                        let polygon = points.into_iter().collect();
834
835                        current_port
836                            .get_or_insert(Default::default())
837                            .port_statements
838                            .push(PinPortStatement::Polygon {
839                                layer_name,
840                                mask_num,
841                                spacing_or_width,
842                                polygon,
843                            });
844                    } else if tk.test_str("VIA")? {
845                        let port = current_port.as_mut().unwrap();
846
847                        let via_name = tk.take_str()?;
848
849                        let mask_num = if tk.test_str("MASK")? {
850                            // Via mask num is encoded as a three-digit hex number
851                            // Of the form <topMaskNum><cutMaskNum><bottomMaskNum>.
852                            Some(tk.take_and_parse()?)
853                        } else {
854                            None
855                        };
856
857                        let location: (db::SInt, db::SInt) = read_point(&mut tk)?;
858
859                        current_port
860                            .get_or_insert(Default::default())
861                            .port_statements
862                            .push(PinPortStatement::Via {
863                                via_name,
864                                mask_num,
865                                location: location.into(),
866                            });
867                    } else if tk.test_str("ANTENNAPINPARTIALMETALAREA")? {
868                        return Err(LefDefParseError::NotImplemented(
869                            "ANTENNAPINPARTIALMETALAREA",
870                        ));
871                    } else if tk.test_str("ANTENNAPINPARTIALMETALSIDEAREA")? {
872                        return Err(LefDefParseError::NotImplemented(
873                            "ANTENNAPINPARTIALMETALSIDEAREA",
874                        ));
875                    } else if tk.test_str("ANTENNAPINPARTIALCUTAREA")? {
876                        return Err(LefDefParseError::NotImplemented("ANTENNAPINPARTIALCUTAREA"));
877                    } else if tk.test_str("ANTENNAPINDIFFAREA")? {
878                        return Err(LefDefParseError::NotImplemented("ANTENNAPINDIFFAREA"));
879                    } else if tk.test_str("ANTENNAPINDIFFAREA")? {
880                        return Err(LefDefParseError::NotImplemented("ANTENNAPINDIFFAREA"));
881                    } else if tk.test_str("ANTENNAMODEL")? {
882                        return Err(LefDefParseError::NotImplemented("ANTENNAMODEL"));
883                    } else if tk.test_str("ANTENNAPINGATEAREA")? {
884                        return Err(LefDefParseError::NotImplemented("ANTENNAPINGATEAREA"));
885                    } else if tk.test_str("ANTENNAPINMAXAREACAR")? {
886                        return Err(LefDefParseError::NotImplemented("ANTENNAPINMAXAREACAR"));
887                    } else if tk.test_str("ANTENNAPINMAXSIDEAREACAR")? {
888                        return Err(LefDefParseError::NotImplemented("ANTENNAPINMAXSIDEAREACAR"));
889                    } else if tk.test_str("ANTENNAPINMAXCUTCAR")? {
890                        return Err(LefDefParseError::NotImplemented("ANTENNAPINMAXCUTCAR"));
891                    } else {
892                        return Err(LefDefParseError::UnexpectedToken(
893                            "".to_string(),
894                            tk.current_token_str().unwrap(),
895                        ));
896                    }
897                }
898
899                // Store the current port, if there's any.
900                if let Some(port) = current_port.take() {
901                    pin.ports.push(port);
902                };
903
904                design.pins.push(pin);
905            }
906
907            if design.pins.len() != num_pins {
908                log::debug!(
909                    "Mismatch in announced number of pins ({}) and actual number of pins ({}).",
910                    num_pins,
911                    design.pins.len()
912                );
913            }
914
915            tk.expect_str("END")?;
916            tk.expect_str("PINS")?;
917        } else if tk.test_str("PINPROPERTIES")? {
918            return Err(LefDefParseError::NotImplemented("PINPROPERTIES"));
919        } else if tk.test_str("BLOCKAGES")? {
920            let num_blockages: u32 = tk.take_and_parse()?;
921            design.blockages.reserve(num_blockages as usize);
922            tk.expect_str(";")?;
923
924            while tk.test_str("-")? {
925                if tk.test_str("LAYER")? {
926                    let mut blk = LayerBlockage::default();
927                    blk.layer = tk.take_str()?;
928
929                    while tk.test_str("+")? {
930                        if tk.test_str("SLOTS")? {
931                            blk.slots = true;
932                        } else if tk.test_str("FILLS")? {
933                            blk.fills = true;
934                        } else if tk.test_str("PUSHDOWN")? {
935                            blk.pushdown = true;
936                        } else if tk.test_str("EXCEPTPGNET")? {
937                            blk.except_pg_net = true;
938                        } else if tk.test_str("COMPONENT")? {
939                            blk.component = Some(tk.take_str()?);
940                        } else if tk.test_str("SPACING")? {
941                            let spacing = tk.take_and_parse()?;
942                            blk.spacing_or_designrule_width =
943                                Some(SpacingOrDesignRuleWidth::MinSpacing(spacing));
944                        } else if tk.test_str("DESIGNRULEWIDTH")? {
945                            let width = tk.take_and_parse()?;
946                            blk.spacing_or_designrule_width =
947                                Some(SpacingOrDesignRuleWidth::DesignRuleWidth(width));
948                        } else if tk.test_str("MASK")? {
949                            let mask_num = tk.take_and_parse()?;
950                            blk.mask_num = Some(mask_num);
951                        } else {
952                            return Err(LefDefParseError::UnexpectedToken(
953                                "SLOTS, FILLS, PUSHDOWN, EXCEPTPGNET, SPACING, DESIGNRULEWIDTH or MASK".to_string(),
954                                tk.current_token_str().unwrap(),
955                            ));
956                        }
957                    }
958
959                    while !tk.test_str(";")? {
960                        if tk.test_str("RECT")? {
961                            let (p1, p2) = read_rect(&mut tk)?;
962                            let rect = db::Rect::new(p1, p2);
963                            blk.blockage_shapes.push(RectOrPolygon::Rect(rect));
964                        } else if tk.test_str("POLYGON")? {
965                            let points = read_polygon(&mut tk)?;
966                            let poly = db::SimplePolygon::from(points);
967                            blk.blockage_shapes.push(RectOrPolygon::Polygon(poly));
968                        } else {
969                            return Err(LefDefParseError::UnexpectedToken(
970                                "RECT or POLYGON".to_string(),
971                                tk.current_token_str().unwrap(),
972                            ));
973                        }
974                    }
975                    design.blockages.push(Blockage::LayerBlockage(blk));
976                } else if tk.test_str("PLACEMENT")? {
977                    let mut blk = PlacementBlockage::default();
978                    while tk.test_str("+")? {
979                        if tk.test_str("SOFT")? {
980                            blk.blockage_type = Some(PlacementBlockageType::Soft);
981                        } else if tk.test_str("PARTIAL")? {
982                            let max_density = tk.take_and_parse()?;
983                            blk.blockage_type = Some(PlacementBlockageType::Partial(max_density));
984                        } else if tk.test_str("PUSHDOWN")? {
985                            blk.pushdown = true;
986                        } else if tk.test_str("COMPONENT")? {
987                            blk.component = Some(tk.take_str()?);
988                        } else {
989                            return Err(LefDefParseError::UnexpectedToken(
990                                "SOFT, PARTIAL, PUSHDOWN or COMPONENT".to_string(),
991                                tk.current_token_str().unwrap(),
992                            ));
993                        }
994                    }
995
996                    while !tk.test_str(";")? {
997                        tk.expect_str("RECT")?;
998                        let (p1, p2) = read_rect(&mut tk)?;
999                        let rect = db::Rect::new(p1, p2);
1000                        blk.rects.push(rect);
1001                    }
1002
1003                    design.blockages.push(Blockage::PlacementBlockage(blk));
1004                } else {
1005                    return Err(LefDefParseError::UnexpectedToken(
1006                        "LAYER of PLACEMENT".to_string(),
1007                        tk.current_token_str().unwrap(),
1008                    ));
1009                }
1010            }
1011            tk.expect_str("END")?;
1012            tk.expect_str("BLOCKAGES")?;
1013        } else if tk.test_str("SLOTS")? {
1014            return Err(LefDefParseError::NotImplemented("SLOTS"));
1015        } else if tk.test_str("FILLS")? {
1016            return Err(LefDefParseError::NotImplemented("FILLS"));
1017        } else if tk.test_str("SPECIALNETS")? {
1018            return Err(LefDefParseError::NotImplemented("SPECIALNETS"));
1019        } else if tk.test_str("NETS")? {
1020            let _num_nets: u32 = tk.take_and_parse()?;
1021            tk.expect_str(";")?;
1022            // design.nets.reserve(num_nets);
1023
1024            while tk.test_str("-")? {
1025                let mut net = Net::default();
1026
1027                if tk.test_str("MUSTJOIN")? {
1028                    let component_name = tk.take_str()?;
1029                    let pin_name = tk.take_str()?;
1030
1031                    net.mustjoin = Some(Mustjoin {
1032                        component_name,
1033                        pin_name,
1034                    })
1035                } else {
1036                    net.name = Some(tk.take_str()?);
1037
1038                    while tk.test_str("(")? {
1039                        let term = if tk.test_str("PIN")? {
1040                            let pin_name = tk.take_str()?;
1041                            NetTerminal::IoPin(pin_name)
1042                        } else {
1043                            let component_name = tk.take_str()?;
1044                            let pin_name = tk.take_str()?;
1045                            NetTerminal::ComponentPin {
1046                                component_name,
1047                                pin_name,
1048                            }
1049                        };
1050
1051                        if tk.test_str("+")? {
1052                            tk.expect_str("SYNTHESIZED")?;
1053                            // TODO: Store synthesized flag.
1054                        }
1055
1056                        net.terminals.push(term);
1057
1058                        tk.expect_str(")")?;
1059                    }
1060
1061                    while tk.test_str("+")? {
1062                        if tk.test_str("SHIELDNET")? {
1063                            net.shield_nets.push(tk.take_str()?);
1064                        } else if tk.test_str("VPIN")? {
1065                            // TODO
1066                            return Err(LefDefParseError::NotImplemented("VPIN"));
1067                        } else if tk.test_str("SUBNET")? {
1068                            // TODO
1069                            return Err(LefDefParseError::NotImplemented("SUBNET"));
1070                        } else if tk.test_str("XTALK")? {
1071                            net.xtalk_class = tk.take_and_parse()?;
1072                        } else if tk.test_str("NONDEFAULTRULE")? {
1073                            net.non_default_rule = Some(tk.take_str()?);
1074                        } else if tk.peeking_test_str("COVER")?
1075                            || tk.peeking_test_str("FIXED")?
1076                            || tk.peeking_test_str("ROUTED")?
1077                            || tk.peeking_test_str("NOSHIELD")?
1078                        {
1079                            // Regular wiring
1080
1081                            let wiring = read_regular_wiring(&mut tk)?;
1082
1083                            // Store the wiring statements.
1084                            net.regular_wiring.push(wiring);
1085                        } else if tk.test_str("SOURCE")? {
1086                            net.source = tk.take_and_parse()?;
1087                        } else if tk.test_str("FIXEDBUMP")? {
1088                            net.fixed_bump = true;
1089                        } else if tk.test_str("FREQUENCY")? {
1090                            net.frequency = Some(tk.take_and_parse()?);
1091                        } else if tk.test_str("ORIGINAL")? {
1092                            net.original = Some(tk.take_str()?);
1093                        } else if tk.test_str("USE")? {
1094                            net.net_use = tk.take_and_parse()?;
1095                        } else if tk.test_str("PATTERN")? {
1096                            net.pattern = tk.take_and_parse()?;
1097                        } else if tk.test_str("ESTCAP")? {
1098                            net.est_cap = Some(tk.take_and_parse()?);
1099                        } else if tk.test_str("WEIGHT")? {
1100                            net.weight = tk.take_and_parse()?;
1101                        } else if tk.test_str("PROPERTY")? {
1102                            while !tk.peeking_test_str("+")? && !tk.peeking_test_str(";")? {
1103                                if let Some((name, value)) =
1104                                    read_def_property(&mut design.property_definitions, &mut tk)?
1105                                {
1106                                    // Store property.
1107                                    net.properties.insert(name, value);
1108                                }
1109                            }
1110                        } else {
1111                            return Err(LefDefParseError::UnexpectedToken(
1112                                "".to_string(),
1113                                tk.current_token_str().unwrap(),
1114                            ));
1115                        }
1116                    }
1117                }
1118                tk.expect_str(";")?; // End of net.
1119
1120                design.nets.push(net);
1121            }
1122
1123            tk.expect_str("END")?;
1124            tk.expect_str("NETS")?;
1125            // return Err(LefDefError::NotImplemented("NETS"));
1126        } else if tk.test_str("SCANCHAINS")? {
1127            return Err(LefDefParseError::NotImplemented("SCANCHAINS"));
1128        } else if tk.test_str("GROUPS")? {
1129            let _num_groups: u32 = tk.take_and_parse()?;
1130
1131            // TODO: Reserve space.
1132            //design.groups.extend_reserve(num_groups);
1133
1134            while tk.test_str("-")? {
1135                let group_name = tk.take_str()?;
1136                let mut group = Group::default();
1137
1138                // Read component names.
1139                while !tk.peeking_test_str("+")? {
1140                    let component = tk.take_str()?;
1141                    group.component_names.push(component);
1142                }
1143
1144                while tk.test_str("+")? {
1145                    if tk.test_str("REGION")? {
1146                        let region_name = tk.take_str()?;
1147                        group.region_name = Some(region_name);
1148                    } else if tk.test_str("PROPERTY")? {
1149                        while !tk.peeking_test_str("+")? {
1150                            if let Some((name, value)) =
1151                                read_def_property(&mut design.property_definitions, &mut tk)?
1152                            {
1153                                // Store property. Name and type must match the property definitions.
1154                                group.properties.insert(name, value);
1155                            }
1156                        }
1157                    } else {
1158                        return Err(LefDefParseError::UnexpectedToken(
1159                            "REGION or PROPERTY".to_string(),
1160                            tk.current_token_str().unwrap(),
1161                        ));
1162                    }
1163                }
1164
1165                // Store the group.
1166                design.groups.entry(group_name).or_default().push(group);
1167            }
1168
1169            tk.expect_str("END")?;
1170            tk.expect_str("GROUPS")?;
1171        } else if tk.test_str("BEGINEXT")? {
1172            // Ignore extensions.
1173            tk.skip_until_str("ENDEXT")?;
1174        } else {
1175            return Err(LefDefParseError::UnknownToken(
1176                tk.current_token_str().unwrap(),
1177            ));
1178        }
1179    }
1180
1181    Ok(design)
1182}
1183
1184#[test]
1185fn test_read_def() {
1186    let data = r#"
1187VERSION 5.7 ;
1188DIVIDERCHAR "/" ;
1189BUSBITCHARS "[]" ;
1190DESIGN test_design ;
1191UNITS DISTANCE MICRONS 2000 ;
1192TECHNOLOGY FreePDK45 ;
1193
1194HISTORY This is a test. ;
1195HISTORY This is an other test. ;
1196
1197
1198PROPERTYDEFINITIONS
1199    COMPONENTPIN designRuleWidth REAL ;
1200    DESIGN testProperty REAL 0.123 ;
1201    DESIGN testProperty2 STRING "as df" ;
1202END PROPERTYDEFINITIONS
1203
1204DIEAREA ( 0 0 ) ( 10000 10000 ) ;
1205
1206COMPONENTS 3 ;
1207    - _1_ BUF_X2 ;
1208    - _2_ BUF_X2 ;
1209    - _3_ BUF_X2 ;
1210END COMPONENTS
1211
1212BLOCKAGES 3 ;
1213    - LAYER metal1
1214        RECT ( -100 200 ) ( 0 100 )
1215        RECT ( -200 200 ) ( 300 500 ) ;
1216
1217    - LAYER metal2 + PUSHDOWN + COMPONENT comp1 + EXCEPTPGNET + SPACING 10
1218        RECT ( -100 200 ) ( 0 100 )
1219        RECT ( -200 200 ) ( 300 500 ) ;
1220
1221    - PLACEMENT
1222        RECT ( -100 200 ) ( 0 100 )
1223        RECT ( -200 200 ) ( 300 500 ) ;
1224
1225    - PLACEMENT
1226        RECT ( -100 200 ) ( 0 100 )
1227        RECT ( -200 200 ) ( 300 500 ) ;
1228
1229    - LAYER metal3
1230        RECT ( -100 200 ) ( 0 100 )
1231        RECT ( -200 200 ) ( 300 500 ) ;
1232
1233END BLOCKAGES
1234
1235PINS 2 ;
1236- IN + NET IN
1237    + DIRECTION INPUT
1238- OUT + NET OUT
1239    + DIRECTION OUTPUT
1240END PINS
1241
1242NETS 6 ;
1243- IN ( PIN IN ) ;
1244- OUT ( PIN OUT ) ;
1245- net1 ( _1_ A ) ;
1246
1247# With more attributes:
1248
1249- net2 ( _2_ A ) ( _3_ B + SYNTHESIZED ) ( PIN OUT ) + SHIELDNET shieldnet1
1250    + XTALK 1
1251    + NONDEFAULTRULE nondefaultrule1
1252    + SOURCE TEST
1253    + FIXEDBUMP
1254    + FREQUENCY 1000000
1255    + ORIGINAL originalNet
1256    + USE ANALOG
1257    + PATTERN BALANCED
1258    + ESTCAP 0.123
1259    + WEIGHT 2
1260    + PROPERTY testProperty 3.14 testProperty2 someText
1261    + PROPERTY testProperty 3.14 testProperty2 someText
1262    ;
1263
1264# Net with simple wiring.
1265
1266- net2 ( _1_ A ) ( _2_ A )
1267    + ROUTED metal1 ( 0 0 ) ( 10 0 )
1268    ;
1269
1270- net3 ( _1_ A ) ( _2_ A )
1271    + ROUTED metal1 ( 0 0 ) ( 10 0 ) ( * 10 ) ( * 20 )
1272        NEW metal2 ( 0 0 ) ( 10 0 )
1273    ;
1274
1275
1276# Nets with vias.
1277- net4 ( _1_ A ) ( _2_ A )
1278    + ROUTED metal1 ( 0 0 ) ( 10 0 ) VIA12 ( * 20 ) ( 40 * )
1279        NEW metal2 ( 0 0 ) ( 10 0 )
1280    ;
1281
1282# Multi patterning
1283- net4 ( _1_ A ) ( _2_ A )
1284    + ROUTED metal1 ( 0 0 ) MASK 1 ( 10 0 ) MASK 012 VIA12 ( * 20 ) MASK 2 ( 40 * )
1285        NEW metal2 ( 0 0 ) MASK 1 ( 10 0 )
1286    ;
1287
1288END NETS
1289
1290BEGINEXT
1291    test 123 ;
1292ENDEXT
1293
1294END DESIGN
1295"#;
1296
1297    let result = read_def_chars(data.chars());
1298
1299    dbg!(&result);
1300
1301    assert!(result.is_ok());
1302}
1303
1304/// Read a property name and a property value.
1305/// Checks if the property is specified in the PROPERTYDEFINITIONS. If not, an error is returned
1306/// and the property should be ignored.
1307///
1308/// Returns `(property_name, value)`.
1309pub fn read_def_property<I>(
1310    property_definitions: &mut BTreeMap<String, DEFPropertyDefinition>,
1311    tk: &mut Tokenized<I, LefDefLexer>,
1312) -> Result<Option<(String, PropertyValue)>, LefDefParseError>
1313where
1314    I: Iterator<Item = char> + PeekingNext,
1315{
1316    let property_name = tk.take_str()?;
1317
1318    let property_def = property_definitions.get(&property_name);
1319
1320    if let Some(property_def) = property_def {
1321        let prop_value = match property_def.property_type {
1322            PropertyType::Integer => PropertyValue::Int(tk.take_and_parse()?),
1323            PropertyType::Real => PropertyValue::Real(tk.take_and_parse()?),
1324            PropertyType::String => PropertyValue::String(tk.take_str()?),
1325        };
1326
1327        // TODO: Store property.
1328        Ok(Some((property_name, prop_value)))
1329    } else {
1330        log::error!("Property is not defined: '{}'", &property_name);
1331        tk.advance(); // Skip property name.
1332                      // Err((LefDefError::UndefinedProperty(prop_name)))
1333        Ok(None)
1334    }
1335}