1use std::collections::BTreeMap;
2use std::sync::Arc;
3
4mod gsd_parser {
5 #[derive(pest_derive::Parser)]
6 #[grammar = "gsd.pest"]
7 pub struct GsdParser;
8}
9
10pub type ParseError = pest::error::Error<gsd_parser::Rule>;
11pub type ParseResult<T> = Result<T, ParseError>;
12
13fn parse_error(e: impl std::fmt::Display, span: pest::Span<'_>) -> ParseError {
14 let message = format!("{}", e);
15 pest::error::Error::new_from_span(pest::error::ErrorVariant::CustomError { message }, span)
16}
17
18fn parse_number<T: TryFrom<u32>>(
19 pair: pest::iterators::Pair<'_, gsd_parser::Rule>,
20) -> ParseResult<T>
21where
22 <T as TryFrom<u32>>::Error: std::fmt::Display,
23{
24 match pair.as_rule() {
25 gsd_parser::Rule::dec_number => pair.as_str().parse(),
26 gsd_parser::Rule::hex_number => {
27 u32::from_str_radix(pair.as_str().trim_start_matches("0x"), 16)
28 }
29 _ => panic!("Called parse_number() on a non-number pair: {:?}", pair),
30 }
31 .map_err(|_| parse_error("invalid digit found while parsing integer", pair.as_span()))
32 .and_then(|i| i.try_into().map_err(|e| parse_error(e, pair.as_span())))
33}
34
35fn parse_signed_number(pair: pest::iterators::Pair<'_, gsd_parser::Rule>) -> ParseResult<i64> {
36 match pair.as_rule() {
37 gsd_parser::Rule::dec_number => pair.as_str().parse(),
38 gsd_parser::Rule::hex_number => {
39 i64::from_str_radix(pair.as_str().trim_start_matches("0x"), 16)
40 }
41 _ => panic!("Called parse_number() on a non-number pair: {:?}", pair),
42 }
43 .map_err(|_| {
44 parse_error(
45 "invalid digit found while parsing signed integer",
46 pair.as_span(),
47 )
48 })
49}
50
51fn parse_number_list<T: TryFrom<u32>>(
52 pair: pest::iterators::Pair<'_, gsd_parser::Rule>,
53) -> ParseResult<Vec<T>>
54where
55 <T as TryFrom<u32>>::Error: std::fmt::Display,
56{
57 Ok(match pair.as_rule() {
58 gsd_parser::Rule::number_list => pair
59 .into_inner()
60 .into_iter()
61 .map(|p| parse_number::<T>(p))
62 .collect::<ParseResult<Vec<T>>>()?,
63 gsd_parser::Rule::dec_number | gsd_parser::Rule::hex_number => {
64 vec![parse_number(pair)?]
65 }
66 _ => panic!(
67 "Called parse_number_list() on a pair that cannot be a number list: {:?}",
68 pair
69 ),
70 })
71}
72
73fn parse_bool(pair: pest::iterators::Pair<'_, gsd_parser::Rule>) -> ParseResult<bool> {
74 Ok(parse_number::<u32>(pair)? != 0)
75}
76
77fn parse_string_literal(pair: pest::iterators::Pair<'_, gsd_parser::Rule>) -> String {
78 assert!(pair.as_rule() == gsd_parser::Rule::string_literal);
79 let mut chars = pair.as_str().chars();
81 chars.next();
82 chars.next_back();
83 let s = chars.as_str().to_owned();
84
85 s.replace("\\\r\n", "").replace("\\\n", "")
87}
88
89pub fn parse(
90 file: &std::path::Path,
91 source: &str,
92) -> ParseResult<crate::GenericStationDescription> {
93 parse_inner(source).map_err(|e| e.with_path(&file.to_string_lossy()))
94}
95
96fn parse_inner(source: &str) -> ParseResult<crate::GenericStationDescription> {
97 use pest::Parser;
98
99 let gsd_pairs = gsd_parser::GsdParser::parse(gsd_parser::Rule::gsd, &source)?
100 .next()
101 .expect("pest grammar wrong?");
102
103 let mut gsd = crate::GenericStationDescription::default();
104 let mut prm_texts = BTreeMap::new();
105 let mut user_prm_data_definitions = BTreeMap::new();
106 let mut legacy_prm = Some(crate::UserPrmData::default());
107
108 for statement in gsd_pairs.into_inner() {
109 let statement_span = statement.as_span();
110 match statement.as_rule() {
111 gsd_parser::Rule::prm_text => {
112 let mut content = statement.into_inner();
113 let id: u16 = parse_number(content.next().expect("pest grammar wrong?"))?;
114 let mut values = BTreeMap::new();
115 for value_pairs in content {
116 assert!(value_pairs.as_rule() == gsd_parser::Rule::prm_text_value);
117 let mut iter = value_pairs.into_inner();
118 let number = parse_signed_number(iter.next().expect("pest grammar wrong?"))?;
119 let value = parse_string_literal(iter.next().expect("pest grammar wrong?"));
120 assert!(iter.next().is_none());
121 values.insert(value, number);
122 }
123 prm_texts.insert(id, Arc::new(values));
124 }
125 gsd_parser::Rule::ext_user_prm_data => {
126 let mut content = statement.into_inner();
127 let id: u32 = parse_number(content.next().expect("pest grammar wrong?"))?;
129 let name = parse_string_literal(content.next().expect("pest grammar wrong?"));
130
131 let data_type_pair = content.next().expect("pest grammar wrong?");
132 assert_eq!(
133 data_type_pair.as_rule(),
134 gsd_parser::Rule::prm_data_type_name
135 );
136 let data_type_rule = data_type_pair
137 .into_inner()
138 .next()
139 .expect("pest grammar wrong?");
140 let data_type = match data_type_rule.as_rule() {
141 gsd_parser::Rule::identifier => {
142 match data_type_rule.as_str().to_lowercase().as_str() {
143 "unsigned8" => crate::UserPrmDataType::Unsigned8,
144 "unsigned16" => crate::UserPrmDataType::Unsigned16,
145 "unsigned32" => crate::UserPrmDataType::Unsigned32,
146 "signed8" => crate::UserPrmDataType::Signed8,
147 "signed16" => crate::UserPrmDataType::Signed16,
148 "signed32" => crate::UserPrmDataType::Signed32,
149 dt => panic!("unknown data type {dt:?}"),
150 }
151 }
152 gsd_parser::Rule::bit => {
153 let bit = parse_number(
154 data_type_rule
155 .into_inner()
156 .next()
157 .expect("pest grammar wrong?"),
158 )?;
159 crate::UserPrmDataType::Bit(bit)
160 }
161 gsd_parser::Rule::bit_area => {
162 let mut content = data_type_rule.into_inner();
163 let first_bit = parse_number(content.next().expect("pest grammar wrong?"))?;
164 let last_bit = parse_number(content.next().expect("pest grammar wrong?"))?;
165 crate::UserPrmDataType::BitArea(first_bit, last_bit)
166 }
167 _ => unreachable!(),
168 };
169
170 let default_value =
171 parse_signed_number(content.next().expect("pest grammar wrong?"))?;
172
173 let mut constraint = crate::PrmValueConstraint::Unconstrained;
174 let mut text_ref = None;
175 let mut changeable = true;
176 let mut visible = true;
177
178 for rule in content {
179 match rule.as_rule() {
180 gsd_parser::Rule::prm_data_value_range => {
181 let mut content = rule.into_inner();
182 let min_value =
183 parse_signed_number(content.next().expect("pest grammar wrong?"))?;
184 let max_value =
185 parse_signed_number(content.next().expect("pest grammar wrong?"))?;
186 constraint = crate::PrmValueConstraint::MinMax(min_value, max_value);
187 }
188 gsd_parser::Rule::prm_data_value_set => {
189 let mut values = Vec::new();
190 for pairs in rule.into_inner() {
191 let number = parse_signed_number(pairs)?;
192 values.push(number);
193 }
194 constraint = crate::PrmValueConstraint::Enum(values);
195 }
196 gsd_parser::Rule::prm_text_ref => {
197 let text_id = parse_number(
198 rule.into_inner().next().expect("pest grammar wrong?"),
199 )?;
200 text_ref = Some(
201 prm_texts
202 .get(&text_id)
203 .ok_or_else(|| {
204 parse_error(
205 format!("PrmText {} was not found", text_id),
206 statement_span,
207 )
208 })?
209 .clone(),
210 );
211 }
212 gsd_parser::Rule::prm_data_changeable => {
213 changeable = parse_bool(rule.into_inner().next().unwrap())?;
214 }
215 gsd_parser::Rule::prm_data_visible => {
216 visible = parse_bool(rule.into_inner().next().unwrap())?;
217 }
218 rule => unreachable!("unexpected rule {rule:?}"),
219 }
220 }
221
222 user_prm_data_definitions.insert(
223 id,
224 Arc::new(crate::UserPrmDataDefinition {
225 name,
226 data_type,
227 text_ref,
228 default_value,
229 constraint,
230 changeable,
231 visible,
232 }),
233 );
234 }
235 gsd_parser::Rule::unit_diag_area => {
236 let mut content = statement.into_inner();
237 let first = parse_number(content.next().unwrap())?;
238 let last = parse_number(content.next().unwrap())?;
239 let mut values = BTreeMap::new();
240 for value_pairs in content {
241 assert!(value_pairs.as_rule() == gsd_parser::Rule::unit_diag_area_value);
242 let mut iter = value_pairs.into_inner();
243 let number = parse_number(iter.next().unwrap())?;
244 let value = parse_string_literal(iter.next().unwrap());
245 assert!(iter.next().is_none());
246 values.insert(number, value);
247 }
248 gsd.unit_diag.areas.push(crate::UnitDiagArea {
249 first,
250 last,
251 values,
252 });
253 }
254 gsd_parser::Rule::module => {
255 let mut content = statement.into_inner();
256 let name = parse_string_literal(content.next().unwrap());
257 let mut info_text = None;
258 let module_config: Vec<u8> = parse_number_list(content.next().unwrap())?;
259 let mut module_reference = None;
260 let mut module_prm_data = crate::UserPrmData::default();
261
262 for rule in content {
263 match rule.as_rule() {
264 gsd_parser::Rule::module_reference => {
265 module_reference =
266 Some(parse_number(rule.into_inner().next().unwrap())?);
267 }
268 gsd_parser::Rule::setting => {
269 let mut pairs = rule.into_inner();
270 let key = pairs.next().unwrap().as_str();
271 let value_pair = pairs.next().unwrap();
272 match key.to_lowercase().as_str() {
273 "ext_module_prm_data_len" => {
274 module_prm_data.length = parse_number(value_pair)?;
275 }
276 "ext_user_prm_data_ref" => {
277 let offset = parse_number(value_pair)?;
278 let data_id = parse_number(pairs.next().unwrap())?;
279 let data_ref =
280 user_prm_data_definitions.get(&data_id).unwrap().clone();
281 module_prm_data.data_ref.push((offset, data_ref));
282 }
283 "ext_user_prm_data_const" => {
284 let offset = parse_number(value_pair)?;
285 let values: Vec<u8> = parse_number_list(pairs.next().unwrap())?;
286 module_prm_data.data_const.push((offset, values));
287 }
288 "info_text" => {
289 info_text = Some(parse_string_literal(value_pair));
290 }
291 _ => (),
292 }
293 }
294 gsd_parser::Rule::data_area => (),
295 r => unreachable!("found rule {r:?}"),
296 }
297 }
298
299 let module = crate::Module {
300 name,
301 info_text,
302 config: module_config,
303 reference: module_reference,
304 module_prm_data,
305 };
306 gsd.available_modules.push(Arc::new(module));
307 }
308 gsd_parser::Rule::slot_definition => {
309 for rule in statement.into_inner() {
310 match rule.as_rule() {
311 gsd_parser::Rule::slot => {
312 let mut pairs = rule.into_inner();
313 let number = parse_number(pairs.next().unwrap())?;
314 let name = parse_string_literal(pairs.next().unwrap());
315
316 #[allow(unused)]
317 let find_module =
318 |reference: u16,
319 slot_ref: &str,
320 slot_num: u8|
321 -> Option<Arc<crate::Module>> {
322 for module in gsd.available_modules.iter() {
323 if module.reference == Some(reference.into()) {
324 return Some(module.clone());
325 }
326 }
327 None
330 };
331
332 let default_pair = pairs.next().unwrap();
333 let default_span = default_pair.as_span();
334 let default_ref = parse_number(default_pair)?;
335
336 let value_pair = pairs.next().unwrap();
337 let allowed_modules = match value_pair.as_rule() {
338 gsd_parser::Rule::slot_value_range => {
339 let mut pairs = value_pair.into_inner();
340 let first = parse_number(pairs.next().unwrap())?;
341 let last = parse_number(pairs.next().unwrap())?;
342 (first..=last)
343 .filter_map(|r| find_module(r, &name, number))
344 .collect::<Vec<_>>()
345 }
346 gsd_parser::Rule::slot_value_set => {
347 let mut allowed_modules = Vec::new();
348 for pairs in value_pair.into_inner() {
349 let reference = parse_number(pairs)?;
350 if let Some(module) = find_module(reference, &name, number)
351 {
352 allowed_modules.push(module);
353 }
354 }
355 allowed_modules
356 }
357 r => unreachable!("found rule {r:?}"),
358 };
359
360 let Some(default) = find_module(default_ref, &name, number) else {
361 return Err(parse_error(
362 format!(
363 "The default module for slot {number} (\"{name}\") with reference {default_ref} is not available",
364 ),
365 default_span,
366 ));
367 };
368 if !allowed_modules.contains(&default) {
369 }
372
373 let slot = crate::Slot {
374 name,
375 number,
376 default,
377 allowed_modules,
378 };
379
380 gsd.slots.push(slot);
381 }
382 r => unreachable!("found rule {r:?}"),
383 }
384 }
385 }
386 gsd_parser::Rule::setting => {
387 let mut pairs = statement.into_inner();
388 let key = pairs.next().unwrap().as_str();
389 let value_pair = pairs.next().unwrap();
390 match key.to_lowercase().as_str() {
391 "gsd_revision" => gsd.gsd_revision = parse_number(value_pair)?,
392 "vendor_name" => gsd.vendor = parse_string_literal(value_pair),
393 "model_name" => gsd.model = parse_string_literal(value_pair),
394 "revision" => gsd.revision = parse_string_literal(value_pair),
395 "revision_number" => gsd.revision_number = parse_number(value_pair)?,
396 "ident_number" => gsd.ident_number = parse_number(value_pair)?,
397 "hardware_release" => gsd.hardware_release = parse_string_literal(value_pair),
399 "software_release" => gsd.software_release = parse_string_literal(value_pair),
400 "fail_safe" => gsd.fail_safe = parse_bool(value_pair)?,
402 "9.6_supp" => {
404 if parse_bool(value_pair)? {
405 gsd.supported_speeds |= crate::SupportedSpeeds::B9600;
406 }
407 }
408 "19.2_supp" => {
409 if parse_bool(value_pair)? {
410 gsd.supported_speeds |= crate::SupportedSpeeds::B19200;
411 }
412 }
413 "31.25_supp" => {
414 if parse_bool(value_pair)? {
415 gsd.supported_speeds |= crate::SupportedSpeeds::B31250;
416 }
417 }
418 "45.45_supp" => {
419 if parse_bool(value_pair)? {
420 gsd.supported_speeds |= crate::SupportedSpeeds::B45450;
421 }
422 }
423 "93.75_supp" => {
424 if parse_bool(value_pair)? {
425 gsd.supported_speeds |= crate::SupportedSpeeds::B93750;
426 }
427 }
428 "187.5_supp" => {
429 if parse_bool(value_pair)? {
430 gsd.supported_speeds |= crate::SupportedSpeeds::B187500;
431 }
432 }
433 "500_supp" => {
434 if parse_bool(value_pair)? {
435 gsd.supported_speeds |= crate::SupportedSpeeds::B500000;
436 }
437 }
438 "1.5m_supp" => {
439 if parse_bool(value_pair)? {
440 gsd.supported_speeds |= crate::SupportedSpeeds::B1500000;
441 }
442 }
443 "3m_supp" => {
444 if parse_bool(value_pair)? {
445 gsd.supported_speeds |= crate::SupportedSpeeds::B3000000;
446 }
447 }
448 "6m_supp" => {
449 if parse_bool(value_pair)? {
450 gsd.supported_speeds |= crate::SupportedSpeeds::B6000000;
451 }
452 }
453 "12m_supp" => {
454 if parse_bool(value_pair)? {
455 gsd.supported_speeds |= crate::SupportedSpeeds::B12000000;
456 }
457 }
458 "maxtsdr_9.6" => gsd.max_tsdr.b9600 = parse_number(value_pair)?,
459 "maxtsdr_19.2" => gsd.max_tsdr.b19200 = parse_number(value_pair)?,
460 "maxtsdr_31.25" => gsd.max_tsdr.b31250 = parse_number(value_pair)?,
461 "maxtsdr_45.45" => gsd.max_tsdr.b45450 = parse_number(value_pair)?,
462 "maxtsdr_93.75" => gsd.max_tsdr.b93750 = parse_number(value_pair)?,
463 "maxtsdr_187.5" => gsd.max_tsdr.b187500 = parse_number(value_pair)?,
464 "maxtsdr_500" => gsd.max_tsdr.b500000 = parse_number(value_pair)?,
465 "maxtsdr_1.5m" => gsd.max_tsdr.b1500000 = parse_number(value_pair)?,
466 "maxtsdr_3m" => gsd.max_tsdr.b3000000 = parse_number(value_pair)?,
467 "maxtsdr_6m" => gsd.max_tsdr.b6000000 = parse_number(value_pair)?,
468 "maxtsdr_12m" => gsd.max_tsdr.b12000000 = parse_number(value_pair)?,
469 "implementation_type" => {
470 gsd.implementation_type = parse_string_literal(value_pair)
471 }
472 "modular_station" => gsd.modular_station = parse_bool(value_pair)?,
474 "max_module" => gsd.max_modules = parse_number(value_pair)?,
475 "max_input_len" => gsd.max_input_length = parse_number(value_pair)?,
476 "max_output_len" => gsd.max_output_length = parse_number(value_pair)?,
477 "max_data_len" => gsd.max_data_length = parse_number(value_pair)?,
478 "max_diag_data_len" => gsd.max_diag_data_length = parse_number(value_pair)?,
479 "freeze_mode_supp" => gsd.freeze_mode_supported = parse_bool(value_pair)?,
480 "sync_mode_supp" => gsd.sync_mode_supported = parse_bool(value_pair)?,
481 "auto_baud_supp" => gsd.auto_baud_supported = parse_bool(value_pair)?,
482 "set_slave_add_supp" => gsd.set_slave_addr_supported = parse_bool(value_pair)?,
483 "ext_user_prm_data_ref" => {
484 let offset = parse_number(value_pair)?;
485 let data_id = parse_number(pairs.next().unwrap())?;
486 let data_ref = user_prm_data_definitions.get(&data_id).unwrap().clone();
487 gsd.user_prm_data.data_ref.push((offset, data_ref));
488 legacy_prm = None;
491 }
492 "ext_user_prm_data_const" => {
493 let offset = parse_number(value_pair)?;
494 let values: Vec<u8> = parse_number_list(pairs.next().unwrap())?;
495 gsd.user_prm_data.data_const.push((offset, values));
496 legacy_prm = None;
499 }
500 "max_user_prm_data_len" => {
501 legacy_prm = None;
506 }
507 "user_prm_data_len" => {
508 if let Some(prm) = legacy_prm.as_mut() {
511 prm.length = parse_number(value_pair)?;
512
513 let current_max_length = prm
515 .data_const
516 .iter()
517 .map(|(offset, values)| offset + values.len())
518 .max()
519 .unwrap_or(0);
520
521 if usize::from(prm.length) < current_max_length {
522 return Err(parse_error(
523 format!(
524 "User_Prm_Data has maximum length of {} while User_Prm_Data_Len only permits {}",
525 current_max_length,
526 prm.length,
527 ),
528 statement_span,
529 ));
530 }
531 }
532 }
533 "user_prm_data" => {
534 if let Some(prm) = legacy_prm.as_mut() {
537 let values: Vec<u8> = parse_number_list(value_pair)?;
538
539 if prm.length != 0 && usize::from(prm.length) < values.len() {
541 return Err(parse_error(
542 format!(
543 "User_Prm_Data has maximum length of {} while User_Prm_Data_Len only permits {}",
544 values.len(),
545 prm.length,
546 ),
547 statement_span,
548 ));
549 }
550
551 prm.data_const.push((0, values));
552 }
553 }
554 "unit_diag_bit" => {
555 let bit = parse_number(value_pair)?;
556 let text = parse_string_literal(pairs.next().unwrap());
557 gsd.unit_diag.bits.entry(bit).or_default().text = text;
558 }
559 "unit_diag_bit_help" => {
560 let bit = parse_number(value_pair)?;
561 let text = parse_string_literal(pairs.next().unwrap());
562 gsd.unit_diag.bits.entry(bit).or_default().help = Some(text);
563 }
564 "unit_diag_not_bit" => {
565 let bit = parse_number(value_pair)?;
566 let text = parse_string_literal(pairs.next().unwrap());
567 gsd.unit_diag.not_bits.entry(bit).or_default().text = text;
568 }
569 "unit_diag_not_bit_help" => {
570 let bit = parse_number(value_pair)?;
571 let text = parse_string_literal(pairs.next().unwrap());
572 gsd.unit_diag.not_bits.entry(bit).or_default().help = Some(text);
573 }
574 _ => (),
575 }
576 }
577 _ => (),
578 }
579 }
580
581 if let Some(prm) = legacy_prm {
583 gsd.user_prm_data = prm;
584 }
585
586 if !gsd.modular_station {
588 if !gsd.max_modules == 1 {
589 }
591 if !gsd.available_modules.len() == 1 {
592 }
594 gsd.max_modules = 1;
595 }
596
597 Ok(gsd)
598}