1extern 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#[derive(Debug)]
25pub enum IdlError {
26 InternalError,
27 UnexpectedItem(Rule),
28 ExpectedItem(Rule),
29 ErrorMesg(String),
30 FileNotFound(String),
31}
32
33pub trait IdlLoader {
35 fn load(&self, filename: &str) -> Result<String, Error>;
36}
37
38#[derive(Debug)]
40pub struct Configuration {
41 pub definition: HashMap<String, String>,
42 pub verbose: bool,
43}
44
45impl Configuration {
47 pub fn new(defs: HashMap<String, String>, verbose: bool) -> Configuration {
48 Configuration { definition: defs, verbose: verbose }
49 }
50}
51
52impl Default for Configuration {
54 fn default() -> Configuration {
55 Configuration { definition: HashMap::default(), verbose: false }
56 }
57}
58
59pub fn load_idl(_config: &Configuration, _path: &str) -> Result<String, Error> {
61 return Ok("".to_owned());
62}
63
64
65type Scope = Vec<String>;
67
68#[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 fn lookup_module(&mut self, scope: &Scope) -> &mut Box<IdlModule> {
88 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 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 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 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 Rule::scoped_name => {
179 let name = self.read_scoped_name(scope, pair)?;
180 Ok(Box::new(IdlTypeSpec::ScopedName(name)))
181 }
182
183 _ => {
185 let p = pair.clone().into_inner().next().unwrap();
186 self.read_type_spec(scope, &p)
187 }
188 }
189 }
190
191 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 _ => Err(IdlError::InternalError)
469 }
470 }
471
472 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 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 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 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 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 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 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 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 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 _ => {
590 for p in iter {
591 let _ = self.process::<L>(scope, loader, &p);
592 }
593 Ok(())
594 }
595 }
596 }
597
598 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 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 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 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 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 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 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 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 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 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 }
745
746
747pub 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
776fn 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
788impl Loader {
790 pub fn new(search_path: Vec<String>) -> Loader {
791 Loader { search_path: search_path }
792 }
793}
794
795impl 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
809pub 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}