dts_core/parsers/
gron.rs

1use super::{ParseError, ParseErrorKind};
2use crate::Result;
3use pest::Parser as ParseTrait;
4use pest_derive::Parser;
5use std::slice::Iter;
6
7#[derive(Parser)]
8#[grammar = "parsers/grammars/gron.pest"]
9struct GronParser;
10
11/// Parses `Statements` from a `&str`.
12pub fn parse(s: &str) -> Result<Statements<'_>, ParseError> {
13    let statements = GronParser::parse(Rule::Statements, s)
14        .map_err(|e| ParseError::new(ParseErrorKind::Gron, e))?
15        .into_iter()
16        .filter_map(|pair| match pair.as_rule() {
17            Rule::Statement => {
18                let mut inner = pair.into_inner();
19                // Guaranteed by the grammar that these will exist so unchecked unwrap here is
20                // safe.
21                let path = inner.next().unwrap().as_str();
22                let value = inner.next().unwrap().as_str();
23
24                Some(Statement::new(path, value))
25            }
26            Rule::EOI => None,
27            _ => unreachable!(),
28        })
29        .collect();
30
31    Ok(statements)
32}
33
34#[derive(Debug, PartialEq)]
35pub struct Statement<'a> {
36    path: &'a str,
37    value: &'a str,
38}
39
40impl<'a> Statement<'a> {
41    pub fn new(path: &'a str, value: &'a str) -> Self {
42        Self { path, value }
43    }
44
45    pub fn path(&self) -> &'a str {
46        self.path
47    }
48
49    pub fn value(&self) -> &'a str {
50        self.value
51    }
52}
53
54#[derive(Debug, PartialEq)]
55pub struct Statements<'a> {
56    inner: Vec<Statement<'a>>,
57}
58
59impl<'a> Statements<'a> {
60    pub fn iter(&self) -> Iter<'a, Statement> {
61        self.inner.iter()
62    }
63}
64
65impl<'a> FromIterator<Statement<'a>> for Statements<'a> {
66    fn from_iter<T>(iter: T) -> Self
67    where
68        T: IntoIterator<Item = Statement<'a>>,
69    {
70        Self {
71            inner: iter.into_iter().collect(),
72        }
73    }
74}
75
76impl<'a> IntoIterator for Statements<'a> {
77    type Item = Statement<'a>;
78    type IntoIter = std::vec::IntoIter<Self::Item>;
79
80    fn into_iter(self) -> Self::IntoIter {
81        self.inner.into_iter()
82    }
83}
84
85#[cfg(test)]
86mod test {
87    use super::*;
88    use pretty_assertions::assert_eq;
89
90    #[test]
91    fn test_parse() {
92        assert_eq!(
93            parse("foo.bar = \"baz\";").unwrap(),
94            Statements::from_iter(vec![Statement::new("foo.bar", "\"baz\"")])
95        );
96        assert_eq!(
97            parse("foo.bar[5].baz = []").unwrap(),
98            Statements::from_iter(vec![Statement::new("foo.bar[5].baz", "[]")])
99        );
100        assert_eq!(
101            parse("foo = \"bar\"; baz = 1").unwrap(),
102            Statements::from_iter(vec![
103                Statement::new("foo", "\"bar\""),
104                Statement::new("baz", "1")
105            ])
106        );
107    }
108}