crcany_core/spec/
parse.rs1use 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 for (param, value) in parse_spec(s).or(Err(SpecParseError::InvalidInput))?.1 {
24 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}