1use crate::label::DebugInfoOverride;
6
7use super::*;
8
9#[doc(hidden)]
10#[derive(Debug)]
11pub enum SeqInfo {
12 Char(char),
13 String(String),
14 Opaque(String),
15 Unknown(String),
16}
17
18impl SeqInfo {
19 fn show(&self) -> String {
20 match self {
21 Self::Char(c) => format!("'{c}'"),
22 Self::String(s) => format!("\"{s}\""),
23 Self::Opaque(s) => s.to_string(),
24 Self::Unknown(s) => s.to_string(),
25 }
26 }
27}
28
29#[doc(hidden)]
30#[derive(Debug)]
31pub enum NodeInfo {
32 Unknown(String),
33 Recursive(usize, Box<Self>),
35 RecursiveRef(usize),
36 Repeated(core::ops::Range<u64>, Box<Self>),
37 SeparatedBy(Box<Self>, Box<Self>),
38 Choice(Vec<Self>),
39 Any,
40 Just(SeqInfo),
41 OneOf(SeqInfo),
42 NoneOf(SeqInfo),
43 Then(Box<Self>, Box<Self>),
44 Padded(Box<Self>),
45 Filter(Box<Self>),
46 OrNot(Box<Self>),
47 Labelled(String, Box<Self>, Option<DebugInfoOverride>),
48 NestedIn(Box<Self>, Box<Self>),
49}
50
51impl NodeInfo {
52 fn bnf_inner(&self, depth: usize, defs: &mut Vec<String>, ctx: usize) -> String {
54 match self {
55 Self::Unknown(s) => format!("<unknown: {s}>"),
56 Self::Recursive(r, inner) => {
57 let def = inner.bnf_inner(1, defs, 0);
58 defs.push(format!("def_{r} ::= {def};"));
59 format!("def_{r}")
60 }
61 Self::Repeated(_, inner) => format!("{{ {} }}", inner.bnf_inner(depth, defs, 0)),
62 Self::SeparatedBy(inner, sep) => format!(
63 "{{ {} [{}]}}",
64 inner.bnf_inner(depth, defs, 2),
65 sep.bnf_inner(depth, defs, 0)
66 ),
67 Self::OrNot(inner) => format!("[ {} ]", inner.bnf_inner(depth, defs, 0)),
68 Self::Choice(inners) => {
69 let s = inners
70 .iter()
71 .map(|i| i.bnf_inner(depth + 1, defs, 1))
72 .collect::<Vec<_>>()
73 .join(&format!("\n{}| ", " ".repeat(depth)));
74 if ctx == 1 || ctx == 0 {
75 s
76 } else {
77 format!("({s})")
78 }
79 }
80 Self::Just(seq) => seq.show(),
81 Self::OneOf(seq) => format!("one_of({})", seq.show()),
82 Self::NoneOf(seq) => format!("none_of({})", seq.show()),
83 Self::Then(a, b) => {
84 let s = format!(
85 "{} {}",
86 a.bnf_inner(depth, defs, 2),
87 b.bnf_inner(depth, defs, 2)
88 );
89 if ctx == 1 || ctx == 0 {
90 s
91 } else {
92 format!("({s})")
93 }
94 }
95 Self::Any => "any".to_string(),
96 Self::NestedIn(a, b) => format!(
97 "({}).nested_in({})",
98 a.bnf_inner(depth, defs, 0),
99 b.bnf_inner(depth, defs, 0)
100 ),
101 Self::Padded(inner) | Self::Filter(inner) | Self::Labelled(_, inner, None) => {
102 inner.bnf_inner(depth, defs, ctx)
103 }
104 Self::Labelled(label, _, Some(_)) => label.clone(),
105 Self::RecursiveRef(r) => format!("def_{r}"),
106 }
107 }
108
109 fn railroad_inner(&self, defs: &mut Vec<Box<dyn railroad::Node>>) -> Box<dyn railroad::Node> {
110 use railroad::*;
111 match self {
112 Self::Unknown(s) => Box::new(Comment::new(s.to_string())),
113 Self::Recursive(r, inner) => {
114 let inner = inner.railroad_inner(defs);
115 defs.push(Box::new(LabeledBox::new(
116 Sequence::new(vec![
117 Box::new(SimpleStart) as Box<dyn Node>,
118 inner,
119 Box::new(SimpleEnd),
120 ]),
121 Terminal::new(format!("def_{r}")),
122 )));
123 Box::new(Terminal::new(format!("def_{r}")))
124 }
125 Self::Repeated(_, inner) => Box::new(Repeat::new(inner.railroad_inner(defs), Empty)),
126 Self::SeparatedBy(inner, sep) => Box::new(Repeat::new(
127 inner.railroad_inner(defs),
128 sep.railroad_inner(defs),
129 )),
130 Self::Choice(inners) => Box::new(Choice::new(
131 inners.iter().map(|i| i.railroad_inner(defs)).collect(),
132 )),
133 Self::Just(seq) => Box::new(Terminal::new(seq.show())),
134 Self::OneOf(seq) => Box::new(Terminal::new(format!("one_of({})", seq.show()))),
135 Self::NoneOf(seq) => Box::new(Terminal::new(format!("none_of({})", seq.show()))),
136 Self::Then(a, b) => Box::new(Sequence::new(vec![
137 a.railroad_inner(defs),
138 b.railroad_inner(defs),
139 ])),
140 Self::RecursiveRef(r) => Box::new(Terminal::new(format!("def_{r}"))),
141 Self::Padded(inner) => inner.railroad_inner(defs),
147 Self::Filter(inner) => Box::new(LabeledBox::new(
148 inner.railroad_inner(defs),
149 Comment::new("filtered".to_string()),
150 )),
151 Self::Labelled(label, inner, None) => Box::new(LabeledBox::new(
152 inner.railroad_inner(defs),
153 NonTerminal::new(label.to_string()),
154 )),
155 Self::Labelled(label, _, Some(DebugInfoOverride::Terminal)) => {
156 Box::new(Terminal::new(label.to_string()))
157 }
158 Self::Labelled(label, _, Some(DebugInfoOverride::NonTerminal)) => {
159 Box::new(NonTerminal::new(label.to_string()))
160 }
161 Self::NestedIn(inner, outer) => Box::new(LabeledBox::new(
162 Box::new(LabeledBox::new(
163 outer.railroad_inner(defs),
164 NonTerminal::new("outer".to_string()),
165 )),
166 Box::new(LabeledBox::new(
167 Sequence::new(vec![
168 Box::new(SimpleStart) as Box<dyn Node>,
169 inner.railroad_inner(defs),
170 Box::new(SimpleEnd),
171 ]),
172 NonTerminal::new("inner".to_string()),
173 )),
174 )),
175 Self::Any => Box::new(Terminal::new("any".to_string())),
176 Self::OrNot(inner) => Box::new(Optional::new(inner.railroad_inner(defs))),
177 }
178 }
179}
180
181#[doc(hidden)]
182#[derive(Default)]
183pub struct NodeScope {
184 rec_count: usize,
185 rec: Vec<(usize, usize)>,
187}
188
189impl NodeScope {
190 pub fn lookup_rec(&mut self, ptr: usize, f: impl FnOnce(&mut Self) -> NodeInfo) -> NodeInfo {
191 self.rec
192 .iter()
193 .rev()
194 .find(|(p, _)| *p == ptr)
195 .map(|(_, r)| NodeInfo::RecursiveRef(*r))
196 .unwrap_or_else(|| {
197 self.rec_count += 1;
198 self.rec.push((ptr, self.rec_count));
199 NodeInfo::Recursive(self.rec_count, Box::new(f(self)))
200 })
201 }
202}
203
204pub struct DebugInfo<'a> {
206 pub(crate) node_info: NodeInfo,
207 pub(crate) phantom: PhantomData<&'a ()>,
208}
209
210impl<'a> DebugInfo<'a> {
211 pub fn to_ebnf(&self) -> String {
215 let mut defs = Vec::new();
216 let def = self.node_info.bnf_inner(1, &mut defs, 0);
217 defs.push(def);
218 defs.join("\n\n")
219 }
220
221 pub fn to_railroad_svg(&self) -> impl core::fmt::Display + Clone {
234 use railroad::*;
235
236 let mut seq = Sequence::default();
237 let mut defs = Vec::new();
238 let def = self.node_info.railroad_inner(&mut defs);
239 defs.push(def);
240 seq.push(Rc::new(VerticalGrid::new(defs)) as Rc<dyn Node>);
241
242 let mut dia = Diagram::new(seq);
243
244 dia.add_element(
245 svg::Element::new("style")
246 .set("type", "text/css")
247 .text(DEFAULT_CSS),
248 );
249 dia
250 }
251}