prism_parser/grammar/
action_result.rs1use 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<'_, '_> {}