tf_parser 0.1.0

technology(.tf) file parser in Rust
Documentation
use super::base_parser::{float, number, positive_number, qstring, ws};
use crate::{model::TfTechnology, TfRes};

use nom::{
    bytes::complete::tag,
    combinator::opt,
    error::context,
    sequence::{delimited, preceded, tuple},
};

fn time_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(tuple((ws(tag("unitTimeName")), ws(tag("=")))), qstring),
        preceded(
            tuple((ws(tag("timePrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn length_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(tuple((ws(tag("unitLengthName")), ws(tag("=")))), qstring),
        preceded(
            tuple((ws(tag("lengthPrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn voltage_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(tuple((ws(tag("unitVoltageName")), ws(tag("=")))), qstring),
        preceded(
            tuple((ws(tag("voltagePrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn current_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(tuple((ws(tag("unitCurrentName")), ws(tag("=")))), qstring),
        preceded(
            tuple((ws(tag("currentPrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn capacitance_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(
            tuple((ws(tag("unitCapacitanceName")), ws(tag("=")))),
            qstring,
        ),
        preceded(
            tuple((ws(tag("capacitancePrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn inductance_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(
            tuple((ws(tag("unitInductanceName")), ws(tag("=")))),
            qstring,
        ),
        preceded(
            tuple((ws(tag("inductancePrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn power_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(tuple((ws(tag("unitPowerName")), ws(tag("=")))), qstring),
        preceded(
            tuple((ws(tag("powerPrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn resistance_unit_parser(input: &str) -> TfRes<&str, (&str, u32)> {
    tuple((
        preceded(
            tuple((ws(tag("unitResistanceName")), ws(tag("=")))),
            qstring,
        ),
        preceded(
            tuple((ws(tag("resistancePrecision")), ws(tag("=")))),
            positive_number,
        ),
    ))(input)
}

fn baseline_temperature_parser(input: &str) -> TfRes<&str, (i32, i32, i32)> {
    tuple((
        preceded(
            tuple((ws(tag("minBaselineTemperature")), ws(tag("=")))),
            number,
        ),
        preceded(
            tuple((ws(tag("nomBaselineTemperature")), ws(tag("=")))),
            number,
        ),
        preceded(
            tuple((ws(tag("maxBaselineTemperature")), ws(tag("=")))),
            number,
        ),
    ))(input)
}

pub fn technology_parser(input: &str) -> TfRes<&str, TfTechnology> {
    context(
        "Technology Section",
        preceded(
            ws(tag("Technology")),
            delimited(
                ws(tag("{")),
                tuple((
                    preceded(tuple((ws(tag("name")), ws(tag("=")))), qstring),
                    preceded(tuple((ws(tag("dielectric")), ws(tag("=")))), float),
                    time_unit_parser,
                    length_unit_parser,
                    preceded(
                        tuple((ws(tag("gridResolution")), ws(tag("=")))),
                        positive_number,
                    ),
                    voltage_unit_parser,
                    current_unit_parser,
                    power_unit_parser,
                    resistance_unit_parser,
                    capacitance_unit_parser,
                    inductance_unit_parser,
                    opt(baseline_temperature_parser),
                )),
                ws(tag("}")),
            ),
        ),
    )(input)
    .map(|(res, data)| {
        (
            res,
            TfTechnology {
                technology: data.0.to_string(),
                dielectric: data.1,
                time_unit: (data.2).0.to_string(),
                time_precision: (data.2).1,
                length_unit: (data.3).0.to_string(),
                length_precision: (data.3).1,
                voltage_unit: (data.5).0.to_string(),
                voltage_precision: (data.5).1,
                current_unit: (data.6).0.to_string(),
                current_precision: (data.6).1,
                power_unit: (data.7).0.to_string(),
                power_precision: (data.7).1,
                resistance_unit: (data.8).0.to_string(),
                resistance_precision: (data.8).1,
                capacitance_unit: (data.9).0.to_string(),
                capacitance_precision: (data.9).1,
                inductance_unit: (data.10).0.to_string(),
                inductance_precision: (data.10).1,
                grid_resolution: data.4,
            },
        )
    })
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_technology1() {
        let input = "Technology {
        name                = \"fake_tech\"
        dielectric          = 4.2e-05
        unitTimeName            = \"ns\"
        timePrecision           = 1000
        unitLengthName          = \"micron\"
        lengthPrecision         = 1000
        gridResolution          = 5
        unitVoltageName         = \"v\"
        voltagePrecision        = 1000000
        unitCurrentName         = \"mA\"
        currentPrecision        = 1000
        unitPowerName           = \"uw\"
        powerPrecision          = 100000000
        unitResistanceName      = \"kohm\"
        resistancePrecision     = 10000000
        unitCapacitanceName     = \"pf\"
        capacitancePrecision        = 10000000
        unitInductanceName      = \"nh\"
        inductancePrecision     = 100
        minBaselineTemperature      = 25
        nomBaselineTemperature      = 25
        maxBaselineTemperature      = 25
}";
        let (_, _) = technology_parser(input).unwrap();
    }

    #[test]
    fn test_technology2() {
        let input = "Technology {
        name                = \"scc40nll_hd\"
        dielectric          = 4.2e-05
        unitTimeName            = \"ns\"
        timePrecision           = 1000
        unitLengthName          = \"micron\"
        lengthPrecision         = 1000
        gridResolution          = 5
        unitVoltageName         = \"v\"
        voltagePrecision        = 1000000
        unitCurrentName         = \"mA\"
        currentPrecision        = 1000
        unitPowerName           = \"uw\"
        powerPrecision          = 100000000
        unitResistanceName      = \"kohm\"
        resistancePrecision     = 10000000
        unitCapacitanceName     = \"pf\"
        capacitancePrecision        = 10000000
        unitInductanceName      = \"nh\"
        inductancePrecision     = 100
        minBaselineTemperature      = 25
        nomBaselineTemperature      = 25
        maxBaselineTemperature      = 25
}";
        let (_, _) = technology_parser(input).unwrap();
    }
}