macroonz_compiler/token/generation/
preserve.rs1use super::{
7 FragmentGenerationIssue, FragmentGenerationRefusal, GeneratedDelimiter, GeneratedLiteral,
8 GeneratedToken, GeneratedTree,
9};
10use crate::token::{CapturedDelimiter, CapturedFragment, CapturedPayload, CapturedTokenTree};
11
12impl CapturedFragment<'_> {
13 pub fn generated(self) -> Result<GeneratedTree, FragmentGenerationRefusal> {
22 preserved_tree(self.tokens())
23 }
24}
25
26pub(crate) fn preserved_tree(
28 tokens: &[CapturedTokenTree],
29) -> Result<GeneratedTree, FragmentGenerationRefusal> {
30 let mut source_spans = Vec::new();
31 let generated = tokens
32 .iter()
33 .map(|token| preserved_token(token, &mut source_spans))
34 .collect::<Result<Vec<_>, _>>()?;
35 GeneratedTree::preserved(generated, source_spans).map_err(|_| FragmentGenerationRefusal {
36 issue: FragmentGenerationIssue::Unbounded,
37 at: tokens.first().map(CapturedTokenTree::span),
38 })
39}
40
41impl FragmentGenerationRefusal {
42 pub const fn issue(self) -> FragmentGenerationIssue {
44 self.issue
45 }
46
47 #[must_use]
49 pub const fn token(self) -> Option<crate::token::SpanHandle> {
50 self.at
51 }
52}
53
54fn preserved_token(
56 token: &CapturedTokenTree,
57 source_spans: &mut Vec<Option<crate::token::SpanHandle>>,
58) -> Result<GeneratedToken, FragmentGenerationRefusal> {
59 source_spans.push(Some(token.span()));
60 match token.payload() {
61 CapturedPayload::Word(word) => Ok(GeneratedToken::word(word)),
62 CapturedPayload::Punct(mark) => Ok(GeneratedToken::alone(*mark)),
63 CapturedPayload::Text(text) => Ok(GeneratedToken::text(text)),
64 CapturedPayload::Number(spelling) => GeneratedLiteral::number(spelling)
65 .map(GeneratedToken::literal)
66 .map_err(|issue| literal_refusal(issue, token)),
67 CapturedPayload::Group { delimiter, trees } => {
68 preserved_group(*delimiter, trees.as_slice(), token, source_spans)
69 }
70 CapturedPayload::ByteText(material) => Ok(GeneratedToken::byte_text(material)),
71 CapturedPayload::Character(character) => Ok(GeneratedToken::literal(
72 GeneratedLiteral::character(*character),
73 )),
74 CapturedPayload::Byte(byte) => Ok(GeneratedToken::literal(GeneratedLiteral::byte(*byte))),
75 CapturedPayload::NulTerminatedText(material) => {
76 GeneratedLiteral::nul_terminated_text(material)
77 .map(GeneratedToken::literal)
78 .map_err(|issue| literal_refusal(issue, token))
79 }
80 CapturedPayload::RawIdentifier(name) => Ok(GeneratedToken::raw_identifier(name)),
81 CapturedPayload::JointPunct(mark) => Ok(GeneratedToken::joint(*mark)),
82 }
83}
84
85fn preserved_group(
87 delimiter: CapturedDelimiter,
88 members: &[CapturedTokenTree],
89 source: &CapturedTokenTree,
90 source_spans: &mut Vec<Option<crate::token::SpanHandle>>,
91) -> Result<GeneratedToken, FragmentGenerationRefusal> {
92 let tokens = members
93 .iter()
94 .map(|member| preserved_token(member, source_spans))
95 .collect::<Result<Vec<_>, _>>()?;
96 GeneratedToken::group(generated_delimiter(delimiter), tokens).map_err(|_| {
97 FragmentGenerationRefusal {
98 issue: FragmentGenerationIssue::Unbounded,
99 at: Some(source.span()),
100 }
101 })
102}
103
104const fn generated_delimiter(delimiter: CapturedDelimiter) -> GeneratedDelimiter {
106 match delimiter {
107 CapturedDelimiter::Parenthesis => GeneratedDelimiter::Parenthesis,
108 CapturedDelimiter::Brace => GeneratedDelimiter::Brace,
109 CapturedDelimiter::Bracket => GeneratedDelimiter::Bracket,
110 CapturedDelimiter::Bare => GeneratedDelimiter::Bare,
111 }
112}
113
114const fn literal_refusal(
116 issue: super::GeneratedLiteralRefusal,
117 token: &CapturedTokenTree,
118) -> FragmentGenerationRefusal {
119 FragmentGenerationRefusal {
120 issue: FragmentGenerationIssue::Literal(issue),
121 at: Some(token.span()),
122 }
123}