1use super::data::{Atom, GroupKind};
2use super::loc::{Position, Span, Spanned};
3use super::tokenizer::{Token, TokenError, Tokenizer, TokenizerConfig};
4
5#[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 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 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 pub fn paren(&self) -> Option<&[SpannedElement<'a>]> {
35 self.group(GroupKind::Paren)
36 }
37
38 pub fn bracket(&self) -> Option<&[SpannedElement<'a>]> {
40 self.group(GroupKind::Bracket)
41 }
42
43 pub fn brace(&self) -> Option<&[SpannedElement<'a>]> {
45 self.group(GroupKind::Brace)
46 }
47}
48
49pub type SpannedElement<'a> = Spanned<Element<'a>>;
51
52pub struct Parser<'a> {
54 tokenizer: Tokenizer<'a>,
55}
56
57#[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 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}