gtk_ui/
parser.rs

1use super::lexer::{
2    Token,
3    TokenValue,
4    DefinitionType as TokenDefinitionType,
5    DirectiveType as TokenDirectiveType,
6    IdentifierType as TokenIdentifierType,
7    TypeIdentifierType as TokenTypeIdentifierType
8};
9use std::path::Path;
10use std::ops::Range;
11
12// Statement
13
14#[derive(Debug, Clone)]
15pub struct Property {
16    pub internal_type: TokenTypeIdentifierType,
17    pub name: String,
18    pub definition_type: TokenDefinitionType
19}
20
21#[derive(Debug, Clone)]
22pub enum DefinitionType {
23    Raw,
24    Collective,
25    Root(String)
26}
27
28#[derive(Debug, Clone)]
29pub struct Definition {
30    pub name: String,
31    pub children: Vec<Statement>,
32    pub inherits: Vec<String>,
33    pub definition_type: DefinitionType
34}
35
36#[derive(Debug, Clone)]
37pub struct Setter {
38    pub name: String,
39    pub value: Token,
40    pub range: Range<usize>
41}
42
43#[derive(Debug, Clone)]
44pub struct Object {
45    pub name: String,
46    pub children: Vec<Statement>,
47    pub arguments: Vec<Token>,
48    pub setters: Vec<Setter>
49}
50
51#[derive(Debug, Clone)]
52pub enum StatementValue {
53    Property(Property),
54    Definition(Definition),
55    Object(Object),
56    Header(String),
57    Include(String)
58}
59
60#[derive(Debug, Clone)]
61pub struct Statement {
62    pub value: StatementValue,
63    pub range: Range<usize>
64}
65
66impl Statement {
67    pub fn to_string(&self) -> &str {
68        match &self.value {
69            StatementValue::Property(_) => "Property",
70            StatementValue::Definition(_) => "Definition",
71            StatementValue::Object(_) => "Object",
72            StatementValue::Header(_) => "Header",
73            StatementValue::Include(_) => "Include"
74        }
75    }
76}
77
78// Parser
79
80pub struct Parser {
81    pub statements: Vec<Statement>,
82    index: usize,
83    tokens: Vec<Token>,
84    filename: String
85}
86
87impl Parser {
88    // Parsing Functions
89
90    fn block(&mut self) -> Result<(Vec<Statement>, Range<usize>), (String, Range<usize>)> {
91        if let Some(token) = self.tokens.get(self.index) {
92            let token_range = token.range.clone();
93            if let TokenValue::StartBlock = token.value {
94                self.index += 1;
95                let mut statements = Vec::new();
96                loop {
97                    if let Some(token) = self.tokens.get(self.index) {
98                        if let TokenValue::EndBlock = token.value {
99                            self.index += 1;
100                            break;
101                        }
102                        match self.parse_statement() {
103                            Some(result) => {
104                                match result {
105                                    Ok(statement) => {
106                                        match &statement.value {
107                                            StatementValue::Property(_) | StatementValue::Object(_) => statements.push(statement),
108                                            _ => return Err((format!("found {} inside block. Only properties and objects are allowed here.", statement.to_string()), statement.range)),
109                                        }
110                                    },
111                                    Err(err) => return Err(err)
112                                }
113                            }
114                            None => continue
115                        }
116                    }
117                }
118                Ok(( statements, token_range ))
119            } else {
120                Err((format!("expected the start of a block, found {}", token.to_string()), token.range.clone()))
121            }
122        } else {
123            Err((format!("expected the start of a block, found nothing"), self.statements[self.statements.len()-1].range.clone()))
124        }
125    }
126
127    fn arglist(&mut self) -> Result<(Vec<Token>, Range<usize>), (String, Range<usize>)> {
128        if let Some(token) = self.tokens.get(self.index) {
129            if let TokenValue::StartArgList = token.value {
130                let mut args: Vec<Token> = Vec::new();
131                loop {
132                    self.index += 1;
133                    if let Some(token) = self.tokens.get(self.index) {
134                        match &token.value {
135                            TokenValue::Number(_) | TokenValue::String(_) | TokenValue::Bool(_) => args.push(token.clone()),
136                            TokenValue::Identifier(_identifier) => {
137                                args.push(token.clone())
138                            },
139                            _ => return Err((format!("found {}, expected Number, String, Bool, or type identifier", token.to_string()), token.range.clone()))
140                        }
141
142                        self.index += 1;
143                        if let Some(token) = self.tokens.get(self.index) {
144                            match token.value {
145                                TokenValue::ArgListDeliminator => continue,
146                                TokenValue::EndArgList => break,
147                                _ => return Err((format!("found '{}', expected ','", token.to_string()), token.range.clone()))
148                            }
149                        } else {
150                            return Err((format!("expected ',', found nothing"), token.range.clone()));
151                        }
152                    } else {
153                        return Err((format!("expected Number, String, Bool, or type identifier, found nothing"), token.range.clone()));
154                    }
155                }
156                self.index += 1;
157                Ok(( args, token.range.clone() ))
158            } else {
159                Err((format!("expected start of argument list, found {}", token.to_string()), token.range.clone()))
160            }
161        } else {
162            Err((format!("expected start of argument list, found nothing"), self.statements[self.statements.len()-1].range.clone()))
163        }
164    }
165
166    fn definition(&mut self, definition_type: TokenDefinitionType, range: Range<usize>) -> Result<Statement, (String, Range<usize>)> {
167        self.index += 1;
168        if let TokenDefinitionType::Object(name) = definition_type {
169            if let Some(token) = self.tokens.get(self.index) {
170                let mut inherits: Vec<String> = Vec::new();
171                match &token.value {
172                    TokenValue::StartBlock => (),
173                    TokenValue::Inherits => {
174                        self.index += 1;
175                        if let Some(token) = self.tokens.get(self.index) {
176                            match &token.value {
177                                TokenValue::StartArgList => {
178                                    match self.arglist() {
179                                        Ok(arglist) => {
180                                            for token in arglist.0 {
181                                                if let TokenValue::Identifier(TokenIdentifierType::Generic(parent)) = &token.value {
182                                                    inherits.push(parent.clone());
183                                                } else {
184                                                    return Err((String::from("argument list of parents must only contain definitions"), arglist.1.clone()));
185                                                }
186                                            }
187                                        },
188                                        Err(err) => {
189                                            return Err(err);
190                                        }
191                                    }
192                                },
193                                TokenValue::Identifier(TokenIdentifierType::Generic(parent)) => {
194                                    inherits.push(parent.clone());
195                                    self.index += 1;
196                                },
197                                _ => return Err((format!("expected an argument list or definition, found {}", token.to_string()), token.range.clone()))
198                            }
199                        } else {
200                            return Err((format!("expected an argument list or definition, found nothing"), token.range.clone()));
201                        }
202                    },
203                    _ => return Err((format!("expected a '->' or '{{', found '{}'", token.to_string()), token.range.clone()))
204                }
205                match self.block() {
206                    Ok(block) => {
207                        let definition_type = {
208                            if block.0.iter().all(|x| matches!(&x.value, StatementValue::Property(_))) {
209                                DefinitionType::Raw
210                            } else if block.0.iter().all(|x| matches!(&x.value, StatementValue::Object(_))) {
211                                if name == "root" {
212                                    let path = Path::new(&self.filename);
213                                    DefinitionType::Root(path.file_stem().expect("invalid file path").to_str().expect("failed to unwrap file path string").to_string())
214                                } else {
215                                    DefinitionType::Collective
216                                }
217                            } else {
218                                return Err((String::from("a definition can only have all property definitions or all objects"), block.1));
219                            }
220                        };
221
222                        let definition = Definition {
223                            name: name.to_string(),
224                            children: block.0,
225                            definition_type,
226                            inherits
227                        };
228
229                        Ok(Statement {
230                            value: StatementValue::Definition(definition),
231                            range: range.clone()
232                        })
233                    },
234                    Err(err) => return Err(err)
235                }
236            } else {
237                Err((format!("expected block or inherit statement, found nothing"), range))
238            }
239        } else {
240            match self.arglist() {
241                Ok(arglist) => {
242                    if arglist.0.len() != 2 {
243                        return Err((format!("expected only 2 arguments, found {} args", arglist.0.len()), arglist.1));
244                    }
245                    
246                    let name = &arglist.0[0];
247                    if let TokenValue::String(name) = &name.value {
248                        let internal_type = &arglist.0[1];
249                        if let TokenValue::Identifier(TokenIdentifierType::Type(internal_type)) = &internal_type.value {
250                            let property = Property {
251                                name: name.clone(),
252                                internal_type: internal_type.clone(),
253                                definition_type: definition_type.clone()
254                            };
255                            Ok(Statement {
256                                value: StatementValue::Property(property),
257                                range: range.clone()
258                            })
259                        } else {
260                            return Err((format!("expected type identifier, found {}", internal_type.to_string()), internal_type.range.clone()));
261                        }
262                    } else {
263                        return Err((format!("expected String, found {}", name.to_string()), name.range.clone()));
264                    }
265                },
266                Err(err) => return Err(err)
267            }
268        }
269    }
270
271    fn directive(&mut self, directive_type: TokenDirectiveType, range: Range<usize>) -> Result<Statement, (String, Range<usize>)> {
272        self.index += 1;
273        if let Some(token) = self.tokens.get(self.index) {
274            if let TokenValue::String(arg) = &token.value {
275                self.index += 1;
276                let value = match directive_type {
277                    TokenDirectiveType::Header => {
278                        StatementValue::Header(arg.clone())
279                    },
280                    TokenDirectiveType::Include => {
281                        StatementValue::Include(arg.clone())
282                    }
283                };
284                Ok(Statement {
285                    value,
286                    range: range.clone()
287                })
288            } else {
289                Err((format!("expected string, found {}", token.to_string()), token.range.clone()))
290            }
291        } else {
292            Err((format!("expected string, found nothing"), range))
293        }
294    }
295
296    fn object(&mut self, identifier_type: TokenIdentifierType, range: Range<usize>) -> Result<Statement, (String, Range<usize>)> {
297        if let TokenIdentifierType::Generic(name) = identifier_type {
298            self.index += 1;
299            if let Some(token) = self.tokens.get(self.index) {
300                let mut arguments = Vec::new();
301                let mut children = Vec::new();
302                let mut setters = Vec::new();
303                let token_range = token.range.clone(); // TODO there might be a better way of handling this
304                
305                match token.value {
306                    TokenValue::StartArgList => {
307                        match self.arglist() {
308                            Ok(args) => {
309                                arguments = args.0;
310                                if let Some(token) = self.tokens.get(self.index) {
311                                    if let TokenValue::StartBlock = token.value {
312                                        match self.block() {
313                                            Ok(c) => children = c.0,
314                                            Err(e) => return Err(e)
315                                        }
316                                    }
317                                } else {
318                                    return Err((format!("expected block, found nothing"), token_range))
319                                }
320                            },
321                            Err(err) => return Err(err)
322                        }
323                    },
324                    TokenValue::StartBlock => {
325                        match self.block() {
326                            Ok(c) => children = c.0,
327                            Err(e) => return Err(e)
328                        }
329                    },
330                    _ => return Err((format!("expected the start of an argument list or block, found '{}'", token.to_string()), token.range.clone()))
331                }
332
333                loop {
334                    if let Some(token) = self.tokens.get(self.index) {
335                        let token_range = token.range.clone();
336                        match &token.value {
337                            TokenValue::Identifier(_) | TokenValue::EndBlock => break,
338                            TokenValue::Setter(name) => {
339                                self.index += 1;
340                                let name = name.clone();
341
342                                match self.arglist() {
343                                    Ok(args) => {
344                                        if args.0.len() != 1 {
345                                            return Err((format!("expected 1 argument, got {}", args.0.len()), args.1));
346                                        }
347
348                                        let value = &args.0[0];
349
350                                        match &value.value {
351                                            TokenValue::Number(_) | TokenValue::String(_) | TokenValue::Bool(_) => {
352                                                setters.push(Setter {
353                                                    name: name,
354                                                    value: value.clone(),
355                                                    range: token_range
356                                                })
357                                            },
358                                            _ => return Err((format!("expected Number, String, or Bool, found {}", value.to_string()), value.range.clone()))
359                                        }
360                                    },
361                                    Err(err) => return Err(err)
362                                }
363                            },
364                            _ => {
365                                return Err((format!("expected setter, found {}", token.to_string()), token_range));
366                            }
367                        }
368                    }
369                }
370                
371                Ok(Statement {
372                    value: StatementValue::Object(
373                        Object {
374                            arguments,
375                            name: name.clone(),
376                            children,
377                            setters
378                        }
379                    ),
380                    range: range.clone()
381                })
382            } else {
383                Err((format!("expected argument list or block, found nothing"), range))
384            }
385        } else {
386            Err((format!("expected generic identifier, found type identifier"), range))
387        }
388    }
389
390    fn parse_statement(&mut self) -> Option<Result<Statement, (String, Range<usize>)>> {
391        if let Some(token) = self.tokens.get(self.index) {
392            match &token.value {
393                TokenValue::Definition(definition) => {
394                    let definition = definition.clone();
395                    Some(self.definition(definition, token.range.clone()))
396                },
397                TokenValue::Directive(directive) => {
398                    let directive = directive.clone();
399                    Some(self.directive(directive, token.range.clone()))
400                },
401                TokenValue::Identifier(identifier) => {
402                    let identifier = identifier.clone();
403                    Some(self.object(identifier, token.range.clone()))
404                },
405                TokenValue::Comment => None,
406                _ => Some(Err(( format!("unexpected {}", token.to_string()), token.range.clone() )))
407            }
408        } else {
409            Some(Err((format!("expected definition, directive, or identifier, found nothing"), self.statements[self.statements.len()-1].range.clone())))
410        }
411    }
412
413    // Pubs
414    pub fn new(tokens: Vec<Token>, filename: String) -> Parser {
415        return Parser {
416            statements: Vec::new(),
417            index: 0,
418            tokens,
419            filename
420        }
421    }
422
423    pub fn parse(&mut self) -> Result<(), (String, Range<usize>)> {
424        loop {
425            if self.index >= self.tokens.len() {
426                break Ok(())
427            }
428            match self.parse_statement() {
429                Some(result) => {
430                    match result {
431                        Ok(statement) => {
432                            match &statement.value {
433                                StatementValue::Definition(_) | StatementValue::Header(_) | StatementValue::Include(_) => self.statements.push(statement),
434                                _ => return Err(( format!("found {} on top level. Only object definitions and directives are allowed here.", statement.to_string()), statement.range )),
435                            }
436                        },
437                        Err(err) => return Err(err)
438                    }
439                },
440                None => continue
441            }
442        }
443    }
444}