rtps_idl/
lib.rs

1// Copyright (C) 2019  Frank Rehberger
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0>
5extern crate linked_hash_map;
6
7mod ast;
8
9use pest::Parser;
10use pest::iterators::{Pair, Pairs};
11use rtps_idl_grammar::{IdlParser, Rule};
12use std::collections::HashMap;
13use std::io::{Error, ErrorKind};
14use std::io::{Write, Read};
15use std::fs::File;
16
17use crate::ast::*;
18
19const MODULE_PRELUDE: &[u8] = b"#[allow(unused_imports)]
20use std::vec::Vec;
21";
22
23///
24#[derive(Debug)]
25pub enum IdlError {
26    InternalError,
27    UnexpectedItem(Rule),
28    ExpectedItem(Rule),
29    ErrorMesg(String),
30    FileNotFound(String),
31}
32
33///
34pub trait IdlLoader {
35    fn load(&self, filename: &str) -> Result<String, Error>;
36}
37
38///
39#[derive(Debug)]
40pub struct Configuration {
41    pub definition: HashMap<String, String>,
42    pub verbose: bool,
43}
44
45///
46impl Configuration {
47    pub fn new(defs: HashMap<String, String>, verbose: bool) -> Configuration {
48        Configuration { definition: defs, verbose: verbose }
49    }
50}
51
52///
53impl Default for Configuration {
54    fn default() -> Configuration {
55        Configuration { definition: HashMap::default(), verbose: false }
56    }
57}
58
59///
60pub fn load_idl(_config: &Configuration, _path: &str) -> Result<String, Error> {
61    return Ok("".to_owned());
62}
63
64
65///
66type Scope = Vec<String>;
67
68///
69#[derive(Debug, Clone)]
70struct Context<'i> {
71    config: &'i Configuration,
72    definitions: HashMap<String, String>,
73    root_module: Box<IdlModule>,
74}
75
76
77impl<'i> Context<'i> {
78    pub fn new(config: &'i Configuration) -> Context {
79        Context {
80            config: &config,
81            definitions: HashMap::default(),
82            root_module: Box::new(IdlModule::new(None, 0)),
83        }
84    }
85
86    ///
87    fn lookup_module(&mut self, scope: &Scope) -> &mut Box<IdlModule> {
88        // Starting from Root traverse the scope-path
89        let mut current_module = &mut self.root_module;
90        let level = scope.len();
91
92        for name in scope {
93            let submodule =
94                current_module.modules.entry(name.to_owned()).or_insert(
95                    Box::new(IdlModule::new(Some(name.to_owned()), level)));
96            current_module = submodule;
97        }
98
99        return current_module;
100    }
101
102    ///
103    fn add_type_dcl(&mut self, scope: &mut Scope, key: String, type_dcl: Box<IdlTypeDcl>)
104                    -> Result<(), IdlError> {
105        let current_module = self.lookup_module(scope);
106        current_module.types
107            .entry(key)
108            .or_insert(type_dcl);
109
110        Ok(())
111    }
112
113    ///
114    fn add_const_dcl(&mut self, scope: &mut Scope, key: String, const_dcl: Box<IdlConstDcl>)
115                     -> Result<(), IdlError> {
116        let current_module = self.lookup_module(scope);
117        current_module.constants
118            .entry(key)
119            .or_insert(const_dcl);
120
121        Ok(())
122    }
123
124    // type_spec = { template_type_spec | simple_type_spec }
125    pub fn read_type_spec(&mut self, scope: &mut Scope,
126                          pair: &Pair<Rule>) -> Result<Box<IdlTypeSpec>, IdlError>
127    {
128        let mut iter = pair.clone().into_inner();
129        if self.config.verbose {
130            print!("{:indent$}", "", indent = 3 * scope.len());
131            println!("{:?}", pair.as_rule());
132        }
133        match pair.as_rule() {
134            Rule::float => Ok(Box::new(IdlTypeSpec::F32Type)),
135            Rule::double => Ok(Box::new(IdlTypeSpec::F64Type)),
136            Rule::long_double => Ok(Box::new(IdlTypeSpec::F128Type)),
137            Rule::unsigned_short_int => Ok(Box::new(IdlTypeSpec::U16Type)),
138            Rule::unsigned_longlong_int => Ok(Box::new(IdlTypeSpec::U64Type)),
139            Rule::unsigned_long_int => Ok(Box::new(IdlTypeSpec::U32Type)),
140            Rule::signed_short_int => Ok(Box::new(IdlTypeSpec::I16Type)),
141            Rule::signed_longlong_int => Ok(Box::new(IdlTypeSpec::I64Type)),
142            Rule::signed_long_int => Ok(Box::new(IdlTypeSpec::I32Type)),
143            Rule::char_type => Ok(Box::new(IdlTypeSpec::CharType)),
144            Rule::wide_char_type => Ok(Box::new(IdlTypeSpec::WideCharType)),
145            Rule::boolean_type => Ok(Box::new(IdlTypeSpec::BooleanType)),
146            Rule::octet_type => Ok(Box::new(IdlTypeSpec::OctetType)),
147            Rule::string_type => match iter.next() {
148                None => Ok(Box::new(IdlTypeSpec::StringType(None))),
149                Some(ref p) => {
150                    let pos_int_const = self.read_const_expr(scope, p)?;
151                    Ok(Box::new(IdlTypeSpec::StringType(Some(pos_int_const))))
152                }
153            },
154            Rule::wide_string_type => match iter.next() {
155                None => Ok(Box::new(IdlTypeSpec::WideStringType(None))),
156                Some(ref p) => {
157                    let pos_int_const = self.read_const_expr(scope, p)?;
158                    Ok(Box::new(IdlTypeSpec::WideStringType(Some(pos_int_const))))
159                }
160            },
161            Rule::sequence_type => match (iter.next(), iter.next()) {
162                (Some(ref typ), None) => {
163                    let typ_expr = self.read_type_spec(scope,
164                                                       typ)?;
165                    Ok(Box::new(IdlTypeSpec::SequenceType(typ_expr, None)))
166                }
167                (Some(ref typ), Some(ref bound)) => {
168                    let typ_expr = self.read_type_spec(scope,
169                                                       typ)?;
170                    let bound_expr = self.read_const_expr(scope,
171                                                          bound)?;
172                    Ok(Box::new(IdlTypeSpec::SequenceType(typ_expr, Some(bound_expr))))
173                }
174                _ => panic!(),
175            },
176
177            //  scoped_name = { "::"? ~ identifier ~ ("::" ~ identifier)* }
178            Rule::scoped_name => {
179                let name = self.read_scoped_name(scope, pair)?;
180                Ok(Box::new(IdlTypeSpec::ScopedName(name)))
181            }
182
183            // go deeper
184            _ => {
185                let p = pair.clone().into_inner().next().unwrap();
186                self.read_type_spec(scope, &p)
187            }
188        }
189    }
190
191    /// declarator = { array_declarator | simple_declarator }
192     /// array_declarator = { identifier ~ fixed_array_size+ }
193     /// simple_declarator = { identifier }
194    pub fn read_struct_member_declarator(&mut self, scope: &mut Scope,
195                                         pair: &Pair<Rule>, type_spec: &Box<IdlTypeSpec>)
196                                         -> Result<Box<IdlStructMember>, IdlError>
197    {
198        let decl = pair.clone().into_inner().next().unwrap();
199
200        let mut iter = decl.clone().into_inner();
201        if self.config.verbose {
202            print!("{:indent$}", "", indent = 3 * scope.len());
203            println!("should be declarator {:?}", decl.as_rule());
204        }
205        match decl.as_rule() {
206            // simple_declarator = { identifier }
207            Rule::simple_declarator => {
208                let id = self.read_identifier(scope, &iter.next().unwrap())?;
209                let member_dcl = Box::new(IdlStructMember {
210                    id: id,
211                    type_spec: type_spec.clone(),
212                });
213
214                Ok(member_dcl)
215            }
216
217            // array_declarator = { identifier ~ fixed_array_size+ }
218            Rule::array_declarator => {
219                let id = self.read_identifier(scope, &iter.next().unwrap())?;
220                let array_sizes: Result<Vec<_>, IdlError> =
221                    iter
222                        .map(|p|
223                            // skip node Rule::fixed_array_size and read const_expr underneath
224                            self.read_const_expr(
225                                scope,
226                                &p.clone().into_inner().next().unwrap()))
227                        .collect();
228                let array_type_spec =
229                    Box::new(IdlTypeSpec::ArrayType(type_spec.clone(), array_sizes?));
230
231                let member_dcl = Box::new(IdlStructMember {
232                    id: id,
233                    type_spec: array_type_spec,
234                });
235
236                Ok(member_dcl)
237            }
238
239            _ => Err(IdlError::InternalError)
240        }
241    }
242
243
244    // member = { type_spec ~ declarators ~ ";" }
245    // declarators = { declarator ~ ("," ~ declarator )* }
246    // declarator = { array_declarator | simple_declarator }
247    fn read_struct_member(&mut self, scope: &mut Scope,
248                          pair: &Pair<Rule>) -> Result<Vec<Box<IdlStructMember>>, IdlError>
249    {
250        let mut iter = pair.clone().into_inner();
251        if self.config.verbose {
252            print!("{:indent$}", "", indent = 3 * scope.len());
253            println!("{:?}", pair.as_rule());
254        }
255        let type_spec: Box<IdlTypeSpec> = self.read_type_spec(scope, &iter.next().unwrap())?;
256
257        // skip rule 'declarators' and parse sibblings `declarator'
258        let declarators = iter.next().unwrap().clone().into_inner();
259
260        let members: Result<Vec<Box<IdlStructMember>>, IdlError> =
261            declarators.map(|declarator|
262                self.read_struct_member_declarator(scope, &declarator, &type_spec)).collect();
263
264        members
265    }
266
267
268    //
269    fn read_identifier(&mut self, scope: &mut Scope,
270                       pair: &Pair<Rule>) -> Result<String, IdlError>
271    {
272        if self.config.verbose {
273            print!("{:indent$}", "", indent = 3 * scope.len());
274            println!("{:?}", pair.as_rule());
275        }
276        match pair.as_rule() {
277            Rule::identifier | Rule::enumerator=> Ok(pair.as_str().to_owned()),
278            _ => Err(IdlError::ExpectedItem(Rule::identifier)),
279        }
280    }
281
282    /// scoped_name = { "::"? ~ identifier ~ ("::" ~ identifier)* }
283    fn read_scoped_name(&mut self, scope: &mut Scope,
284                        pair: &Pair<Rule>) -> Result<IdlScopedName, IdlError>
285    {
286        let iter = pair.clone().into_inner();
287        if self.config.verbose {
288            print!("{:indent$}", "", indent = 3 * scope.len());
289            println!(">>> {:?} '{}'", pair.as_rule(), pair.as_str());
290        }
291        // check if name starts with "::"
292        let is_absolute_name = pair.as_str().starts_with("::");
293        let scoped_name = iter
294            .map(|p| self.read_identifier(scope, &p).unwrap().to_owned())
295            .collect::<Vec<String>>();
296
297        Ok(IdlScopedName(scoped_name, is_absolute_name))
298    }
299
300    /// const_expr = { unary_expr ~ (or_expr | xor_expr | and_expr | shift_expr | add_expr | mult_expr)? }
301    fn read_const_expr(&mut self, scope: &mut Scope,
302                       pair: &Pair<Rule>) -> Result<Box<IdlValueExpr>, IdlError>
303    {
304        let mut iter = pair.clone().into_inner();
305        if self.config.verbose {
306            print!("{:indent$}", "", indent = 3 * scope.len());
307            println!("{:?} '{}'", pair.as_rule(), pair.as_str());
308        }
309        let fp_collect_init = (None, None, None, None);
310
311        let fp_collect = |(i, f, e, s), node: Pair<Rule>|
312            match node.as_rule() {
313                Rule::integral_part => (Some(node.as_str().to_owned()), f, e, s),
314                Rule::fractional_part => (i, Some(node.as_str().to_owned()), e, s),
315                Rule::exponent => (i, f, Some(node.as_str().to_owned()), s),
316                Rule::float_suffix => (i, f, e, Some(node.as_str().to_owned())),
317                _ => panic!(),
318            };
319
320        match pair.as_rule() {
321            Rule::const_expr => match (iter.next(), iter.next()) {
322                (Some(ref expr1), Some(ref expr2)) => {
323                    let e1 = self.read_const_expr(scope, &expr1)?;
324                    let e2 = self.read_const_expr(scope, &expr2)?;
325                    Ok(Box::new(IdlValueExpr::Expr(e1, e2)))
326                }
327                (Some(ref expr1), None) => self.read_const_expr(scope, &expr1),
328                _ => Err(IdlError::ExpectedItem(Rule::const_expr))
329            },
330            Rule::unary_expr => match (iter.next(), iter.next()) {
331                (Some(ref unary_op), Some(ref prim_expr)) => {
332                    // TBD
333                    let expr = self.read_const_expr(scope, prim_expr)?;
334                    match unary_op.as_str() {
335                        "-" => Ok(Box::new(IdlValueExpr::UnaryOp(UnaryOp::Neg, expr))),
336                        "+" => Ok(Box::new(IdlValueExpr::UnaryOp(UnaryOp::Pos, expr))),
337                        "~" => Ok(Box::new(IdlValueExpr::UnaryOp(UnaryOp::Inverse, expr))),
338                        _ => Err(IdlError::ExpectedItem(Rule::unary_operator))
339                    }
340                }
341                (Some(ref prim_expr), None) => {
342                    self.read_const_expr(scope, prim_expr)
343                }
344                _ => Err(IdlError::ExpectedItem(Rule::primary_expr))
345            },
346            Rule::primary_expr => match iter.next() {
347                //  scoped_name = { "::"? ~ identifier ~ ("::" ~ identifier)* }
348                Some(ref p) if p.as_rule() == Rule::scoped_name => {
349                    let name = self.read_scoped_name(scope, p)?;
350                    Ok(Box::new(IdlValueExpr::ScopedName(name)))
351                }
352                Some(ref p) if p.as_rule() == Rule::literal => self.read_const_expr(scope, p),
353                Some(ref p) if p.as_rule() == Rule::const_expr => {
354                    let expr = self.read_const_expr(scope, p)?;
355                    Ok(Box::new(IdlValueExpr::Brace(expr)))
356                }
357                _ => Err(IdlError::ExpectedItem(Rule::primary_expr))
358            },
359            Rule::and_expr => {
360                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
361                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::And, expr)))
362            }
363            Rule::or_expr => {
364                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
365                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Or, expr)))
366            }
367            Rule::xor_expr => {
368                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
369                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Xor, expr)))
370            }
371            Rule::lshift_expr => {
372                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
373                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::LShift, expr)))
374            }
375            Rule::rshift_expr => {
376                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
377                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::RShift, expr)))
378            }
379            Rule::add_expr => {
380                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
381                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Add, expr)))
382            }
383            Rule::sub_expr => {
384                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
385                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Sub, expr)))
386            }
387            Rule::mul_expr => {
388                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
389                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Mul, expr)))
390            }
391            Rule::div_expr => {
392                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
393                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Div, expr)))
394            }
395            Rule::mod_expr => {
396                let expr = self.read_const_expr(scope, &iter.next().unwrap())?;
397                Ok(Box::new(IdlValueExpr::BinaryOp(BinaryOp::Mod, expr)))
398            }
399            Rule::decimal_integer_literal =>
400                Ok(Box::new(IdlValueExpr::DecLiteral(pair.as_str().to_owned()))),
401            Rule::octal_integer_literal =>
402                Ok(Box::new(IdlValueExpr::OctLiteral(pair.as_str().to_owned()))),
403            Rule::hex_integer_literal =>
404                Ok(Box::new(IdlValueExpr::HexLiteral(pair.as_str().to_owned()))),
405            Rule::floating_pt_literal => {
406                let (i, f, e, s) = iter.fold(fp_collect_init, fp_collect);
407                Ok(Box::new(IdlValueExpr::FloatLiteral(i, f, e, s)))
408            }
409            Rule::boolean_literal => match pair.as_str() {
410                "TRUE" => Ok(Box::new(IdlValueExpr::BooleanLiteral(true))),
411                _ => Ok(Box::new(IdlValueExpr::BooleanLiteral(false))),
412            },
413            Rule::character_literal =>
414                Ok(Box::new(IdlValueExpr::CharLiteral(pair.as_str().to_owned()))),
415            Rule::wide_character_literal =>
416                Ok(Box::new(IdlValueExpr::WideCharLiteral(pair.as_str().to_owned()))),
417            Rule::string_literal =>
418                Ok(Box::new(IdlValueExpr::StringLiteral(pair.as_str().to_owned()))),
419            Rule::wide_string_literal =>
420                Ok(Box::new(IdlValueExpr::WideStringLiteral(pair.as_str().to_owned()))),
421            _ => self.read_const_expr(scope, &iter.next().unwrap()),
422        }
423    }
424
425    /// declarator = { array_declarator | simple_declarator }
426    /// array_declarator = { identifier ~ fixed_array_size+ }
427    /// simple_declarator = { identifier }
428    pub fn process_declarator(&mut self, scope: &mut Scope,
429                              pair: &Pair<Rule>, type_spec: &Box<IdlTypeSpec>) -> Result<(), IdlError>
430    {
431        let decl = pair.clone().into_inner().next().unwrap();
432        let mut iter = decl.clone().into_inner();
433        if self.config.verbose {
434            print!("{:indent$}", "", indent = 3 * scope.len());
435            println!("{:?}", decl.as_rule());
436        }
437        match decl.as_rule() {
438            // simple_declarator = { identifier }
439            Rule::simple_declarator => {
440                let id = self.read_identifier(scope, &iter.next().unwrap())?;
441
442                let type_dcl = Box::new(
443                    IdlTypeDcl(IdlTypeDclKind::TypeDcl(id.clone(), type_spec.clone())));
444                self.add_type_dcl(scope, id, type_dcl)
445            }
446
447            // array_declarator = { identifier ~ fixed_array_size+ }
448            Rule::array_declarator => {
449                let id = self.read_identifier(scope, &iter.next().unwrap())?;
450                let key = id.clone();
451
452                let array_sizes: Result<Vec<_>, IdlError> =
453                    iter
454                        .map(|p|
455                            // skip node Rule::fixed_array_size and read const_expr underneath
456                            self.read_const_expr(
457                                scope,
458                                &p.clone().into_inner().next().unwrap()))
459                        .collect();
460                let array_type_spec =
461                    Box::new(IdlTypeSpec::ArrayType(type_spec.clone(), array_sizes?));
462                let type_dcl = Box::new(
463                    IdlTypeDcl(IdlTypeDclKind::TypeDcl(id, array_type_spec)));
464                self.add_type_dcl(scope, key, type_dcl)
465            }
466
467            // traverse deeper
468            _ => Err(IdlError::InternalError)
469        }
470    }
471
472    ///
473    pub fn process<L: IdlLoader>(&mut self, scope: &mut Scope, loader: &mut IdlLoader,
474                                 pair: &Pair<Rule>) -> Result<(), IdlError>
475    {
476        let mut iter = pair.clone().into_inner();
477        if self.config.verbose {
478            print!("{:indent$}", "", indent = 3 * scope.len());
479            println!("{:?}", pair.as_rule());
480        }
481        match pair.as_rule() {
482            // module_dcl = { "module" ~ identifier ~ "{" ~ definition* ~ "}" }
483            Rule::module_dcl => {
484                let id = iter.next().unwrap().as_str();
485
486                scope.push(id.to_owned());
487
488                let _ = self.lookup_module(scope);
489
490                for p in iter {
491                    let _ = self.process::<L>(scope, loader, &p);
492                }
493
494                let _ = scope.pop();
495
496                Ok(())
497            }
498
499            // struct_def = { "struct" ~ identifier ~ (":" ~ scoped_name)? ~ "{" ~ member* ~ "}" }
500            Rule::struct_def => {
501                let id = iter.next().unwrap().as_str().to_owned();
502                let key = id.clone();
503                let m1: Result<Vec<Vec<Box<IdlStructMember>>>, _> = iter.map(|p| {
504                    // skip hte member-node and read sibbling directly
505                    self.read_struct_member(scope, &p)
506                }).collect();
507
508                let m2 = m1?;
509                let members = m2.into_iter().flatten().collect::<Vec<_>>();
510
511                let typedcl = Box::new(IdlTypeDcl(IdlTypeDclKind::StructDcl(id,
512                                                                            members)));
513                self.add_type_dcl(scope, key, typedcl)
514            }
515
516            // union_def = { "union" ~ identifier ~ "switch" ~ "(" ~ switch_type_spec ~ ")" ~ "{" ~ switch_body ~ "}" }
517            Rule::union_def => {
518                let id = self.read_identifier(scope, &iter.next().unwrap())?;
519                let key = id.to_owned();
520                let switch_type_spec = self.read_switch_type_spec(scope, &iter.next().unwrap())?;
521                let switch_body = self.read_switch_body(scope, &iter.next().unwrap())?;
522                let union_def = Box::new(
523                    IdlTypeDcl(IdlTypeDclKind::UnionDcl(
524                        id, switch_type_spec, switch_body)));
525
526                self.add_type_dcl(scope, key, union_def)
527            }
528
529            // type_declarator = { (template_type_spec | constr_type_dcl | simple_type_spec) ~ any_declarators }
530            Rule::type_declarator => {
531                let type_spec =
532                    self.read_type_spec(scope, &iter.next().unwrap())?;
533
534                let any_declarators_pair = &iter.next().unwrap();
535
536                for p in any_declarators_pair.clone().into_inner() {
537                    let _ = self.process_declarator(scope, &p, &type_spec);
538                }
539                Ok(())
540            }
541
542            // enum_dcl = { "enum" ~ identifier ~ "{" ~ enumerator ~ ("," ~ enumerator)* ~ ","? ~ "}" }
543            // enumerator = { identifier }
544            Rule::enum_dcl => {
545                let id = iter.next().unwrap().as_str().to_owned();
546                let key = id.clone();
547                let enums: Result<Vec<_>, IdlError> =
548                    iter.map(|p| self.read_identifier(scope, &p))
549                        .collect();
550
551                let typedcl = Box::new(
552                    IdlTypeDcl(IdlTypeDclKind::EnumDcl(id, enums?)));
553                self.add_type_dcl(scope, key, typedcl)
554            }
555            // const_dcl = { "const" ~ const_type ~ identifier ~ "=" ~ const_expr }
556            Rule::const_dcl => {
557                let type_spec =
558                    self.read_type_spec(scope, &iter.next().unwrap())?;
559                let id = self.read_identifier(scope, &iter.next().unwrap())?;
560                let key = id.clone();
561                let const_expr = self.read_const_expr(scope, &iter.next().unwrap())?;
562                let const_dcl = Box::new(IdlConstDcl { id: id, typedcl: type_spec, value: const_expr });
563                self.add_const_dcl(scope, key, const_dcl)
564            }
565
566            // include_directive = !{ "#" ~ "include" ~ (("<" ~ path_spec ~ ">") | ("\"" ~ path_spec ~ "\"")) }
567            Rule::include_directive => {
568                match pair.clone().into_inner().nth(0) {
569                    Some(ref p) => {
570                        let fname = p.as_str();
571                        let data = loader.load(fname)
572                            .map_err(|_| IdlError::FileNotFound(fname.to_owned()))?;
573
574                        let idl: Pairs<Rule> =
575                            IdlParser::parse(Rule::specification, &data)
576                                .map_err(|e| IdlError::ErrorMesg(e.to_string()))?;
577
578                        for p in idl {
579                            self.process::<L>(scope, loader, &p)?;
580                        }
581                    }
582                    _ => {}
583                }
584                Ok(())
585            }
586
587
588            // anything else
589            _ => {
590                for p in iter {
591                    let _ = self.process::<L>(scope, loader, &p);
592                }
593                Ok(())
594            }
595        }
596    }
597
598    /// declarator = { array_declarator | simple_declarator }
599    /// array_declarator = { identifier ~ fixed_array_size+ }
600    /// simple_declarator = { identifier }
601    pub fn read_switch_element_declarator(&mut self, scope: &mut Scope,
602                                          pair: &Pair<Rule>, type_spec: &Box<IdlTypeSpec>)
603                                          -> Result<Box<IdlSwitchElement>, IdlError>
604    {
605        let decl = pair.clone().into_inner().next().unwrap();
606
607        let mut iter = decl.clone().into_inner();
608        if self.config.verbose {
609            print!("{:indent$}", "", indent = 3 * scope.len());
610            println!("should be declarator {:?}", decl.as_rule());
611        }
612        match decl.as_rule() {
613            // simple_declarator = { identifier }
614            Rule::simple_declarator => {
615                let id = self.read_identifier(scope, &iter.next().unwrap())?;
616                let member_dcl = Box::new(IdlSwitchElement {
617                    id: id,
618                    type_spec: type_spec.clone(),
619                });
620
621                Ok(member_dcl)
622            }
623
624            // array_declarator = { identifier ~ fixed_array_size+ }
625            Rule::array_declarator => {
626                let id = self.read_identifier(scope, &iter.next().unwrap())?;
627                let array_sizes: Result<Vec<_>, IdlError> =
628                    iter
629                        .map(|p|
630                            // skip node Rule::fixed_array_size and read const_expr underneath
631                            self.read_const_expr(
632                                scope,
633                                &p.clone().into_inner().next().unwrap()))
634                        .collect();
635                let array_type_spec =
636                    Box::new(IdlTypeSpec::ArrayType(type_spec.clone(), array_sizes?));
637
638                let member_dcl = Box::new(IdlSwitchElement {
639                    id: id,
640                    type_spec: array_type_spec,
641                });
642
643                Ok(member_dcl)
644            }
645
646            _ => Err(IdlError::InternalError)
647        }
648    }
649
650    /// element_spec = { type_spec ~ declarator }
651    fn read_switch_element_spec(&mut self, scope: &mut Scope,
652                                pair: &Pair<Rule>) -> Result<Box<IdlSwitchElement>, IdlError>
653    {
654        let mut iter = pair.clone().into_inner();
655        if self.config.verbose {
656            print!("{:indent$}", "", indent = 3 * scope.len());
657            println!("{:?}", pair.as_rule());
658        }
659        let type_spec: Box<IdlTypeSpec> = self.read_type_spec(scope, &iter.next().unwrap())?;
660
661        let element_spec =
662            self.read_switch_element_declarator(scope, &iter.next().unwrap(), &type_spec);
663
664        element_spec
665    }
666
667    /// switch_type_spec = {integer_type | char_type | boolean_type | wide_char_type| octet_type| scoped_name }
668    fn read_switch_type_spec(&mut self, scope: &mut Scope,
669                             pair: &Pair<Rule>) -> Result<Box<IdlTypeSpec>, IdlError>
670    {
671        let mut iter = pair.clone().into_inner();
672        if self.config.verbose {
673            print!("{:indent$}", "", indent = 3 * scope.len());
674            println!("{:?}", pair.as_rule());
675        }
676        self.read_type_spec(scope, &iter.next().unwrap())
677    }
678
679    /// switch_body = { case+ }
680    fn read_switch_body(&mut self, scope: &mut Scope,
681                        pair: &Pair<Rule>) -> Result<Vec<IdlSwitchCase>, IdlError>
682    {
683        let iter = pair.clone().into_inner();
684        if self.config.verbose {
685            print!("{:indent$}", "", indent = 3 * scope.len());
686            println!("{:?}", pair.as_rule());
687        }
688
689        let cases: Result<Vec<_>, IdlError> =
690            iter
691                .map(|p| self.read_switch_case(scope, &p))
692                .collect();
693
694        cases
695    }
696
697    /// case_label = { "case" ~ const_expr ~ ":" | "default" ~ ":" }
698    fn read_switch_label(&mut self, scope: &mut Scope,
699                         pair: &Pair<Rule>) -> Result<IdlSwitchLabel, IdlError>
700    {
701        let mut iter = pair.clone().into_inner();
702        if self.config.verbose {
703            print!("{:indent$}", "", indent = 3 * scope.len());
704            println!("{:?}", pair.as_rule());
705        }
706
707        match iter.next() {
708            Some(p) => {
709                let expr = self.read_const_expr(scope, &p)?;
710                Ok(IdlSwitchLabel::Label(expr))
711            }
712            _ => Ok(IdlSwitchLabel::Default)
713        }
714    }
715
716    /// case = { case_label+ ~ element_spec ~ ";" }
717    fn read_switch_case(&mut self, scope: &mut Scope,
718                        pair: &Pair<Rule>) -> Result<IdlSwitchCase, IdlError>
719    {
720        if self.config.verbose {
721            print!("{:indent$}", "", indent = 3 * scope.len());
722            println!("{:?}", pair.as_rule());
723        }
724
725        let case_labels: Result<Vec<IdlSwitchLabel>, IdlError> = pair.clone().into_inner()
726            .filter(|p| p.as_rule() == Rule::case_label)
727            .map(|p| self.read_switch_label(scope, &p))
728            .collect();
729
730        // there will be only one in the list, choose the last
731        let elem_spec: Result<Box<IdlSwitchElement>, IdlError> = pair.clone().into_inner()
732            .filter(|p| p.as_rule() == Rule::element_spec)
733            .map(|p| self.read_switch_element_spec(scope, &p))
734            .last().unwrap();
735
736        Ok(IdlSwitchCase {
737            labels: case_labels?,
738            elem_spec: elem_spec?,
739        })
740    }
741
742    // enum_dcl = { "enum" ~ identifier ~ "{" ~ enumerator ~ ("," ~ enumerator)* ~ ","? ~ "}" }
743    // enumerator = { identifier }
744}
745
746
747///
748///
749pub fn generate_with_loader<W: Write, L: IdlLoader>(
750    out: &mut W,
751    loader: &mut L,
752    config: &Configuration,
753    idldecl: &str) -> Result<(), IdlError> {
754    let mut ctx = Context::new(config);
755
756    let idl: Pairs<Rule> =
757        IdlParser::parse(Rule::specification, &idldecl)
758            .map_err(|e| IdlError::ErrorMesg(e.to_string()))?;
759
760    let mut scope = Scope::new();
761
762    for p in idl {
763        let _ = ctx.process::<L>(&mut scope, loader, &p);
764    }
765
766    let _ = out.write(MODULE_PRELUDE);
767    ctx.root_module.as_mut().write(out, 0).map_err(|_| IdlError::InternalError)
768}
769
770
771#[derive(Debug, Clone, Default)]
772struct Loader {
773    search_path: Vec<String>,
774}
775
776///
777fn load_from(prefix: &std::path::Path, filename: &str) -> Result<String, Error> {
778    let fullname = prefix.join(filename);
779
780    let mut file = File::open(fullname)?;
781    let mut data = String::new();
782
783    file.read_to_string(&mut data)?;
784
785    return Ok(data);
786}
787
788///
789impl Loader {
790    pub fn new(search_path: Vec<String>) -> Loader {
791        Loader { search_path: search_path }
792    }
793}
794
795///
796impl IdlLoader for Loader {
797    fn load(&self, filename: &str) -> Result<String, Error> {
798        for prefix in &self.search_path {
799            let prefix_path = std::path::Path::new(&prefix);
800            match load_from(&prefix_path, filename) {
801                Ok(data) => return Ok(data),
802                _ => continue,
803            }
804        }
805        Err(Error::from(ErrorKind::NotFound))
806    }
807}
808
809///
810pub fn generate_with_search_path<W: Write>(out: &mut W, search_path: Vec<String>,
811                                           config: &Configuration, data: &str) -> Result<(), IdlError> {
812    let mut loader = Loader::new(search_path);
813
814    generate_with_loader(out, &mut loader, config, data)
815}