Skip to main content

can_dbc/
parser.rs

1//!
2//! Parser module for DBC files using pest
3//!
4
5use can_dbc_pest::{Error as PestError, Pair, Pairs, Rule};
6
7use crate::ast::NumericValue;
8
9pub type DbcResult<T> = Result<T, DbcError>;
10
11/// Error type for DBC parsing operations
12#[derive(Debug, Clone, PartialEq, thiserror::Error)]
13pub enum DbcError {
14    #[error("No more rules expected, but found: {0:?}")]
15    ExpectedEmpty(Rule),
16    #[error("Expected rule: {0:?}, found: {1:?}")]
17    ExpectedRule(Rule, Rule),
18    #[error("Expected one of these rules: {0:?}, found: {1:?}")]
19    ExpectedOneOfRules(Vec<Rule>, Rule),
20    #[error("Expected a quoted string or a number, found: {0:?}")]
21    ExpectedStrNumber(Rule),
22    #[error("Invalid Float value: '{0}'")]
23    InvalidFloat(String),
24    #[error("Invalid Int value: '{0}'")]
25    InvalidInt(String),
26    #[error("Invalid Uint value: '{0}'")]
27    InvalidUint(String),
28    #[error("Message ID out of range: {0}")]
29    MessageIdOutOfRange(u64),
30    #[error("Multiple multiplexors defined for a message")]
31    MultipleMultiplexors,
32    #[error("No more parsing rules available")]
33    NoMoreRules,
34    #[error("Feature not implemented: {0}")]
35    NotImplemented(&'static str),
36    #[error(transparent)]
37    Pest(Box<PestError<Rule>>),
38    #[error("Signal defined without an associated message")]
39    SignalWithoutMessage,
40    #[error("Unknown multiplex indicator: {0}")]
41    UnknownMultiplexIndicator(String),
42    #[error("Unknown rule: {0:?}")]
43    UnknownRule(Rule),
44    #[error("Invalid numeric value: '{0}'")]
45    InvalidNumericValue(String),
46}
47
48impl From<PestError<Rule>> for DbcError {
49    fn from(value: PestError<Rule>) -> Self {
50        Self::Pest(Box::new(value))
51    }
52}
53
54/// Helper function to get the next pair and validate its rule
55pub(crate) fn next<'a>(iter: &'a mut Pairs<Rule>) -> DbcResult<Pair<'a, Rule>> {
56    iter.next().ok_or(DbcError::NoMoreRules)
57}
58
59/// Helper function to get the next pair and validate its rule
60pub(crate) fn next_rule<'a>(
61    iter: &'a mut Pairs<Rule>,
62    expected: Rule,
63) -> DbcResult<Pair<'a, Rule>> {
64    next(iter).and_then(|pair| {
65        if pair.as_rule() == expected {
66            Ok(pair)
67        } else {
68            Err(DbcError::ExpectedRule(expected, pair.as_rule()))
69        }
70    })
71}
72
73pub(crate) fn next_optional_rule<'a>(
74    iter: &'a mut Pairs<Rule>,
75    expected: Rule,
76) -> Option<Pair<'a, Rule>> {
77    if let Some(pair) = iter.peek() {
78        if pair.as_rule() == expected {
79            return iter.next();
80        }
81    }
82    None
83}
84
85/// Helper function to get the next pair, ensure it matches the expected rule, and convert to string
86pub(crate) fn next_string(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<String> {
87    Ok(next_rule(iter, expected)?.as_str().to_string())
88}
89
90/// Helper function to get a single pair and validate its rule
91pub(crate) fn single_inner(pair: Pair<Rule>, expected: Rule) -> DbcResult<Pair<Rule>> {
92    let mut iter = pair.into_inner();
93    let pair = iter.next().ok_or(DbcError::NoMoreRules)?;
94    if pair.as_rule() != expected {
95        Err(DbcError::ExpectedRule(expected, pair.as_rule()))
96    } else if let Some(next) = iter.next() {
97        Err(DbcError::ExpectedEmpty(next.as_rule()))
98    } else {
99        Ok(pair)
100    }
101}
102
103/// Helper function to validate a pair's rule matches the expected rule
104pub(crate) fn validated(pair: Pair<Rule>, expected: Rule) -> DbcResult<Pair<Rule>> {
105    if pair.as_rule() == expected {
106        Ok(pair)
107    } else {
108        Err(DbcError::ExpectedRule(expected, pair.as_rule()))
109    }
110}
111
112pub(crate) fn validated_inner(pair: Pair<'_, Rule>, expected: Rule) -> DbcResult<Pairs<'_, Rule>> {
113    Ok(validated(pair, expected)?.into_inner())
114}
115
116/// Helper function to get a single pair, validate its rule, and convert to string
117pub(crate) fn single_inner_str(pair: Pair<Rule>, expected: Rule) -> DbcResult<String> {
118    Ok(single_inner(pair, expected)?.as_str().to_string())
119}
120
121/// Helper function to collect all remaining pairs of a specific rule type
122pub(crate) fn collect_all<'a, T: TryFrom<Pair<'a, Rule>, Error = DbcError>>(
123    iter: &mut Pairs<'a, Rule>,
124) -> DbcResult<Vec<T>> {
125    iter.map(TryInto::try_into).collect()
126}
127
128/// Helper function to collect all remaining pairs of a specific rule type
129pub(crate) fn collect_expected<'a, T: TryFrom<Pair<'a, Rule>, Error = DbcError>>(
130    iter: &mut Pairs<'a, Rule>,
131    expected: Rule,
132) -> DbcResult<Vec<T>> {
133    iter.map(|pair| {
134        if pair.as_rule() == expected {
135            pair.try_into()
136        } else {
137            Err(DbcError::ExpectedRule(expected, pair.as_rule()))
138        }
139    })
140    .collect()
141}
142
143/// Helper function to collect all remaining pairs of a specific rule type and convert to strings
144pub(crate) fn collect_strings(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<Vec<String>> {
145    iter.map(|pair| {
146        if pair.as_rule() == expected {
147            Ok(pair.as_str().to_string())
148        } else {
149            Err(DbcError::ExpectedRule(expected, pair.as_rule()))
150        }
151    })
152    .collect()
153}
154
155pub(crate) fn is_vector_placeholder(value: &str) -> bool {
156    matches!(value, "" | "Vector__XXX" | "VectorXXX" | "VECTOR__XXX")
157}
158
159pub(crate) fn node_name_or_none(value: String) -> Option<String> {
160    if is_vector_placeholder(&value) {
161        None
162    } else {
163        Some(value)
164    }
165}
166
167pub(crate) fn collect_node_names(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<Vec<String>> {
168    collect_strings(iter, expected).map(|v| v.into_iter().filter_map(node_name_or_none).collect())
169}
170
171/// Helper function to ensure the iterator is empty (no more items)
172pub(crate) fn expect_empty(iter: &Pairs<Rule>) -> DbcResult<()> {
173    iter.peek()
174        .map_or(Ok(()), |v| Err(DbcError::ExpectedEmpty(v.as_rule())))
175}
176
177/// Helper function to extract string content from `quoted_str` rule
178pub(crate) fn inner_str(pair: Pair<Rule>) -> String {
179    // panics because pest grammar ensures this
180    next_rule(&mut pair.into_inner(), Rule::string)
181        .expect("string")
182        .as_str()
183        .to_string()
184}
185
186/// Helper function to parse an integer from a pest pair
187pub(crate) fn parse_int(pair: &Pair<Rule>) -> DbcResult<i64> {
188    let value = pair.as_str();
189    value
190        .parse::<i64>()
191        .map_err(|_| DbcError::InvalidInt(value.to_string()))
192}
193
194/// Helper function to parse an unsigned integer from a pest pair
195pub(crate) fn parse_uint(pair: &Pair<Rule>) -> DbcResult<u64> {
196    let value = pair.as_str();
197    value
198        .parse::<u64>()
199        .map_err(|_| DbcError::InvalidUint(value.to_string()))
200}
201
202/// Helper function to parse a float from a pest pair
203pub(crate) fn parse_float(pair: &Pair<Rule>) -> DbcResult<f64> {
204    let value = pair.as_str();
205    value
206        .parse::<f64>()
207        .map_err(|_| DbcError::InvalidFloat(value.to_string()))
208}
209
210/// Helper function to parse the next uint from the iterator
211pub(crate) fn parse_next_uint(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<u64> {
212    parse_uint(&next_rule(iter, expected)?)
213}
214
215/// Helper function to parse the next int from the iterator
216pub(crate) fn parse_next_int(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<i64> {
217    parse_int(&next_rule(iter, expected)?)
218}
219
220/// Helper function to parse the next float from the iterator
221pub(crate) fn parse_next_float(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<f64> {
222    parse_float(&next_rule(iter, expected)?)
223}
224
225/// Helper function to parse the next string from the iterator
226pub(crate) fn parse_next_inner_str(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<String> {
227    Ok(inner_str(next_rule(iter, expected)?))
228}
229
230/// Helper to parse min/max values from a `min_max` rule
231pub(crate) fn parse_min_max_int(pair: Pair<Rule>) -> DbcResult<(i64, i64)> {
232    let mut pairs = pair.into_inner();
233
234    let min_val = parse_next_int(&mut pairs, Rule::minimum)?;
235    let max_val = parse_next_int(&mut pairs, Rule::maximum)?;
236    expect_empty(&pairs).expect("pest grammar ensures no extra items");
237
238    Ok((min_val, max_val))
239}
240
241/// Helper to parse min/max values from a `min_max` rule as `NumericValue`
242/// This preserves the exact value without precision loss for large integers like 2**64
243pub(crate) fn parse_min_max_numeric(pair: Pair<Rule>) -> DbcResult<(NumericValue, NumericValue)> {
244    let mut pairs = pair.into_inner();
245
246    let min_val = next_rule(&mut pairs, Rule::minimum)?
247        .as_str()
248        .parse::<NumericValue>()?;
249    let max_val = next_rule(&mut pairs, Rule::maximum)?
250        .as_str()
251        .parse::<NumericValue>()?;
252    expect_empty(&pairs).expect("pest grammar ensures no extra items");
253
254    Ok((min_val, max_val))
255}