ice_rs/slice/
parser.rs

1use std::collections::{BTreeSet, BTreeMap};
2use std::path::Path;
3use std::fs::File;
4use std::rc::Rc;
5use std::cell::RefCell;
6use std::io::prelude::*;
7use escape::escape;
8use inflector::cases::{classcase, pascalcase, snakecase};
9use pest::Parser;
10use pest::iterators::Pairs;
11use quote::__private::TokenStream;
12use quote::*;
13use crate::errors::*;
14use crate::slice::module::Module;
15use crate::slice::enumeration::Enum;
16use crate::slice::structure::Struct;
17use crate::slice::interface::Interface;
18use crate::slice::function::Function;
19use crate::slice::exception::Exception;
20use crate::slice::class::Class;
21use crate::slice::types::IceType;
22
23use super::{escape, function_argument::FunctionArgument, function_return::FunctionReturn, function_throws::FunctionThrows, struct_member::StructMember};
24
25
26#[derive(Parser)]
27#[grammar = "slice/ice.pest"]
28pub struct IceParser;
29
30pub trait ParsedObject {
31    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized;
32}
33
34pub trait ParsedModule {
35    fn parse(&mut self, rule: &mut Pairs<Rule>) -> Result<(), Box<dyn std::error::Error>> where Self: Sized;
36}
37
38
39impl ParsedModule for Module {
40    fn parse(&mut self, rule: &mut Pairs<Rule>) -> Result<(), Box<dyn std::error::Error>> where Self: Sized {
41        let it = rule.next().ok_or(
42            Box::new(ParsingError::new("No more items"))
43        )?;
44        if it.as_rule() != Rule::keyword_module {
45            return Err(Box::new(ParsingError::new(
46                &format!("Expected keyword module but found {:?}", it.as_rule())
47            )));
48        }
49        let it = rule.next().ok_or(
50            Box::new(ParsingError::new("No more items"))
51        )?;
52        if it.as_rule() != Rule::identifier {
53            return Err(Box::new(ParsingError::new(
54                &format!("Expected identifier but found {:?}", it.as_rule())
55            )));
56        }
57        let name = it.as_str();
58        let module = match self.sub_modules.iter_mut().find(|f| f.name == name) {
59            Some(module) => {
60                module
61            }
62            None => {
63                let mut new_module = Module::new(Rc::clone(&self.type_map));
64                new_module.name = String::from(name);
65                new_module.full_name = format!("{}::{}", self.full_name, new_module.name);
66                self.sub_modules.push(new_module);
67                self.sub_modules.last_mut().ok_or(
68                    Box::new(ParsingError::new("Unexpected. No module found."))
69                )?
70            }
71        };
72
73        for child in rule {
74            match child.as_rule() {
75                Rule::block_open => {},
76                Rule::any_block => {
77                    for block in child.into_inner() {
78                        match block.as_rule() {
79                            Rule::module_block => {
80                                module.parse(&mut block.into_inner())?;
81                            },
82                            Rule::enum_block => {
83                                let enumeration = Enum::parse(block.into_inner())?;
84                                self.type_map.borrow_mut().insert(enumeration.id.to_string(), module.snake_name());
85                                module.add_enum(enumeration);
86                            },
87                            Rule::struct_block => {
88                                let structure = Struct::parse(block.into_inner())?;
89                                self.type_map.borrow_mut().insert(structure.id.to_string(), module.snake_name());
90                                module.add_struct(structure);
91                            },
92                            Rule::class_block => {
93                                let class = Class::parse(block.into_inner())?;
94                                self.type_map.borrow_mut().insert(class.id.to_string(), module.snake_name());
95                                module.add_class(class);
96                            },
97                            Rule::interface_block => {
98                                let interface = Interface::parse(block.into_inner())?;
99                                module.add_interface(interface);
100                            },
101                            Rule::exception_block => {
102                                let exception = Exception::parse(block.into_inner())?;
103                                self.type_map.borrow_mut().insert(exception.id.to_string(), module.snake_name());
104                                module.add_exception(exception);
105                            }
106                            _ => return Err(Box::new(ParsingError::new(
107                                &format!("Unexpected rule {:?}", block.as_rule())
108                            )))
109                        }
110                    }
111                },
112                Rule::typedef => {
113                    let mut vartype = IceType::VoidType;
114                    let mut id = "";
115                    for item in child.into_inner() {
116                        match item.as_rule() {
117                            Rule::typename => { vartype = IceType::from(&escape::escape(item.as_str()))? },
118                            Rule::identifier => { id = item.as_str(); },
119                            Rule::typedef_end => {
120                                self.type_map.borrow_mut().insert(String::from(id), module.snake_name());
121                                module.add_typedef(id, vartype.clone());
122                            },
123                            _ => return Err(Box::new(ParsingError::new(
124                                &format!("Unexpected rule {:?}", item.as_rule())
125                            )))
126                        }
127                    }
128                }
129                Rule::block_close => {},
130                _ => return Err(Box::new(ParsingError::new(
131                    &format!("Unexpected rule {:?}", child.as_rule())
132                )))
133            };
134        }
135        Ok(())
136    }
137}
138
139impl ParsedObject for Enum {
140    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
141        let mut enumeration = Enum::empty();
142        for child in rule {
143            match child.as_rule() {
144                Rule::keyword_enum => {},
145                Rule::identifier => { 
146                    enumeration.ice_id = String::from(child.as_str());
147                    let id_str = format_ident!("{}", classcase::to_class_case(&enumeration.ice_id));
148                    enumeration.id = quote! { #id_str };
149                },
150                Rule::block_open => {},
151                Rule::enum_lines => {
152                    for line in child.into_inner() {
153                        match line.as_rule() {
154                            // TODO: maybe add struct for each enum line
155                            Rule::enum_line => {
156                                let mut id = "";
157                                let mut value: Option<i32> = None;
158                                for item in line.into_inner() {
159                                    match item.as_rule() {
160                                        Rule::identifier => {
161                                            id = item.as_str();
162                                        },
163                                        Rule::numeric_value => {
164                                            value = Some(item.as_str().parse()?);
165                                        },
166                                        _ => return Err(Box::new(ParsingError::new(
167                                            &format!("Unexpected rule {:?}", item.as_rule())
168                                        )))
169                                    };
170                                }
171                                enumeration.add_variant(id, value);
172                            },
173                            _ => return Err(Box::new(ParsingError::new(
174                                &format!("Unexpected rule {:?}", line.as_rule())
175                            )))
176                        }
177                    }
178                },
179                Rule::block_close => {},
180                _ => return Err(Box::new(ParsingError::new(
181                    &format!("Unexpected rule {:?}", child.as_rule())
182                )))
183            }
184        }
185
186        Ok(enumeration)
187    }
188}
189
190impl ParsedObject for StructMember {
191    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
192        let mut member = StructMember::empty();
193        let mut optional = false;
194        let mut optional_tag = 0;
195        for child in rule {
196            match child.as_rule() {
197                Rule::keyword_optional => {
198                    optional = true;
199                    for line in child.into_inner() {
200                        match line.as_rule() {
201                            Rule::optional_tag => {
202                                optional_tag = line.as_str().parse()?;
203                            }
204                            _ => return Err(Box::new(ParsingError::new(
205                                &format!("Unexpected rule {:?}", line.as_rule())
206                            )))
207                        }
208                    }
209                },
210                Rule::typename => {
211                    if optional {
212                        member.r#type = IceType::Optional(Box::new(IceType::from(child.as_str())?), optional_tag);
213                    } else {
214                        member.r#type = IceType::from(child.as_str())?;
215                    }
216                },
217                Rule::identifier => {
218                    member.ice_id = String::from(child.as_str());
219                    let id_str = format_ident!("{}", escape::escape(&snakecase::to_snake_case(&member.ice_id)));
220                    member.id = quote! { #id_str };
221                },
222                Rule::struct_line_default | Rule::class_line_default => {
223                    // TODO
224                }
225                Rule::struct_line_end => {
226                },
227                Rule::class_line_end => {
228                },
229                _ => return Err(Box::new(ParsingError::new(
230                    &format!("Unexpected rule {:?}", child.as_rule())
231                )))
232            }
233        }
234        Ok(member)
235    }
236}
237
238impl ParsedObject for Struct {
239    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
240        let mut structure = Struct::empty();
241        for child in rule {
242            match child.as_rule() {
243                Rule::keyword_struct => {},
244                Rule::identifier => { 
245                    structure.ice_id = String::from(child.as_str());
246                    let id_str = format_ident!("{}", classcase::to_class_case(&structure.ice_id));
247                    structure.id = quote! { #id_str };
248                },
249                Rule::block_open => {},
250
251                Rule::struct_line => {
252                    let member = StructMember::parse(child.into_inner())?;
253                    structure.add_member(member);
254                },
255                Rule::block_close => {},
256                _ => return Err(Box::new(ParsingError::new(
257                    &format!("Unexpected rule {:?}", child.as_rule())
258                )))
259            }
260        }
261
262        Ok(structure)
263    }
264}
265
266impl ParsedObject for Class {
267    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
268        let mut class = Class::empty();
269        for child in rule {
270            match child.as_rule() {
271                Rule::keyword_class => {},
272                Rule::identifier => { 
273                    class.ice_id = String::from(child.as_str());
274                    let id_str = format_ident!("{}", classcase::to_class_case(&class.ice_id));
275                    class.id = quote! { #id_str };
276                },
277                Rule::extends => {
278                    for line in child.into_inner() {
279                        match line.as_rule() {
280                            Rule::keyword_extends => { },
281                            Rule::identifier => {
282                                class.extends = Some(IceType::from(line.as_str())?);
283                            },
284                            _ => return Err(Box::new(ParsingError::new(
285                                &format!("Unexpected rule {:?}", line.as_rule())
286                            )))
287                        }
288                    }
289                }
290                Rule::block_open => {},
291                Rule::class_line => {
292                    let member = StructMember::parse(child.into_inner())?;
293                    class.add_member(member);
294                },
295                Rule::block_close => {},
296                _ => return Err(Box::new(ParsingError::new(
297                    &format!("Unexpected rule {:?}", child.as_rule())
298                )))
299            }
300        }
301
302        Ok(class)
303    }
304}
305
306impl ParsedObject for Interface {
307    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
308        let mut interface = Interface::empty();
309        for child in rule {
310            match child.as_rule() {
311                Rule::keyword_interface => {},
312                Rule::identifier => { 
313                    interface.ice_id = String::from(child.as_str());
314                    let id_str = format_ident!("{}", classcase::to_class_case(&interface.ice_id));
315                    interface.id = quote! { #id_str };
316                },
317                Rule::block_open => {},
318                Rule::function => {
319                    interface.add_function(Function::parse(child.into_inner())?);
320                },
321                Rule::block_close => {},
322                _ => return Err(Box::new(ParsingError::new(
323                    &format!("Unexpected rule {:?}", child.as_rule())
324                )))
325            }
326        }
327        Ok(interface)
328    }
329}
330
331impl ParsedObject for Function {
332    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
333        let mut function = Function::empty();
334        for child in rule {
335            match child.as_rule() {
336                Rule::keyword_idempotent => {
337                    function.set_idempotent();
338                }
339                Rule::fn_return_proxy => {
340                    function.return_type.set_proxy();
341                }
342                Rule::fn_return => {
343                    function.return_type = FunctionReturn::parse(child.into_inner())?;
344                },
345                Rule::fn_name => { 
346                    function.ice_id = String::from(child.as_str());
347                    let id_str = format_ident!("{}", snakecase::to_snake_case(&function.ice_id));
348                    function.id = quote! { #id_str };
349                    
350                },
351                Rule::fn_arg_open => {},
352                Rule::fn_arg_list => {
353                    for arg in child.into_inner() {
354                        match arg.as_rule() {
355                            Rule::fn_arg | Rule::fn_arg_out => {
356                                let arg = FunctionArgument::parse(arg.into_inner())?;
357                                function.add_argument(arg);
358                            }
359                            _ => return Err(Box::new(ParsingError::new(
360                                &format!("Unexpected rule {:?}", arg.as_rule())
361                            )))
362                        }
363                    }
364                },
365                Rule::fn_arg_close => {},
366                Rule::fn_throws => {
367                    function.throws = FunctionThrows::parse(child.into_inner())?;
368                }
369                _ => return Err(Box::new(ParsingError::new(
370                    &format!("Unexpected rule {:?}", child.as_rule())
371                )))
372            }
373        }
374        Ok(function)
375    }
376}
377
378impl ParsedObject for FunctionThrows {
379    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
380        for child in rule {
381            match child.as_rule() {
382                Rule::keyword_throws => {}
383                Rule::identifier => {
384                    return Ok(FunctionThrows::new(IceType::from(child.as_str())?));
385                }
386                _ => { }
387            }
388        }
389        return Err(Box::new(ParsingError::new(
390            &format!("Did not find throw identifier")
391        )))
392    }
393}
394
395impl ParsedObject for FunctionReturn {
396    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
397        let mut return_type = IceType::VoidType;
398        let mut optional = false;
399        let mut optional_tag = 0;
400        for child in rule {
401            match child.as_rule() {
402                Rule::keyword_optional => {
403                    optional = true;
404                    let tag = child.into_inner().next().ok_or(Box::new(ParsingError::new("No more items")))?;
405
406                    if tag.as_rule() != Rule::optional_tag {
407                        return Err(Box::new(ParsingError::new(
408                            &format!("Expected keyword optional_tag but found {:?}", tag.as_rule())
409                        )));
410                    }
411                    optional_tag = tag.as_str().parse()?;
412                }
413                Rule::identifier => {
414                    if optional {
415                        return_type = IceType::Optional(Box::new(IceType::from(child.as_str())?), optional_tag);
416                    } else {
417                        return_type = IceType::from(child.as_str())?;
418                    }
419                }
420                _ => return Err(Box::new(ParsingError::new(
421                    &format!("Unexpected rule {:?}", child.as_rule())
422                )))
423            }
424        }
425        Ok(FunctionReturn::new(return_type))
426    }
427}
428
429impl ParsedObject for FunctionArgument {
430    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
431        let mut id = TokenStream::new();
432        let mut optional = false;
433        let mut optional_tag = 0;
434        let mut typename = IceType::VoidType;
435        let mut out = false;
436
437        for child in rule {
438            match child.as_rule() {
439                Rule::typename => {
440                    if optional {
441                        typename = IceType::Optional(Box::new(IceType::from(child.as_str())?), optional_tag);
442                    } else {
443                        typename = IceType::from(child.as_str())?;
444                    }
445                },
446                Rule::identifier => {
447                    let id_str = format_ident!("{}", escape(&snakecase::to_snake_case(child.as_str())));
448                    id = quote! { #id_str }
449                },
450                Rule::keyword_out => out = true,
451                Rule::keyword_optional => {
452                    optional = true;
453                    let tag = child.into_inner().next().ok_or(Box::new(ParsingError::new("No more items")))?;
454
455                    if tag.as_rule() != Rule::optional_tag {
456                        return Err(Box::new(ParsingError::new(
457                            &format!("Expected keyword optional_tag but found {:?}", tag.as_rule())
458                        )));
459                    }
460                    optional_tag = tag.as_str().parse()?;
461                }
462                _ => return Err(Box::new(ParsingError::new(
463                    &format!("Unexpected rule {:?}", child.as_rule())
464                )))
465            }
466        }
467        Ok(FunctionArgument::new(id, typename, out))
468    }
469}
470
471impl ParsedObject for Exception {
472    fn parse(rule: Pairs<Rule>) -> Result<Self, Box<dyn std::error::Error>> where Self: Sized {
473        let mut exception = Exception::empty();
474        for child in rule {
475            match child.as_rule() {
476                Rule::keyword_exception => {},
477                Rule::identifier => { 
478                    exception.ice_id = String::from(child.as_str());
479                    let id_str = format_ident!("{}", pascalcase::to_pascal_case(&exception.ice_id));
480                    exception.id = quote! { #id_str };
481                },
482                Rule::block_open => {},
483                Rule::extends => {
484                    for line in child.into_inner() {
485                        match line.as_rule() {
486                            Rule::keyword_extends => { },
487                            Rule::identifier => {
488                                exception.extends = Some(IceType::from(line.as_str())?);
489                            },
490                            _ => return Err(Box::new(ParsingError::new(
491                                &format!("Unexpected rule {:?}", line.as_rule())
492                            )))
493                        }
494                    }
495                }
496                Rule::struct_line => {
497                    let member = StructMember::parse(child.into_inner())?;
498                    exception.add_member(member);
499                },
500                Rule::block_close => {},
501                _ => return Err(Box::new(ParsingError::new(
502                    &format!("Unexpected rule {:?}", child.as_rule())
503                )))
504            }
505        }
506
507        Ok(exception)
508    }
509}
510
511impl Module {
512    fn parse_file(&mut self, file: &mut File, include_dir: &Path, parsed_files: &mut BTreeSet<String>) -> Result<(), Box<dyn std::error::Error>> {
513        let mut content = String::new();
514        file.read_to_string(&mut content)?;
515
516        let pairs = IceParser::parse(Rule::ice, &content).unwrap();
517        for pair in pairs {
518            match pair.as_rule() {
519                Rule::ice => {
520                    for child in pair.into_inner() {
521                        match child.as_rule() {
522                            Rule::file_include => {
523                                for item in child.into_inner() {
524                                    match item.as_rule() {
525                                        Rule::keyword_include => {},
526                                        Rule::identifier => {
527                                            let include = include_dir.join(format!("{}.ice", item.as_str()));
528                                            let include_str = String::from(include_dir.join(format!("{}.ice", item.as_str())).to_str().unwrap());
529                                            println!("  parsing include {} ... ", include_str);
530                                            if parsed_files.contains(&include_str) {
531                                                println!("  skip file!");
532                                            } else {
533                                                parsed_files.insert(include_str);
534                                                let mut include_file = File::open(include)?;
535                                                self.parse_file(&mut include_file, include_dir, parsed_files)?;
536                                                println!("  finished include");
537                                            }
538                                        }
539                                        _ => return Err(Box::new(ParsingError::new(
540                                            &format!("Unexpected rule {:?}", item.as_rule())
541                                        )))
542                                    }
543                                }
544                            }
545                            Rule::module_block => {
546                                self.parse(&mut child.into_inner())?;
547                            },
548                            Rule::EOI => {
549                                return Ok(())
550                            },
551                            _ => return Err(Box::new(ParsingError::new(
552                                &format!("Unexpected rule {:?}", child.as_rule())
553                            )))
554                        }
555                    }
556                },
557                _ => return Err(Box::new(ParsingError::new(
558                    &format!("Unexpected rule {:?}", pair.as_rule())
559                )))
560            };
561        }
562
563        Err(Box::new(ParsingError::new("Unexpected error while parsing")))
564    }
565}
566
567pub fn parse_ice_files(ice_files: &Vec<String>, include_dir: &str) -> Result<Module, Box<dyn std::error::Error>> {
568    let mut parsed_files = BTreeSet::new();
569    let mut root = Module::new(Rc::new(RefCell::new(BTreeMap::new())));
570    for item in ice_files {
571        println!("parsing {} ... ", item);
572        if parsed_files.contains(item) {
573            println!("skip file!");
574        } else {
575            parsed_files.insert(item.clone());
576            let mut file = File::open(Path::new(&item))?;
577            root.parse_file(&mut file, Path::new(include_dir), &mut parsed_files)?;
578            println!("finished parsing!");
579        }
580    }
581
582    Ok(root)
583}
584
585
586#[cfg(test)]
587mod test {
588    use super::*;
589
590    #[test]
591    fn test_function() {
592        assert!(IceParser::parse(Rule::function, "void test();").is_ok());
593        assert!(IceParser::parse(Rule::function, "long test();").is_ok());
594        assert!(IceParser::parse(Rule::function, "long test(long width);").is_ok());
595        assert!(IceParser::parse(Rule::function, "long test(long width, long height);").is_ok());
596        assert!(IceParser::parse(Rule::function, "long test(long radius, out long area);").is_ok());
597        assert!(IceParser::parse(Rule::function, "long test(out long area);").is_ok());
598        assert!(IceParser::parse(Rule::function, "long test(out long area) throws exception;").is_ok());
599
600        assert!(IceParser::parse(Rule::function, "123abc test();").is_err());
601        assert!(IceParser::parse(Rule::function, "void 123abc();").is_err());
602        assert!(IceParser::parse(Rule::function, "void test(123abc width);").is_err());
603        assert!(IceParser::parse(Rule::function, "void test(long 123abc);").is_err());
604        assert!(IceParser::parse(Rule::function, "void test(long width height);").is_err());
605        assert!(IceParser::parse(Rule::function, "void test(out 123abc height);").is_err());
606        assert!(IceParser::parse(Rule::function, "void test(out long 123abc);").is_err());
607        assert!(IceParser::parse(Rule::function, "void test(out long result, long input);").is_err());
608    }
609
610    #[test]
611    fn test_module_block() {
612        assert!(IceParser::parse(Rule::ice, "#pragma once\nmodule Test { }").is_ok());
613
614        assert!(IceParser::parse(Rule::module_block, "module Test { }").is_ok());
615        assert!(IceParser::parse(Rule::module_block, "module Test { module Test2 {} }").is_ok());
616        assert!(IceParser::parse(Rule::module_block, "module Test { enum Test2 { First } }").is_ok());
617        assert!(IceParser::parse(Rule::module_block, "module Test { struct Test2 { long width; } }").is_ok());
618        assert!(IceParser::parse(Rule::module_block, "module Test { interface Test2 { void test(); } }").is_ok());
619
620        assert!(IceParser::parse(Rule::module_block, "module {}").is_err());
621        assert!(IceParser::parse(Rule::module_block, "struct Test {}").is_err());
622        assert!(IceParser::parse(Rule::module_block, "interface Test {}").is_err());
623        assert!(IceParser::parse(Rule::module_block, "enum Test {}").is_err());
624        assert!(IceParser::parse(Rule::module_block, "module 12Test {}").is_err());
625    }
626
627    #[test]
628    fn test_enum_block() {
629        assert!(IceParser::parse(Rule::enum_lines, "First = 0").is_ok());
630        assert!(IceParser::parse(Rule::enum_lines, "First = 0, Second = 1").is_ok());
631        assert!(IceParser::parse(Rule::enum_lines, "First").is_ok());
632        assert!(IceParser::parse(Rule::enum_lines, "First, Second").is_ok());
633
634        assert!(IceParser::parse(Rule::enum_block, "enum Test { First = 0 }").is_ok());
635        assert!(IceParser::parse(Rule::enum_block, "enum Test { First }").is_ok());
636        assert!(IceParser::parse(Rule::enum_block, "enum Test { First = 0, Second = 1 }").is_ok());
637        assert!(IceParser::parse(Rule::enum_block, "enum Test { First, Second }").is_ok());
638
639        assert!(IceParser::parse(Rule::enum_block, "struct Test {}").is_err());
640        assert!(IceParser::parse(Rule::enum_block, "interface Test {}").is_err());
641        assert!(IceParser::parse(Rule::enum_block, "module Test {}").is_err());
642        assert!(IceParser::parse(Rule::enum_block, "enum 12Test {}").is_err());
643        assert!(IceParser::parse(Rule::enum_block, "enum Test { 123abc }").is_err());
644        assert!(IceParser::parse(Rule::enum_block, "enum Test { 123abc = 1 }").is_err());
645        assert!(IceParser::parse(Rule::enum_block, "enum Test { First = X }").is_err());
646    }
647
648    #[test]
649    fn test_struct_block() {
650        assert!(IceParser::parse(Rule::struct_block, "struct Test { long width; }").is_ok());
651        assert!(IceParser::parse(Rule::struct_block, "struct Test { long width; long height; }").is_ok());
652
653        assert!(IceParser::parse(Rule::struct_block, "struct Test { long width }").is_err());
654        assert!(IceParser::parse(Rule::struct_block, "struct Test { }").is_err());
655        assert!(IceParser::parse(Rule::struct_block, "enum Test {}").is_err());
656        assert!(IceParser::parse(Rule::struct_block, "inteface Test {}").is_err());
657        assert!(IceParser::parse(Rule::struct_block, "module Test {}").is_err());
658        assert!(IceParser::parse(Rule::struct_block, "struct 12Test {}").is_err());
659        assert!(IceParser::parse(Rule::struct_block, "struct Test { 12long width; }").is_err());
660        assert!(IceParser::parse(Rule::struct_block, "struct Test { long 12width; }").is_err());
661        assert!(IceParser::parse(Rule::struct_block, "struct Test { struct Test2 { } }").is_err());
662    }
663
664    #[test]
665    fn test_interface_block() {
666        assert!(IceParser::parse(Rule::interface_block, "interface Test { void test(); }").is_ok());
667        assert!(IceParser::parse(Rule::interface_block, "interface Test { void test(long width); }").is_ok());
668        assert!(IceParser::parse(Rule::interface_block, "interface Test { void test(long width, long height); }").is_ok());
669
670        assert!(IceParser::parse(Rule::interface_block, "interface Test { void 12test(); }").is_err());
671        assert!(IceParser::parse(Rule::interface_block, "interface Test { test(); }").is_err());
672        assert!(IceParser::parse(Rule::interface_block, "interface Test { void test(long 12width); }").is_err());
673        assert!(IceParser::parse(Rule::interface_block, "enum Test {}").is_err());
674        assert!(IceParser::parse(Rule::interface_block, "struct Test {}").is_err());
675        assert!(IceParser::parse(Rule::interface_block, "module Test {}").is_err());
676    }
677}