kiki/data/
validated_file.rs1use 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};