1use super::{
2 comment,
3 errors::{ErrorKind, ParserError},
4 slice::Slice,
5};
6use crate::ast;
7
8pub type Result<T> = std::result::Result<T, ParserError>;
9
10pub struct Parser<S> {
11 pub(super) source: S,
12 pub(super) ptr: usize,
13 pub(super) length: usize,
14}
15
16impl<'s, S> Parser<S>
17where
18 S: Slice<'s>,
19{
20 pub fn new(source: S) -> Self {
21 let length = source.as_ref().as_bytes().len();
22 Self {
23 source,
24 ptr: 0,
25 length,
26 }
27 }
28
29 pub fn parse(
30 mut self,
31 ) -> std::result::Result<ast::Resource<S>, (ast::Resource<S>, Vec<ParserError>)> {
32 let mut errors = vec![];
33
34 let mut body = vec![];
35
36 self.skip_blank_block();
37 let mut last_comment = None;
38 let mut last_blank_count = 0;
39
40 while self.ptr < self.length {
41 let entry_start = self.ptr;
42 let mut entry = self.get_entry(entry_start);
43
44 if let Some(comment) = last_comment.take() {
45 match entry {
46 Ok(ast::Entry::Message(ref mut msg)) if last_blank_count < 2 => {
47 msg.comment = Some(comment);
48 }
49 Ok(ast::Entry::Term(ref mut term)) if last_blank_count < 2 => {
50 term.comment = Some(comment);
51 }
52 _ => {
53 body.push(ast::Entry::Comment(comment));
54 }
55 }
56 }
57
58 match entry {
59 Ok(ast::Entry::Comment(comment)) => {
60 last_comment = Some(comment);
61 }
62 Ok(entry) => {
63 body.push(entry);
64 }
65 Err(mut err) => {
66 self.skip_to_next_entry_start();
67 err.slice = Some(entry_start..self.ptr);
68 errors.push(err);
69 let content = self.source.slice(entry_start..self.ptr);
70 body.push(ast::Entry::Junk { content });
71 }
72 }
73 last_blank_count = self.skip_blank_block();
74 }
75
76 if let Some(last_comment) = last_comment.take() {
77 body.push(ast::Entry::Comment(last_comment));
78 }
79 if errors.is_empty() {
80 Ok(ast::Resource { body })
81 } else {
82 Err((ast::Resource { body }, errors))
83 }
84 }
85
86 fn get_entry(&mut self, entry_start: usize) -> Result<ast::Entry<S>> {
87 let entry = match get_current_byte!(self) {
88 Some(b'#') => {
89 let (comment, level) = self.get_comment()?;
90 match level {
91 comment::Level::Regular => ast::Entry::Comment(comment),
92 comment::Level::Group => ast::Entry::GroupComment(comment),
93 comment::Level::Resource => ast::Entry::ResourceComment(comment),
94 comment::Level::None => unreachable!(),
95 }
96 }
97 Some(b'-') => ast::Entry::Term(self.get_term(entry_start)?),
98 _ => ast::Entry::Message(self.get_message(entry_start)?),
99 };
100 Ok(entry)
101 }
102
103 pub fn get_message(&mut self, entry_start: usize) -> Result<ast::Message<S>> {
104 let id = self.get_identifier()?;
105 self.skip_blank_inline();
106 self.expect_byte(b'=')?;
107 let pattern = self.get_pattern()?;
108
109 self.skip_blank_block();
110
111 let attributes = self.get_attributes();
112
113 if pattern.is_none() && attributes.is_empty() {
114 let entry_id = id.name.as_ref().to_owned();
115 return error!(
116 ErrorKind::ExpectedMessageField { entry_id },
117 entry_start, self.ptr
118 );
119 }
120
121 Ok(ast::Message {
122 id,
123 value: pattern,
124 attributes,
125 comment: None,
126 })
127 }
128
129 pub fn get_term(&mut self, entry_start: usize) -> Result<ast::Term<S>> {
130 self.expect_byte(b'-')?;
131 let id = self.get_identifier()?;
132 self.skip_blank_inline();
133 self.expect_byte(b'=')?;
134 self.skip_blank_inline();
135
136 let value = self.get_pattern()?;
137
138 self.skip_blank_block();
139
140 let attributes = self.get_attributes();
141
142 if let Some(value) = value {
143 Ok(ast::Term {
144 id,
145 value,
146 attributes,
147 comment: None,
148 })
149 } else {
150 error!(
151 ErrorKind::ExpectedTermField {
152 entry_id: id.name.as_ref().to_owned()
153 },
154 entry_start, self.ptr
155 )
156 }
157 }
158
159 fn get_attributes(&mut self) -> Vec<ast::Attribute<S>> {
160 let mut attributes = vec![];
161
162 loop {
163 let line_start = self.ptr;
164 self.skip_blank_inline();
165 if !self.take_byte_if(b'.') {
166 self.ptr = line_start;
167 break;
168 }
169
170 if let Ok(attr) = self.get_attribute() {
171 attributes.push(attr);
172 } else {
173 self.ptr = line_start;
174 break;
175 }
176 }
177 attributes
178 }
179
180 fn get_attribute(&mut self) -> Result<ast::Attribute<S>> {
181 let id = self.get_identifier()?;
182 self.skip_blank_inline();
183 self.expect_byte(b'=')?;
184 let pattern = self.get_pattern()?;
185
186 match pattern {
187 Some(pattern) => Ok(ast::Attribute { id, value: pattern }),
188 None => error!(ErrorKind::MissingValue, self.ptr),
189 }
190 }
191
192 pub(super) fn get_identifier_unchecked(&mut self) -> ast::Identifier<S> {
193 let mut ptr = self.ptr;
194
195 while matches!(get_byte!(self, ptr), Some(b) if b.is_ascii_alphanumeric() || *b == b'-' || *b == b'_')
196 {
197 ptr += 1;
198 }
199
200 let name = self.source.slice(self.ptr - 1..ptr);
201 self.ptr = ptr;
202
203 ast::Identifier { name }
204 }
205
206 pub(super) fn get_identifier(&mut self) -> Result<ast::Identifier<S>> {
207 if !self.is_identifier_start() {
208 return error!(
209 ErrorKind::ExpectedCharRange {
210 range: "a-zA-Z".to_string()
211 },
212 self.ptr
213 );
214 }
215 self.ptr += 1;
216 Ok(self.get_identifier_unchecked())
217 }
218
219 pub(super) fn get_attribute_accessor(&mut self) -> Result<Option<ast::Identifier<S>>> {
220 if self.take_byte_if(b'.') {
221 let ident = self.get_identifier()?;
222 Ok(Some(ident))
223 } else {
224 Ok(None)
225 }
226 }
227
228 fn get_variant_key(&mut self) -> Result<ast::VariantKey<S>> {
229 self.skip_blank();
230
231 let key = if self.is_number_start() {
232 ast::VariantKey::NumberLiteral {
233 value: self.get_number_literal()?,
234 }
235 } else {
236 ast::VariantKey::Identifier {
237 name: self.get_identifier()?.name,
238 }
239 };
240
241 self.skip_blank();
242
243 self.expect_byte(b']')?;
244
245 Ok(key)
246 }
247
248 pub(super) fn get_variants(&mut self) -> Result<Vec<ast::Variant<S>>> {
249 let mut variants = Vec::with_capacity(2);
250 let mut has_default = false;
251
252 loop {
253 let default = self.take_byte_if(b'*');
254 if default {
255 if has_default {
256 return error!(ErrorKind::MultipleDefaultVariants, self.ptr);
257 } else {
258 has_default = true;
259 }
260 }
261
262 if !self.take_byte_if(b'[') {
263 break;
264 }
265
266 let key = self.get_variant_key()?;
267
268 let value = self.get_pattern()?;
269
270 if let Some(value) = value {
271 variants.push(ast::Variant {
272 key,
273 value,
274 default,
275 });
276 self.skip_blank();
277 } else {
278 return error!(ErrorKind::MissingValue, self.ptr);
279 }
280 }
281
282 if has_default {
283 Ok(variants)
284 } else {
285 error!(ErrorKind::MissingDefaultVariant, self.ptr)
286 }
287 }
288
289 pub(super) fn get_placeable(&mut self) -> Result<ast::Expression<S>> {
290 self.skip_blank();
291 let exp = self.get_expression()?;
292 self.skip_blank_inline();
293 self.expect_byte(b'}')?;
294
295 let invalid_expression_found = match &exp {
296 ast::Expression::Inline(ast::InlineExpression::TermReference {
297 ref attribute, ..
298 }) => attribute.is_some(),
299 _ => false,
300 };
301 if invalid_expression_found {
302 return error!(ErrorKind::TermAttributeAsPlaceable, self.ptr);
303 }
304
305 Ok(exp)
306 }
307}
308