1use crate::errors::AntlrError;
2use crate::token::{CommonToken, Token};
3use std::collections::BTreeMap;
4
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub enum ParseTree {
7 Rule(RuleNode),
8 Terminal(TerminalNode),
9 Error(ErrorNode),
10}
11
12impl ParseTree {
13 pub fn text(&self) -> String {
14 match self {
15 Self::Rule(rule) => rule.text(),
16 Self::Terminal(node) => node.text(),
17 Self::Error(node) => node.text(),
18 }
19 }
20
21 pub fn to_string_tree(&self, rule_names: &[String]) -> String {
22 match self {
23 Self::Rule(rule) => rule.to_string_tree(rule_names),
24 Self::Terminal(node) => escape_tree_text(&node.text()),
25 Self::Error(node) => escape_tree_text(&node.text()),
26 }
27 }
28
29 pub fn first_rule(&self, rule_index: usize) -> Option<&Self> {
31 match self {
32 Self::Rule(rule) => {
33 if rule.context().rule_index() == rule_index {
34 return Some(self);
35 }
36 rule.context()
37 .children()
38 .iter()
39 .find_map(|child| child.first_rule(rule_index))
40 }
41 Self::Terminal(_) | Self::Error(_) => None,
42 }
43 }
44
45 pub fn first_rule_stop(&self, rule_index: usize) -> Option<&CommonToken> {
47 let Self::Rule(rule) = self else {
48 return None;
49 };
50 if rule.context().rule_index() == rule_index {
51 return rule.context().stop();
52 }
53 rule.context()
54 .children()
55 .iter()
56 .find_map(|child| child.first_rule_stop(rule_index))
57 }
58
59 pub fn first_rule_int_return(&self, rule_index: usize, name: &str) -> Option<i64> {
63 let Self::Rule(rule) = self else {
64 return None;
65 };
66 if rule.context().rule_index() == rule_index {
67 return rule.context().int_return(name);
68 }
69 rule.context()
70 .children()
71 .iter()
72 .find_map(|child| child.first_rule_int_return(rule_index, name))
73 }
74
75 pub fn first_error_token(&self) -> Option<&CommonToken> {
77 match self {
78 Self::Rule(rule) => rule
79 .context()
80 .children()
81 .iter()
82 .find_map(Self::first_error_token),
83 Self::Terminal(_) => None,
84 Self::Error(node) => Some(node.symbol()),
85 }
86 }
87
88 pub fn rule_invocation_stack(
91 &self,
92 rule_index: usize,
93 rule_names: &[String],
94 ) -> Option<Vec<String>> {
95 let mut stack = Vec::new();
96 if self.find_rule_path(rule_index, rule_names, &mut stack) {
97 stack.reverse();
98 return Some(stack);
99 }
100 None
101 }
102
103 fn find_rule_path(
104 &self,
105 rule_index: usize,
106 rule_names: &[String],
107 stack: &mut Vec<String>,
108 ) -> bool {
109 let Self::Rule(rule) = self else {
110 return false;
111 };
112 let current_index = rule.context().rule_index();
113 stack.push(
114 rule_names
115 .get(current_index)
116 .map_or("<unknown>", String::as_str)
117 .to_owned(),
118 );
119 if current_index == rule_index
120 || rule
121 .context()
122 .children()
123 .iter()
124 .any(|child| child.find_rule_path(rule_index, rule_names, stack))
125 {
126 return true;
127 }
128 stack.pop();
129 false
130 }
131}
132
133fn escape_tree_text(text: &str) -> String {
134 let mut escaped = String::with_capacity(text.len());
135 for ch in text.chars() {
136 match ch {
137 '\n' => escaped.push_str("\\n"),
138 '\r' => escaped.push_str("\\r"),
139 '\t' => escaped.push_str("\\t"),
140 _ => escaped.push(ch),
141 }
142 }
143 escaped
144}
145
146#[derive(Clone, Debug, Eq, PartialEq)]
147pub struct RuleNode {
148 context: ParserRuleContext,
149}
150
151impl RuleNode {
152 pub const fn new(context: ParserRuleContext) -> Self {
153 Self { context }
154 }
155
156 pub const fn context(&self) -> &ParserRuleContext {
157 &self.context
158 }
159
160 pub const fn context_mut(&mut self) -> &mut ParserRuleContext {
161 &mut self.context
162 }
163
164 pub fn text(&self) -> String {
165 self.context.text()
166 }
167
168 pub fn to_string_tree(&self, rule_names: &[String]) -> String {
169 self.context.to_string_tree(rule_names)
170 }
171}
172
173#[derive(Clone, Debug, Eq, PartialEq)]
174pub struct ParserRuleContext {
175 rule_index: usize,
176 invoking_state: isize,
177 alt_number: usize,
178 start: Option<CommonToken>,
179 stop: Option<CommonToken>,
180 int_returns: Option<Box<IntReturns>>,
181 children: Vec<ParseTree>,
182 matched_child: bool,
188 exception: Option<Box<AntlrError>>,
192}
193
194#[derive(Clone, Debug, Default, Eq, PartialEq)]
195struct IntReturns(BTreeMap<String, i64>);
196
197impl ParserRuleContext {
198 pub const fn new(rule_index: usize, invoking_state: isize) -> Self {
199 Self {
200 rule_index,
201 invoking_state,
202 alt_number: 0,
203 start: None,
204 stop: None,
205 int_returns: None,
206 children: Vec::new(),
207 matched_child: false,
208 exception: None,
209 }
210 }
211
212 pub(crate) fn with_child_capacity(
213 rule_index: usize,
214 invoking_state: isize,
215 capacity: usize,
216 ) -> Self {
217 Self {
218 rule_index,
219 invoking_state,
220 alt_number: 0,
221 start: None,
222 stop: None,
223 int_returns: None,
224 children: Vec::with_capacity(capacity),
225 matched_child: false,
226 exception: None,
227 }
228 }
229
230 pub const fn rule_index(&self) -> usize {
231 self.rule_index
232 }
233
234 pub const fn invoking_state(&self) -> isize {
235 self.invoking_state
236 }
237
238 pub const fn alt_number(&self) -> usize {
239 self.alt_number
240 }
241
242 pub const fn set_alt_number(&mut self, alt_number: usize) {
243 self.alt_number = alt_number;
244 }
245
246 pub const fn start(&self) -> Option<&CommonToken> {
247 self.start.as_ref()
248 }
249
250 pub const fn stop(&self) -> Option<&CommonToken> {
251 self.stop.as_ref()
252 }
253
254 pub fn set_start(&mut self, token: CommonToken) {
255 self.start = Some(token);
256 }
257
258 pub fn set_stop(&mut self, token: CommonToken) {
259 self.stop = Some(token);
260 }
261
262 pub fn set_int_return(&mut self, name: impl Into<String>, value: i64) {
264 self.int_returns
265 .get_or_insert_with(Box::default)
266 .0
267 .insert(name.into(), value);
268 }
269
270 pub fn int_return(&self, name: &str) -> Option<i64> {
272 self.int_returns
273 .as_ref()
274 .and_then(|values| values.0.get(name).copied())
275 }
276
277 pub fn exception(&self) -> Option<&AntlrError> {
278 self.exception.as_deref()
279 }
280
281 pub fn set_exception(&mut self, error: AntlrError) {
282 self.exception = Some(Box::new(error));
283 }
284
285 pub fn children(&self) -> &[ParseTree] {
286 &self.children
287 }
288
289 pub fn add_child(&mut self, child: ParseTree) {
290 self.matched_child = true;
291 self.children.push(child);
292 }
293
294 pub const fn note_matched_child(&mut self) {
298 self.matched_child = true;
299 }
300
301 pub const fn has_matched_child(&self) -> bool {
304 self.matched_child
305 }
306
307 pub fn text(&self) -> String {
308 self.children.iter().map(ParseTree::text).collect()
309 }
310
311 pub fn to_string_tree(&self, rule_names: &[String]) -> String {
312 let name = rule_names
313 .get(self.rule_index)
314 .map_or("<unknown>", String::as_str);
315 let display_name = if self.alt_number == 0 {
316 name.to_owned()
317 } else {
318 format!("{name}:{}", self.alt_number)
319 };
320 if self.children.is_empty() {
321 return display_name;
322 }
323 let children = self
324 .children
325 .iter()
326 .map(|child| child.to_string_tree(rule_names))
327 .collect::<Vec<_>>()
328 .join(" ");
329 format!("({display_name} {children})")
330 }
331}
332
333#[derive(Clone, Debug, Eq, PartialEq)]
334pub struct TerminalNode {
335 token: CommonToken,
336}
337
338impl TerminalNode {
339 pub const fn new(token: CommonToken) -> Self {
340 Self { token }
341 }
342
343 pub const fn symbol(&self) -> &CommonToken {
344 &self.token
345 }
346
347 pub fn text(&self) -> String {
348 self.token.text().unwrap_or("").to_owned()
349 }
350}
351
352#[derive(Clone, Debug, Eq, PartialEq)]
353pub struct ErrorNode {
354 token: CommonToken,
355}
356
357impl ErrorNode {
358 pub const fn new(token: CommonToken) -> Self {
359 Self { token }
360 }
361
362 pub const fn symbol(&self) -> &CommonToken {
363 &self.token
364 }
365
366 pub fn text(&self) -> String {
367 self.token.text().unwrap_or("").to_owned()
368 }
369}
370
371pub trait ParseTreeListener {
372 fn enter_every_rule(&mut self, _ctx: &ParserRuleContext) -> Result<(), AntlrError> {
373 Ok(())
374 }
375
376 fn exit_every_rule(&mut self, _ctx: &ParserRuleContext) -> Result<(), AntlrError> {
377 Ok(())
378 }
379
380 fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), AntlrError> {
381 Ok(())
382 }
383
384 fn visit_error_node(&mut self, _node: &ErrorNode) -> Result<(), AntlrError> {
385 Ok(())
386 }
387}
388
389#[derive(Debug, Default)]
390pub struct ParseTreeWalker;
391
392impl ParseTreeWalker {
393 pub fn walk<L: ParseTreeListener>(
396 listener: &mut L,
397 tree: &ParseTree,
398 ) -> Result<(), AntlrError> {
399 match tree {
400 ParseTree::Rule(rule) => {
401 listener.enter_every_rule(rule.context())?;
402 for child in rule.context().children() {
403 Self::walk(listener, child)?;
404 }
405 listener.exit_every_rule(rule.context())
406 }
407 ParseTree::Terminal(node) => listener.visit_terminal(node),
408 ParseTree::Error(node) => listener.visit_error_node(node),
409 }
410 }
411}
412
413#[cfg(test)]
414mod tests {
415 use super::*;
416 use crate::token::CommonToken;
417
418 #[test]
419 fn renders_rule_tree() {
420 let mut ctx = ParserRuleContext::new(0, -1);
421 ctx.add_child(ParseTree::Terminal(TerminalNode::new(
422 CommonToken::new(1).with_text("x"),
423 )));
424 let tree = ParseTree::Rule(RuleNode::new(ctx));
425 assert_eq!(tree.to_string_tree(&["expr".to_owned()]), "(expr x)");
426 }
427
428 #[test]
429 fn finds_first_rule_depth_first() {
430 let mut nested = ParserRuleContext::new(1, -1);
431 nested.add_child(ParseTree::Terminal(TerminalNode::new(
432 CommonToken::new(1).with_text("x"),
433 )));
434
435 let mut root = ParserRuleContext::new(0, -1);
436 root.add_child(ParseTree::Rule(RuleNode::new(nested)));
437 let tree = ParseTree::Rule(RuleNode::new(root));
438
439 let rule = tree.first_rule(1).expect("nested rule should be found");
440 assert_eq!(
441 rule.to_string_tree(&["root".to_owned(), "child".to_owned()]),
442 "(child x)"
443 );
444 assert!(tree.first_rule(2).is_none());
445 }
446
447 #[test]
448 fn reports_rule_invocation_stack_from_leaf_to_root() {
449 let mut nested = ParserRuleContext::new(1, -1);
450 nested.add_child(ParseTree::Terminal(TerminalNode::new(
451 CommonToken::new(1).with_text("x"),
452 )));
453
454 let mut root = ParserRuleContext::new(0, -1);
455 root.add_child(ParseTree::Rule(RuleNode::new(nested)));
456 let tree = ParseTree::Rule(RuleNode::new(root));
457
458 assert_eq!(
459 tree.rule_invocation_stack(1, &["s".to_owned(), "a".to_owned()]),
460 Some(vec!["a".to_owned(), "s".to_owned()])
461 );
462 }
463}