s_expr/
parser.rs

1use super::data::{Atom, GroupKind};
2use super::loc::{Position, Span, Spanned};
3use super::tokenizer::{Token, TokenError, Tokenizer, TokenizerConfig};
4
5/// Element of S-Expr
6#[derive(Debug, Clone)]
7pub enum Element<'a> {
8    Group(GroupKind, Vec<SpannedElement<'a>>),
9    Atom(Atom<'a>),
10    Comment(&'a str),
11}
12
13impl<'a> Element<'a> {
14    /// Return the atom if the element is an atom, otherwise None
15    pub fn atom(&self) -> Option<&Atom<'a>> {
16        match self {
17            Element::Group(_, _) => None,
18            Element::Comment(_) => None,
19            Element::Atom(a) => Some(a),
20        }
21    }
22
23    /// Return the group elements if the element is a group of the right type, otherwise None
24    pub fn group(&self, grp: GroupKind) -> Option<&[SpannedElement<'a>]> {
25        match self {
26            Element::Group(got_grp, elements) if *got_grp == grp => Some(elements),
27            Element::Group(_, _) => None,
28            Element::Comment(_) => None,
29            Element::Atom(_) => None,
30        }
31    }
32
33    /// Return the group elements if the element is a paren group, otherwise None
34    pub fn paren(&self) -> Option<&[SpannedElement<'a>]> {
35        self.group(GroupKind::Paren)
36    }
37
38    /// Return the group elements if the element is a bracket group, otherwise None
39    pub fn bracket(&self) -> Option<&[SpannedElement<'a>]> {
40        self.group(GroupKind::Bracket)
41    }
42
43    /// Return the group elements if the element is a brace group, otherwise None
44    pub fn brace(&self) -> Option<&[SpannedElement<'a>]> {
45        self.group(GroupKind::Brace)
46    }
47}
48
49/// Spanned Element
50pub type SpannedElement<'a> = Spanned<Element<'a>>;
51
52/// S-Expr Parser
53pub struct Parser<'a> {
54    tokenizer: Tokenizer<'a>,
55}
56
57/// Parser Error, which are either token error or some error related to group balancing
58/// like unterminated group, or mismatch of group
59#[derive(Debug, Clone)]
60pub enum ParserError {
61    UnbalancedEmpty(Position, GroupKind),
62    UnbalancedMismatch {
63        span: Span,
64        expected: GroupKind,
65        got: GroupKind,
66    },
67    UnfinishedGroup(GroupKind),
68    TokenizerError(TokenError),
69}
70
71impl From<TokenError> for ParserError {
72    fn from(t: TokenError) -> ParserError {
73        ParserError::TokenizerError(t)
74    }
75}
76
77impl<'a> Parser<'a> {
78    pub fn new_with_config(data: &'a str, cfg: TokenizerConfig) -> Self {
79        Parser {
80            tokenizer: Tokenizer::new_with_config(data, cfg),
81        }
82    }
83
84    pub fn new(data: &'a str) -> Self {
85        Parser {
86            tokenizer: Tokenizer::new(data),
87        }
88    }
89
90    pub fn next(&mut self) -> Result<Option<SpannedElement<'a>>, ParserError> {
91        let mut out: Vec<(GroupKind, Span, Vec<SpannedElement<'a>>)> = vec![];
92        loop {
93            match self.tokenizer.next()? {
94                None => match out.last() {
95                    None => return Ok(None),
96                    Some((grp, _, _)) => return Err(ParserError::UnfinishedGroup(*grp)),
97                },
98                Some(tok) => match tok.inner {
99                    Token::Comment(comment) => {
100                        let el = Spanned {
101                            span: tok.span,
102                            inner: Element::Comment(comment),
103                        };
104                        match out.last_mut() {
105                            None => return Ok(Some(el)),
106                            Some((_, _, elements)) => {
107                                elements.push(el);
108                            }
109                        }
110                    }
111                    Token::Atom(atom) => {
112                        let el = Spanned {
113                            span: tok.span,
114                            inner: Element::Atom(atom),
115                        };
116                        match out.last_mut() {
117                            None => return Ok(Some(el)),
118                            Some((_, _, elements)) => {
119                                elements.push(el);
120                            }
121                        }
122                    }
123                    Token::Left(grp) => {
124                        // create a new group
125                        out.push((grp, tok.span, Vec::new()));
126                    }
127                    Token::Right(grp) => match out.pop() {
128                        None => {
129                            return Err(ParserError::UnbalancedEmpty(tok.span.start, grp));
130                        }
131                        Some((inner_grp, inner_start, inner_elements)) => {
132                            if inner_grp != grp {
133                                return Err(ParserError::UnbalancedMismatch {
134                                    span: inner_start.extend(&tok.span),
135                                    expected: inner_grp,
136                                    got: grp,
137                                });
138                            }
139                            let inner = Spanned {
140                                span: inner_start.extend(&tok.span),
141                                inner: Element::Group(grp, inner_elements),
142                            };
143                            match out.last_mut() {
144                                None => return Ok(Some(inner)),
145                                Some((_, _, elements)) => {
146                                    elements.push(inner);
147                                }
148                            }
149                        }
150                    },
151                },
152            }
153        }
154    }
155}