crcany_core/spec/
parse.rs

1use crate::spec::Spec;
2use crate::util::{ones, parse_int};
3
4#[derive(Debug)]
5pub enum SpecParseError {
6    InvalidInput,
7    MissingParams,
8}
9
10pub fn read_spec(s: &str) -> Result<Spec, SpecParseError> {
11    let mut width = None;
12    let mut poly = None;
13    let mut init = 0;
14    let mut refin = None;
15    let mut refout = None;
16    let mut xorout = 0;
17    let mut check = None;
18    let mut residue = 0;
19    let mut name = None;
20
21    //println!("parsing: {}", s);
22
23    for (param, value) in parse_spec(s).or(Err(SpecParseError::InvalidInput))?.1 {
24        //println!("checking param: {} = {}", param, value);
25
26        match param {
27            "width" | "w" => {
28                width = Some(parse_int(value).or(Err(SpecParseError::InvalidInput))? as _)
29            }
30            "poly" | "p" => poly = Some(parse_int(value).or(Err(SpecParseError::InvalidInput))?),
31            "init" | "i" => init = parse_int(value).or(Err(SpecParseError::InvalidInput))?,
32            "refin" | "r" => refin = Some(value == "true" || value == "t"),
33            "refout" | "refo" => refout = Some(value == "true" || value == "t"),
34            "xorout" | "x" => xorout = parse_int(value).or(Err(SpecParseError::InvalidInput))?,
35            "check" | "c" => check = Some(parse_int(value).or(Err(SpecParseError::InvalidInput))?),
36            "residue" | "res" => {
37                residue = parse_int(value).or(Err(SpecParseError::InvalidInput))?
38            }
39            "name" | "n" => name = Some(value.to_string()),
40            _ => panic!(),
41        }
42    }
43
44    let (refin, refout) = match (refin, refout) {
45        (Some(a), Some(b)) => (a, b),
46        (Some(a), None) => (a, a),
47        (None, Some(b)) => (b, b),
48        (None, None) => return Err(SpecParseError::MissingParams),
49    };
50
51    let (width, poly, check, name) = match (width, poly, check, name) {
52        (Some(w), Some(p), Some(c), Some(n)) => (w, p, c, n),
53        _ => return Err(SpecParseError::MissingParams),
54    };
55
56    xorout &= ones(width);
57
58    Ok(Spec {
59        width,
60        poly,
61        init,
62        refin,
63        refout,
64        xorout,
65        check,
66        residue,
67        name,
68    })
69}
70
71fn parse_var(i: &str) -> nom::IResult<&str, (&str, &str)> {
72    use nom::{
73        branch::alt,
74        character::complete::{char, none_of},
75        combinator::recognize,
76        multi::{many0_count, many1_count},
77        sequence::{delimited, separated_pair},
78    };
79
80    separated_pair(
81        recognize(many1_count(none_of(" ="))),
82        char('='),
83        alt((
84            delimited(char('"'), recognize(many0_count(none_of("\""))), char('"')),
85            recognize(many1_count(none_of(" ="))),
86        )),
87    )(i)
88}
89
90fn parse_spec(i: &str) -> nom::IResult<&str, Vec<(&str, &str)>> {
91    use nom::{character::complete::space1, multi::separated_list1};
92
93    separated_list1(space1, parse_var)(i)
94}