1mod basic_type;
2pub use basic_type::*;
3
4mod structure;
5pub use structure::*;
6
7mod union;
8pub use union::*;
9
10mod enumeration;
11pub use enumeration::*;
12
13mod node;
14use node::*;
15
16mod array;
17pub use array::*;
18
19mod typedef;
20pub use typedef::*;
21
22pub mod indexes;
23use indexes::*;
24
25pub trait CompoundType {
26 fn inner_types(&self) -> Vec<&ArrayType<BasicType>>;
27 fn contains_opaque(&self) -> bool;
28}
29
30use crate::Result;
31use pest::iterators::Pair;
32use pest::Parser;
33use pest_derive::Parser;
34use std::convert::TryFrom;
35
36#[derive(Parser)]
37#[grammar = "xdr.pest"]
38pub(crate) struct XDRParser;
39
40#[derive(Debug)]
41pub struct Ast {
42 constant_index: ConstantIndex,
43 generic_index: GenericIndex,
44 type_index: TypeIndex,
45}
46
47impl Ast {
50 pub fn new(xdr: &str) -> Result<Self> {
51 let mut root = XDRParser::parse(Rule::item, xdr)?;
53 let ast = walk(root.next().ok_or("unable to tokenise input")?);
55
56 let constant_index = ConstantIndex::new(&ast);
59 let generic_index = GenericIndex::new(&ast);
60 let type_index = TypeIndex::new(&ast);
61
62 Ok(Ast {
63 constant_index,
64 generic_index,
65 type_index,
66 })
67 }
68
69 pub fn constants(&self) -> &ConstantIndex {
70 &self.constant_index
71 }
72
73 pub fn generics(&self) -> &GenericIndex {
74 &self.generic_index
75 }
76
77 pub fn types(&self) -> &TypeIndex {
78 &self.type_index
79 }
80}
81
82fn walk(ast: Pair<'_, Rule>) -> Node<'_> {
88 fn collect_values(ast: Pair<'_, Rule>) -> Vec<Node<'_>> {
89 ast.into_inner().map(walk).collect()
90 }
91
92 match ast.as_rule() {
93 Rule::item => Node::Root(collect_values(ast)),
94 Rule::typedef => Node::Typedef(Typedef::new(collect_values(ast))),
95 Rule::constant => Node::Constant(collect_values(ast)),
96 Rule::ident | Rule::ident_const | Rule::ident_value => {
97 if let Ok(t) = BasicType::try_from(ast.as_str()) {
98 Node::Type(t)
99 } else {
100 Node::Ident(ast.as_str())
101 }
102 }
103 Rule::enum_type => Node::Enum(Enum::new(collect_values(ast))),
104 Rule::enum_variant => Node::EnumVariant(collect_values(ast)),
105 Rule::array => Node::Array(collect_values(ast)),
106 Rule::array_variable => Node::ArrayVariable(ast.into_inner().as_str()),
107 Rule::array_fixed => Node::ArrayFixed(ast.into_inner().as_str()),
108 Rule::struct_type => Node::Struct(Struct::new(collect_values(ast))),
109 Rule::struct_data_field => Node::StructDataField(collect_values(ast)),
110 Rule::union_data_field => Node::UnionDataField(collect_values(ast)),
111 Rule::union => Node::Union(Union::new(collect_values(ast))),
112 Rule::union_case => Node::UnionCase(collect_values(ast)),
113 Rule::union_default => Node::UnionDefault(collect_values(ast)),
114 Rule::union_void => Node::UnionVoid,
115 Rule::option => Node::Option(collect_values(ast)),
116 Rule::basic_type => {
117 Node::Type(BasicType::try_from(ast.as_str()).expect("unrecognised type"))
118 }
119 Rule::EOI => Node::EOF,
120 e => unimplemented!("unknown token type {:?}", e),
121 }
122}