kiki/data/
validated_file.rs

1use crate::data::*;
2
3use std::collections::HashSet;
4use std::fmt::{self, Display, Formatter};
5
6#[derive(Debug, Clone)]
7pub struct File {
8    pub start: String,
9    pub terminal_enum: TerminalEnum,
10    pub nonterminals: Vec<Nonterminal>,
11}
12
13impl File {
14    pub fn get_rules(&self) -> impl Iterator<Item = Rule> {
15        self.nonterminals
16            .iter()
17            .flat_map(|nonterminal| match nonterminal {
18                Nonterminal::Struct(s) => {
19                    vec![Rule {
20                        constructor_name: ConstructorName::Struct(&s.name.name),
21                        fieldset: &s.fieldset,
22                    }]
23                }
24                Nonterminal::Enum(e) => e
25                    .variants
26                    .iter()
27                    .map(|v| {
28                        let enum_name = &e.name.name;
29                        let variant_name = &v.name.name;
30                        Rule {
31                            constructor_name: ConstructorName::EnumVariant {
32                                enum_name,
33                                variant_name,
34                            },
35                            fieldset: &v.fieldset,
36                        }
37                    })
38                    .collect(),
39            })
40    }
41}
42
43#[derive(Debug, Clone, Copy)]
44pub struct Rule<'a> {
45    pub constructor_name: ConstructorName<'a>,
46    pub fieldset: &'a Fieldset,
47}
48
49#[derive(Debug, Clone, Copy)]
50pub enum ConstructorName<'a> {
51    Struct(&'a str),
52    EnumVariant {
53        enum_name: &'a str,
54        variant_name: &'a str,
55    },
56}
57
58impl Display for ConstructorName<'_> {
59    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
60        match self {
61            ConstructorName::Struct(name) => write!(f, "{}", name),
62            ConstructorName::EnumVariant {
63                enum_name,
64                variant_name,
65            } => write!(f, "{}::{}", enum_name, variant_name),
66        }
67    }
68}
69
70impl ConstructorName<'_> {
71    pub fn type_name(&self) -> &str {
72        match self {
73            ConstructorName::Struct(name) => name,
74            ConstructorName::EnumVariant { enum_name, .. } => enum_name,
75        }
76    }
77}
78
79impl File {
80    pub fn get_defined_identifiers(&self) -> HashSet<String> {
81        self.get_nonterminal_names()
82            .chain(self.get_terminal_enum_variant_names())
83            .chain(std::iter::once(self.terminal_enum.name.clone()))
84            .collect()
85    }
86
87    fn get_nonterminal_names(&self) -> impl Iterator<Item = String> + '_ {
88        self.nonterminals
89            .iter()
90            .map(|nonterminal| match nonterminal {
91                Nonterminal::Struct(s) => &s.name.name,
92                Nonterminal::Enum(e) => &e.name.name,
93            })
94            .cloned()
95    }
96
97    fn get_terminal_enum_variant_names(&self) -> impl Iterator<Item = String> + '_ {
98        self.terminal_enum
99            .variants
100            .iter()
101            .map(|variant| variant.dollarless_name.to_string())
102    }
103}
104
105#[derive(Debug, Clone)]
106pub struct TerminalEnum {
107    pub attributes: Vec<Attribute>,
108    pub name: String,
109    pub variants: Vec<TerminalVariant>,
110}
111
112impl TerminalEnum {
113    pub fn get_type(&self, variant_name: &DollarlessTerminalName) -> Option<&str> {
114        self.variants
115            .iter()
116            .find(|variant| variant.dollarless_name == *variant_name)
117            .map(|variant| -> &str { &variant.type_ })
118    }
119}
120
121#[derive(Debug, Clone)]
122pub struct TerminalVariant {
123    pub dollarless_name: DollarlessTerminalName,
124    pub type_: String,
125}
126
127#[derive(Debug, Clone)]
128pub enum Nonterminal {
129    Struct(Struct),
130    Enum(Enum),
131}
132
133impl Nonterminal {
134    pub fn name(&self) -> &str {
135        match self {
136            Nonterminal::Struct(s) => &s.name.name,
137            Nonterminal::Enum(e) => &e.name.name,
138        }
139    }
140}
141
142pub use crate::data::ast::{
143    Attribute, ComplexType, Enum, EnumVariant, Fieldset, NamedField, NamedFieldset, Struct,
144    TupleField, TupleFieldset, Type,
145};
146pub use crate::data::ast::{Ident, IdentOrTerminalIdent, IdentOrUnderscore, TerminalIdent, Token};