prism_parser/grammar/
action_result.rs

1use crate::core::adaptive::RuleId;
2use crate::core::span::Span;
3use crate::grammar::escaped_string::EscapedString;
4use crate::grammar::serde_leak::*;
5use crate::parser::var_map::VarMap;
6use serde::{Deserialize, Serialize};
7
8#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
9pub enum ActionResult<'arn, 'grm> {
10    Value(Span),
11    Literal(EscapedString<'grm>),
12    Construct(
13        Span,
14        &'grm str,
15        #[serde(with = "leak_slice")] &'arn [ActionResult<'arn, 'grm>],
16    ),
17    Guid(usize),
18    RuleId(RuleId),
19    #[serde(skip)]
20    WithEnv(VarMap<'arn, 'grm>, &'arn ActionResult<'arn, 'grm>),
21}
22
23impl<'arn, 'grm> ActionResult<'arn, 'grm> {
24    pub fn get_value(&self, src: &'grm str) -> std::borrow::Cow<'grm, str> {
25        match self {
26            ActionResult::Value(span) => std::borrow::Cow::Borrowed(&src[*span]),
27            ActionResult::Literal(s) => s.to_cow(),
28            _ => panic!("Tried to get value of non-valued action result"),
29        }
30    }
31
32    pub fn to_string(&self, src: &str) -> String {
33        match self {
34            ActionResult::Value(span) => format!("\'{}\'", &src[*span]),
35            ActionResult::Literal(lit) => format!("\'{}\'", lit),
36            ActionResult::Construct(_, "Cons" | "Nil", _) => {
37                format!(
38                    "[{}]",
39                    self.iter_list()
40                        .map(|e| e.to_string(src))
41                        .collect::<Vec<String>>()
42                        .join(", ")
43                )
44            }
45            ActionResult::Construct(_, c, es) => format!(
46                "{}({})",
47                c,
48                es.iter()
49                    .map(|e| e.to_string(src))
50                    .collect::<Vec<String>>()
51                    .join(", ")
52            ),
53            ActionResult::Guid(r) => format!("Guid({r})"),
54            ActionResult::RuleId(rule) => format!("Rule({rule})"),
55            ActionResult::WithEnv(_, ar) => format!("Env({})", ar.to_string(src)),
56        }
57    }
58
59    pub fn iter_list(&self) -> ARListIterator<'arn, 'grm> {
60        ARListIterator(*self, None)
61    }
62
63    pub const VOID: &'static ActionResult<'static, 'static> =
64        &ActionResult::Construct(Span::invalid(), "#VOID#", &[]);
65}
66
67#[derive(Clone)]
68pub struct ARListIterator<'arn, 'grm: 'arn>(ActionResult<'arn, 'grm>, Option<usize>);
69
70impl<'arn, 'grm: 'arn> Iterator for ARListIterator<'arn, 'grm> {
71    type Item = &'arn ActionResult<'arn, 'grm>;
72
73    fn next(&mut self) -> Option<Self::Item> {
74        match self.0 {
75            ActionResult::Construct(_, "Cons", els) => {
76                assert_eq!(els.len(), 2);
77                self.0 = els[1];
78                self.1 = self.1.map(|v| v - 1);
79                Some(&els[0])
80            }
81            ActionResult::Construct(_, "Nil", els) => {
82                assert_eq!(els.len(), 0);
83                None
84            }
85            _ => panic!("Invalid list: {:?}", &self.0),
86        }
87    }
88
89    fn size_hint(&self) -> (usize, Option<usize>) {
90        let count = self.1.unwrap_or_else(|| self.clone().count());
91        (count, Some(count))
92    }
93}
94
95impl ExactSizeIterator for ARListIterator<'_, '_> {}