1#![deny(missing_docs)]
2
3use header_parsing::parse_header;
26use logical_expressions::{LogicalExpression, ParseError};
27use thiserror::Error;
28
29use multilinear::{Channel, Condition, Event, InvalidChangeError, MultilinearInfo};
30
31use std::{
32 io::{BufRead, BufReader, Read},
33 marker::PhantomData,
34};
35
36pub struct IndexMap<I: Into<usize> + From<usize>, V> {
38 entries: Vec<V>,
39 index: PhantomData<I>,
40}
41
42impl<I: Into<usize> + From<usize>, V> Default for IndexMap<I, V> {
43 fn default() -> Self {
44 Self {
45 entries: Vec::new(),
46 index: PhantomData,
47 }
48 }
49}
50
51impl<I: Into<usize> + From<usize>, V> IndexMap<I, V> {
52 fn insert(&mut self, index: I, value: V) {
53 let i = index.into();
54 assert_eq!(i, self.entries.len(), "Wrong insertion order");
55 self.entries.push(value);
56 }
57}
58
59pub struct IntoIter<I: Into<usize> + From<usize>, V> {
61 data: std::iter::Enumerate<std::vec::IntoIter<V>>,
62 index: PhantomData<I>,
63}
64
65impl<I: Into<usize> + From<usize>, V> Iterator for IntoIter<I, V> {
66 type Item = (I, V);
67
68 fn next(&mut self) -> Option<(I, V)> {
69 let (i, value) = self.data.next()?;
70 Some((i.into(), value))
71 }
72}
73
74impl<I: Into<usize> + From<usize>, V> IntoIterator for IndexMap<I, V> {
75 type Item = (I, V);
76 type IntoIter = IntoIter<I, V>;
77
78 fn into_iter(self) -> IntoIter<I, V> {
79 IntoIter {
80 data: self.entries.into_iter().enumerate(),
81 index: PhantomData,
82 }
83 }
84}
85
86#[derive(Copy, Clone, Debug)]
87struct ValueCheckingError(char);
88
89type Str = Box<str>;
90
91fn check_name(name: &str) -> Result<(), ValueCheckingError> {
92 if let Some(c) = name
93 .chars()
94 .find(|&c| !c.is_alphanumeric() && !"_- ".contains(c))
95 {
96 Err(ValueCheckingError(c))
97 } else {
98 Ok(())
99 }
100}
101
102fn valid_name(name: &str) -> Result<&str, ValueCheckingError> {
103 let name = name.trim();
104 check_name(name)?;
105 Ok(name)
106}
107
108fn value_index(value_names: &mut Vec<Str>, name: &str) -> Result<usize, ValueCheckingError> {
109 let name = valid_name(name)?;
110
111 if let Some(index) = value_names.iter().position(|x| x.as_ref() == name) {
112 return Ok(index);
113 }
114
115 let index = value_names.len();
116 value_names.push(name.into());
117 Ok(index)
118}
119
120fn channel_info<'a>(
121 channels: &'a mut IndexMap<Channel, (Str, Vec<Str>)>,
122 name: &str,
123 info: &mut MultilinearInfo,
124) -> Result<(Channel, &'a mut Vec<Str>), ValueCheckingError> {
125 let name = valid_name(name)?;
126
127 if let Some(i) = channels
128 .entries
129 .iter()
130 .position(|(checked_name, _)| checked_name.as_ref() == name)
131 {
132 return Ok((Channel(i), &mut channels.entries[i].1));
133 }
134
135 let channel = info.add_channel();
136 channels.insert(channel, (name.into(), Vec::new()));
137
138 let (_, value_names) = channels.entries.last_mut().unwrap();
139
140 let _ = value_index(value_names, "");
141
142 Ok((channel, value_names))
143}
144
145#[derive(Copy, Clone, Debug, Error)]
147pub enum ConditionParsingError {
148 #[error("Invalid character '{0}' for condition names")]
150 InvalidCharacter(char),
151
152 #[error("Invalid condition format")]
154 InvalidCondition,
155}
156
157impl From<ValueCheckingError> for ConditionParsingError {
158 fn from(ValueCheckingError(c): ValueCheckingError) -> Self {
159 Self::InvalidCharacter(c)
160 }
161}
162
163#[derive(Copy, Clone, Debug, Error)]
165pub enum ErrorKind {
166 #[error("Input error while parsing line")]
168 LineParsing,
169
170 #[error("Parsing expression failed: {0}")]
172 ExpressionParsing(ParseError<ConditionParsingError>),
173
174 #[error("Encountered conflicting conditions: {0}")]
176 ConflictingCondition(InvalidChangeError),
177
178 #[error("Invalid character '{0}' in event name")]
180 InvalidCharacterInEventName(char),
181
182 #[error("No event has been specified")]
184 NoEvent,
185
186 #[error("Subheader without matching header")]
188 SubheaderWithoutHeader,
189}
190
191trait ErrorLine {
192 type Output;
193
194 fn line(self, line: usize) -> Self::Output;
195}
196
197impl ErrorLine for ErrorKind {
198 type Output = Error;
199
200 fn line(self, line: usize) -> Error {
201 Error { line, kind: self }
202 }
203}
204
205impl<T> ErrorLine for Result<T, ErrorKind> {
206 type Output = Result<T, Error>;
207
208 fn line(self, line: usize) -> Result<T, Error> {
209 match self {
210 Ok(value) => Ok(value),
211 Err(err) => Err(err.line(line)),
212 }
213 }
214}
215
216#[derive(Debug, Error)]
218#[error("Line {line}: {kind}")]
219pub struct Error {
220 line: usize,
222 kind: ErrorKind,
224}
225
226#[derive(Default)]
228pub struct NamedMultilinearInfo {
229 pub info: MultilinearInfo,
231 pub events: IndexMap<Event, Vec<Str>>,
233 pub channels: IndexMap<Channel, (Str, Vec<Str>)>,
235}
236
237#[derive(Default)]
240pub struct MultilinearParser(NamedMultilinearInfo);
241
242impl MultilinearParser {
243 pub fn parse<R: Read>(&mut self, reader: R, mut namespace: Vec<Str>) -> Result<(), Error> {
261 let NamedMultilinearInfo {
262 info,
263 events,
264 channels,
265 } = &mut self.0;
266
267 let mut condition_groups = Vec::new();
268 let mut condition_lines = Vec::new();
269
270 let mut last_header_line = 0;
271
272 for (line_number, line) in BufReader::new(reader).lines().enumerate() {
273 let Ok(line) = line else {
274 return Err(ErrorKind::LineParsing.line(line_number));
275 };
276
277 if line.trim().is_empty() {
278 if !condition_lines.is_empty() {
279 condition_groups.push(LogicalExpression::and(condition_lines));
280 condition_lines = Vec::new();
281 }
282 continue;
283 }
284
285 if let Some(success) = parse_header(&mut namespace, &line) {
286 let Ok(changes) = success else {
287 return Err(ErrorKind::SubheaderWithoutHeader.line(line_number));
288 };
289
290 if let Err(ValueCheckingError(c)) = check_name(&changes.header) {
291 return Err(ErrorKind::InvalidCharacterInEventName(c)).line(line_number);
292 }
293
294 if !condition_lines.is_empty() {
295 condition_groups.push(LogicalExpression::and(condition_lines));
296 condition_lines = Vec::new();
297 }
298
299 if !condition_groups.is_empty() {
300 let mut event_edit = info.add_event();
301 for conditions in LogicalExpression::or(condition_groups).expand() {
302 if let Err(err) = event_edit.add_change(&conditions) {
303 return Err(ErrorKind::ConflictingCondition(err).line(last_header_line));
304 }
305 }
306
307 events.insert(event_edit.event(), changes.path.clone());
308
309 condition_groups = Vec::new();
310 }
311
312 last_header_line = line_number + 1;
313
314 changes.apply();
315
316 continue;
317 }
318
319 if namespace.is_empty() {
320 return Err(ErrorKind::NoEvent.line(line_number));
321 }
322
323 let parse_expression = |condition: &str| {
324 let Some((channel, changes)) = condition.split_once(':') else {
325 return Err(ConditionParsingError::InvalidCondition);
326 };
327
328 let (channel, value_names) = channel_info(channels, channel.trim(), info)?;
329 Ok(LogicalExpression::or(
330 changes
331 .split(';')
332 .map(|change| -> Result<_, ValueCheckingError> {
333 Ok(LogicalExpression::Condition(
334 if let Some((from, to)) = change.split_once('>') {
335 let from = value_index(value_names, from)?;
336 let to = value_index(value_names, to)?;
337 Condition::change(channel, from, to)
338 } else {
339 let change = value_index(value_names, change)?;
340 Condition::new(channel, change)
341 },
342 ))
343 })
344 .collect::<Result<_, _>>()?,
345 ))
346 };
347
348 let conditions = LogicalExpression::parse_with_expression(&line, parse_expression);
349
350 let conditions = match conditions {
351 Ok(conditions) => conditions,
352 Err(err) => return Err(ErrorKind::ExpressionParsing(err).line(line_number)),
353 };
354
355 condition_lines.push(conditions);
356 }
357
358 if !condition_lines.is_empty() {
359 condition_groups.push(LogicalExpression::and(condition_lines));
360 }
361
362 if !condition_groups.is_empty() {
363 let mut event_edit = info.add_event();
364 for conditions in LogicalExpression::or(condition_groups).expand() {
365 if let Err(err) = event_edit.add_change(&conditions) {
366 return Err(ErrorKind::ConflictingCondition(err).line(last_header_line));
367 }
368 }
369
370 events.insert(event_edit.event(), namespace);
371 }
372
373 Ok(())
374 }
375
376 pub fn into_info(self) -> NamedMultilinearInfo {
380 self.0
381 }
382}
383
384pub fn parse_multilinear<R: Read>(reader: R) -> Result<NamedMultilinearInfo, Error> {
398 let mut result = MultilinearParser::default();
399 result.parse(reader, Vec::new())?;
400 Ok(result.0)
401}