1use crate::errors::AntlrError;
2use std::rc::Rc;
3
4use crate::token::{CommonToken, Token, TokenRef};
5use std::collections::BTreeMap;
6
7#[derive(Clone, Debug, Eq, PartialEq)]
8pub enum ParseTree {
9 Rule(RuleNode),
10 Terminal(TerminalNode),
11 Error(ErrorNode),
12}
13
14impl ParseTree {
15 pub fn text(&self) -> String {
16 match self {
17 Self::Rule(rule) => rule.text(),
18 Self::Terminal(node) => node.text(),
19 Self::Error(node) => node.text(),
20 }
21 }
22
23 pub fn to_string_tree<S: AsRef<str>>(&self, rule_names: &[S]) -> String {
24 match self {
25 Self::Rule(rule) => rule.to_string_tree(rule_names),
26 Self::Terminal(node) => escape_tree_text(&node.text()),
27 Self::Error(node) => escape_tree_text(&node.text()),
28 }
29 }
30
31 pub fn first_rule(&self, rule_index: usize) -> Option<&Self> {
33 match self {
34 Self::Rule(rule) => {
35 if rule.context().rule_index() == rule_index {
36 return Some(self);
37 }
38 rule.context()
39 .children()
40 .iter()
41 .find_map(|child| child.first_rule(rule_index))
42 }
43 Self::Terminal(_) | Self::Error(_) => None,
44 }
45 }
46
47 pub fn first_rule_stop(&self, rule_index: usize) -> Option<&CommonToken> {
49 let Self::Rule(rule) = self else {
50 return None;
51 };
52 if rule.context().rule_index() == rule_index {
53 return rule.context().stop();
54 }
55 rule.context()
56 .children()
57 .iter()
58 .find_map(|child| child.first_rule_stop(rule_index))
59 }
60
61 pub fn first_rule_int_return(&self, rule_index: usize, name: &str) -> Option<i64> {
65 let Self::Rule(rule) = self else {
66 return None;
67 };
68 if rule.context().rule_index() == rule_index {
69 return rule.context().int_return(name);
70 }
71 rule.context()
72 .children()
73 .iter()
74 .find_map(|child| child.first_rule_int_return(rule_index, name))
75 }
76
77 pub fn first_error_token(&self) -> Option<&CommonToken> {
79 match self {
80 Self::Rule(rule) => rule
81 .context()
82 .children()
83 .iter()
84 .find_map(Self::first_error_token),
85 Self::Terminal(_) => None,
86 Self::Error(node) => Some(node.symbol()),
87 }
88 }
89
90 pub fn rule_invocation_stack<S: AsRef<str>>(
93 &self,
94 rule_index: usize,
95 rule_names: &[S],
96 ) -> Option<Vec<String>> {
97 let mut stack = Vec::new();
98 if self.find_rule_path(rule_index, rule_names, &mut stack) {
99 stack.reverse();
100 return Some(stack);
101 }
102 None
103 }
104
105 fn find_rule_path<S: AsRef<str>>(
106 &self,
107 rule_index: usize,
108 rule_names: &[S],
109 stack: &mut Vec<String>,
110 ) -> bool {
111 let Self::Rule(rule) = self else {
112 return false;
113 };
114 let current_index = rule.context().rule_index();
115 stack.push(
116 rule_names
117 .get(current_index)
118 .map_or("<unknown>", |name| name.as_ref())
119 .to_owned(),
120 );
121 if current_index == rule_index
122 || rule
123 .context()
124 .children()
125 .iter()
126 .any(|child| child.find_rule_path(rule_index, rule_names, stack))
127 {
128 return true;
129 }
130 stack.pop();
131 false
132 }
133}
134
135fn escape_tree_text(text: &str) -> String {
136 let mut escaped = String::with_capacity(text.len());
137 for ch in text.chars() {
138 match ch {
139 '\n' => escaped.push_str("\\n"),
140 '\r' => escaped.push_str("\\r"),
141 '\t' => escaped.push_str("\\t"),
142 _ => escaped.push(ch),
143 }
144 }
145 escaped
146}
147
148#[derive(Clone, Debug, Eq, PartialEq)]
149pub struct RuleNode {
150 context: ParserRuleContext,
151}
152
153impl RuleNode {
154 pub const fn new(context: ParserRuleContext) -> Self {
155 Self { context }
156 }
157
158 pub const fn context(&self) -> &ParserRuleContext {
159 &self.context
160 }
161
162 pub const fn context_mut(&mut self) -> &mut ParserRuleContext {
163 &mut self.context
164 }
165
166 pub fn text(&self) -> String {
167 self.context.text()
168 }
169
170 pub fn to_string_tree<S: AsRef<str>>(&self, rule_names: &[S]) -> String {
171 self.context.to_string_tree(rule_names)
172 }
173}
174
175#[derive(Clone, Debug, Eq, PartialEq)]
176pub struct ParserRuleContext {
177 rule_index: usize,
178 invoking_state: isize,
179 alt_number: usize,
180 start: Option<TokenRef>,
181 stop: Option<TokenRef>,
182 int_returns: Option<Box<IntReturns>>,
183 children: Vec<ParseTree>,
184 matched_child: bool,
190 exception: Option<Box<AntlrError>>,
194}
195
196#[derive(Clone, Debug, Default, Eq, PartialEq)]
197struct IntReturns(BTreeMap<String, i64>);
198
199impl ParserRuleContext {
200 pub const fn new(rule_index: usize, invoking_state: isize) -> Self {
201 Self {
202 rule_index,
203 invoking_state,
204 alt_number: 0,
205 start: None,
206 stop: None,
207 int_returns: None,
208 children: Vec::new(),
209 matched_child: false,
210 exception: None,
211 }
212 }
213
214 pub(crate) fn with_child_capacity(
215 rule_index: usize,
216 invoking_state: isize,
217 capacity: usize,
218 ) -> Self {
219 Self {
220 rule_index,
221 invoking_state,
222 alt_number: 0,
223 start: None,
224 stop: None,
225 int_returns: None,
226 children: Vec::with_capacity(capacity),
227 matched_child: false,
228 exception: None,
229 }
230 }
231
232 pub const fn rule_index(&self) -> usize {
233 self.rule_index
234 }
235
236 pub const fn invoking_state(&self) -> isize {
237 self.invoking_state
238 }
239
240 pub const fn alt_number(&self) -> usize {
241 self.alt_number
242 }
243
244 pub const fn set_alt_number(&mut self, alt_number: usize) {
245 self.alt_number = alt_number;
246 }
247
248 pub fn start(&self) -> Option<&CommonToken> {
249 self.start.as_deref()
250 }
251
252 pub(crate) fn start_ref(&self) -> Option<TokenRef> {
253 self.start.as_ref().map(Rc::clone)
254 }
255
256 pub fn stop(&self) -> Option<&CommonToken> {
257 self.stop.as_deref()
258 }
259
260 pub fn set_start(&mut self, token: CommonToken) {
261 self.start = Some(Rc::new(token));
262 }
263
264 pub(crate) fn set_start_ref(&mut self, token: TokenRef) {
265 self.start = Some(token);
266 }
267
268 pub fn set_stop(&mut self, token: CommonToken) {
269 self.stop = Some(Rc::new(token));
270 }
271
272 pub(crate) fn set_stop_ref(&mut self, token: TokenRef) {
273 self.stop = Some(token);
274 }
275
276 pub fn set_int_return(&mut self, name: impl Into<String>, value: i64) {
278 self.int_returns
279 .get_or_insert_with(Box::default)
280 .0
281 .insert(name.into(), value);
282 }
283
284 pub fn int_return(&self, name: &str) -> Option<i64> {
286 self.int_returns
287 .as_ref()
288 .and_then(|values| values.0.get(name).copied())
289 }
290
291 pub fn exception(&self) -> Option<&AntlrError> {
292 self.exception.as_deref()
293 }
294
295 pub fn set_exception(&mut self, error: AntlrError) {
296 self.exception = Some(Box::new(error));
297 }
298
299 pub fn children(&self) -> &[ParseTree] {
300 &self.children
301 }
302
303 pub const fn child_count(&self) -> usize {
305 self.children.len()
306 }
307
308 pub fn child_rule(&self, rule_index: usize) -> Option<&Self> {
310 self.child_rules(rule_index).next()
311 }
312
313 pub fn child_rules(&self, rule_index: usize) -> impl Iterator<Item = &Self> + '_ {
315 self.children.iter().filter_map(move |child| match child {
316 ParseTree::Rule(rule) if rule.context().rule_index() == rule_index => {
317 Some(rule.context())
318 }
319 _ => None,
320 })
321 }
322
323 pub fn child_token(&self, token_type: i32) -> Option<&TerminalNode> {
328 self.children.iter().find_map(|child| match child {
329 ParseTree::Terminal(node) if node.symbol().token_type() == token_type => Some(node),
330 ParseTree::Error(node) if node.symbol().token_type() == token_type => {
331 Some(node.terminal())
332 }
333 _ => None,
334 })
335 }
336
337 pub fn has_token(&self, token_type: i32) -> bool {
339 self.child_token(token_type).is_some()
340 }
341
342 pub fn add_child(&mut self, child: ParseTree) {
343 self.matched_child = true;
344 self.children.push(child);
345 }
346
347 pub const fn note_matched_child(&mut self) {
351 self.matched_child = true;
352 }
353
354 pub const fn has_matched_child(&self) -> bool {
357 self.matched_child
358 }
359
360 pub fn text(&self) -> String {
361 self.children.iter().map(ParseTree::text).collect()
362 }
363
364 pub fn to_string_tree<S: AsRef<str>>(&self, rule_names: &[S]) -> String {
365 let name = rule_names
366 .get(self.rule_index)
367 .map_or("<unknown>", |name| name.as_ref());
368 let display_name = if self.alt_number == 0 {
369 name.to_owned()
370 } else {
371 format!("{name}:{}", self.alt_number)
372 };
373 if self.children.is_empty() {
374 return display_name;
375 }
376 let children = self
377 .children
378 .iter()
379 .map(|child| child.to_string_tree(rule_names))
380 .collect::<Vec<_>>()
381 .join(" ");
382 format!("({display_name} {children})")
383 }
384}
385
386#[derive(Clone, Debug, Eq, PartialEq)]
387pub struct TerminalNode {
388 token: TokenRef,
389}
390
391impl TerminalNode {
392 pub fn new(token: CommonToken) -> Self {
393 Self {
394 token: Rc::new(token),
395 }
396 }
397
398 pub(crate) const fn from_ref(token: TokenRef) -> Self {
399 Self { token }
400 }
401
402 pub fn symbol(&self) -> &CommonToken {
403 self.token.as_ref()
404 }
405
406 pub fn text(&self) -> String {
407 self.token.text().unwrap_or("").to_owned()
408 }
409}
410
411#[derive(Clone, Debug, Eq, PartialEq)]
412pub struct ErrorNode {
413 terminal: TerminalNode,
414}
415
416impl ErrorNode {
417 pub fn new(token: CommonToken) -> Self {
418 Self {
419 terminal: TerminalNode::new(token),
420 }
421 }
422
423 pub(crate) const fn from_ref(token: TokenRef) -> Self {
424 Self {
425 terminal: TerminalNode::from_ref(token),
426 }
427 }
428
429 const fn terminal(&self) -> &TerminalNode {
430 &self.terminal
431 }
432
433 pub fn symbol(&self) -> &CommonToken {
434 self.terminal.symbol()
435 }
436
437 pub fn text(&self) -> String {
438 self.terminal.text()
439 }
440}
441
442pub trait ParseTreeListener {
443 fn enter_every_rule(&mut self, _ctx: &ParserRuleContext) -> Result<(), AntlrError> {
444 Ok(())
445 }
446
447 fn exit_every_rule(&mut self, _ctx: &ParserRuleContext) -> Result<(), AntlrError> {
448 Ok(())
449 }
450
451 fn visit_terminal(&mut self, _node: &TerminalNode) -> Result<(), AntlrError> {
452 Ok(())
453 }
454
455 fn visit_error_node(&mut self, _node: &ErrorNode) -> Result<(), AntlrError> {
456 Ok(())
457 }
458}
459
460#[derive(Debug, Default)]
461pub struct ParseTreeWalker;
462
463impl ParseTreeWalker {
464 pub fn walk<L: ParseTreeListener>(
467 listener: &mut L,
468 tree: &ParseTree,
469 ) -> Result<(), AntlrError> {
470 match tree {
471 ParseTree::Rule(rule) => {
472 listener.enter_every_rule(rule.context())?;
473 for child in rule.context().children() {
474 Self::walk(listener, child)?;
475 }
476 listener.exit_every_rule(rule.context())
477 }
478 ParseTree::Terminal(node) => listener.visit_terminal(node),
479 ParseTree::Error(node) => listener.visit_error_node(node),
480 }
481 }
482}
483
484#[cfg(test)]
485mod tests {
486 use super::*;
487 use crate::token::CommonToken;
488
489 #[test]
490 fn renders_rule_tree() {
491 let mut ctx = ParserRuleContext::new(0, -1);
492 ctx.add_child(ParseTree::Terminal(TerminalNode::new(
493 CommonToken::new(1).with_text("x"),
494 )));
495 let tree = ParseTree::Rule(RuleNode::new(ctx));
496 assert_eq!(tree.to_string_tree(&["expr"]), "(expr x)");
497 }
498
499 #[test]
500 fn finds_first_rule_depth_first() {
501 let mut nested = ParserRuleContext::new(1, -1);
502 nested.add_child(ParseTree::Terminal(TerminalNode::new(
503 CommonToken::new(1).with_text("x"),
504 )));
505
506 let mut root = ParserRuleContext::new(0, -1);
507 root.add_child(ParseTree::Rule(RuleNode::new(nested)));
508 let tree = ParseTree::Rule(RuleNode::new(root));
509
510 let rule = tree.first_rule(1).expect("nested rule should be found");
511 assert_eq!(
512 rule.to_string_tree(&["root".to_owned(), "child".to_owned()]),
513 "(child x)"
514 );
515 assert!(tree.first_rule(2).is_none());
516 }
517
518 #[test]
519 fn reports_rule_invocation_stack_from_leaf_to_root() {
520 let mut nested = ParserRuleContext::new(1, -1);
521 nested.add_child(ParseTree::Terminal(TerminalNode::new(
522 CommonToken::new(1).with_text("x"),
523 )));
524
525 let mut root = ParserRuleContext::new(0, -1);
526 root.add_child(ParseTree::Rule(RuleNode::new(nested)));
527 let tree = ParseTree::Rule(RuleNode::new(root));
528
529 assert_eq!(
530 tree.rule_invocation_stack(1, &["s", "a"]),
531 Some(vec!["a".to_owned(), "s".to_owned()])
532 );
533 }
534
535 #[test]
536 fn finds_direct_child_rules_by_index() {
537 let mut direct = ParserRuleContext::new(1, -1);
538 direct.add_child(ParseTree::Terminal(TerminalNode::new(
539 CommonToken::new(10).with_text("direct"),
540 )));
541
542 let mut nested_match = ParserRuleContext::new(1, -1);
543 nested_match.add_child(ParseTree::Terminal(TerminalNode::new(
544 CommonToken::new(11).with_text("nested"),
545 )));
546 let mut wrapper = ParserRuleContext::new(2, -1);
547 wrapper.add_child(ParseTree::Rule(RuleNode::new(nested_match)));
548
549 let mut root = ParserRuleContext::new(0, -1);
550 root.add_child(ParseTree::Terminal(TerminalNode::new(
551 CommonToken::new(12).with_text("prefix"),
552 )));
553 root.add_child(ParseTree::Rule(RuleNode::new(direct)));
554 root.add_child(ParseTree::Rule(RuleNode::new(wrapper)));
555
556 assert_eq!(root.child_count(), 3);
557 assert_eq!(root.child_rules(1).count(), 1);
558 assert_eq!(
559 root.child_rule(1).map(ParserRuleContext::text),
560 Some("direct".to_owned())
561 );
562 assert_eq!(
563 root.child_rule(2).map(ParserRuleContext::rule_index),
564 Some(2)
565 );
566 assert!(root.child_rule(3).is_none());
567 }
568
569 #[test]
570 fn finds_direct_terminal_children_by_token_type() {
571 let mut nested = ParserRuleContext::new(1, -1);
572 nested.add_child(ParseTree::Terminal(TerminalNode::new(
573 CommonToken::new(13).with_text("nested"),
574 )));
575
576 let mut root = ParserRuleContext::new(0, -1);
577 root.add_child(ParseTree::Error(ErrorNode::new(
578 CommonToken::new(12).with_text("error"),
579 )));
580 root.add_child(ParseTree::Terminal(TerminalNode::new(
581 CommonToken::new(10).with_text("direct"),
582 )));
583 root.add_child(ParseTree::Terminal(TerminalNode::new(
584 CommonToken::new(11).with_text("other"),
585 )));
586 root.add_child(ParseTree::Rule(RuleNode::new(nested)));
587
588 assert_eq!(root.child_count(), 4);
589 assert!(root.has_token(10));
590 assert!(root.has_token(12));
591 assert_eq!(
592 root.child_token(10).map(TerminalNode::text),
593 Some("direct".to_owned())
594 );
595 assert_eq!(
596 root.child_token(11).map(TerminalNode::text),
597 Some("other".to_owned())
598 );
599 assert_eq!(
600 root.child_token(12).map(TerminalNode::text),
601 Some("error".to_owned())
602 );
603 assert!(root.child_token(13).is_none());
604 }
605}