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