csml_interpreter/parser/
step_checksum.rs1use crate::data::{ast::*, tokens::*};
2use crate::error_format::*;
3use crate::interpreter::variable_handler::interval::interval_from_expr;
4use crate::parser::parse_comments::comment;
5
6use nom::{
7 bytes::complete::take_while1,
8 error::{ContextError, ParseError},
9 multi::fold_many0,
10 sequence::preceded,
11 Err, IResult, InputTake,
12};
13
14fn get_text<'a, E>(s: Span<'a>) -> IResult<Span<'a>, &'a str, E>
19where
20 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
21{
22 let (rest, string) = take_while1(|c: char| !WHITE_SPACE.contains(c))(s)?;
23
24 Ok((rest, (*string.fragment())))
25}
26
27fn clean_text<'a, E>(s: Span<'a>) -> IResult<Span<'a>, String, E>
28where
29 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
30{
31 let (span, vec) = fold_many0(preceded(comment, get_text), Vec::new, |mut acc, item| {
32 acc.push(item);
33 acc
34 })(s)?;
35
36 let s: String = vec.into_iter().collect();
37 Ok((span, s))
38}
39
40fn get_step_offset(
41 name: &str,
42 offsets: &[(String, usize)],
43) -> ((String, usize), Option<(String, usize)>) {
44 let mut step_info = None;
45 let mut index = 0;
46
47 for (i, (step_name, offset)) in offsets.iter().enumerate() {
48 if step_name == name {
49 step_info = Some((step_name.to_owned(), offset.to_owned()));
50 index = i;
51 break;
52 }
53 }
54
55 match step_info {
56 Some(step_info) => {
57 if offsets.len() > index + 1 {
58 let next_step = offsets[index + 1].clone();
59 (step_info, Some(next_step))
60 } else {
61 (step_info, None)
62 }
63 }
64 None => unreachable!(),
65 }
66}
67
68fn get_skip_offset(skip_offsets: &[usize], offset: usize) -> Option<usize> {
69 for skip_offset in skip_offsets.iter() {
70 if *skip_offset > offset {
71 return Some(*skip_offset);
72 }
73 }
74 None
75}
76
77fn get_next_offset(
78 offset: usize,
79 next_step: Option<(String, usize)>,
80 skip_offsets: &[usize],
81) -> Option<usize> {
82 match next_step {
83 Some((_, next_step_offset)) => match get_skip_offset(skip_offsets, offset) {
84 Some(skip_offset) => {
85 if skip_offset > next_step_offset {
86 Some(skip_offset)
87 } else {
88 Some(next_step_offset)
89 }
90 }
91 None => Some(next_step_offset),
92 },
93 None => get_skip_offset(skip_offsets, offset),
94 }
95}
96
97fn get_offsets(ast: &Flow) -> (Vec<(String, usize)>, Vec<usize>) {
98 let mut offsets = vec![];
99 let mut skip_offsets = vec![];
100
101 for (instruction_type, block) in ast.flow_instructions.iter() {
102 match instruction_type {
103 InstructionScope::StepScope(name) | InstructionScope::Constant(name) => {
104 let interval = interval_from_expr(block);
105 offsets.push((name.to_owned(), interval.offset))
106 }
107 InstructionScope::FunctionScope { .. }
108 | InstructionScope::ImportScope(_)
109 | InstructionScope::InsertStep(_) => {
110 let interval = interval_from_expr(block);
111 skip_offsets.push(interval.offset)
112 }
113 InstructionScope::DuplicateInstruction(..) => {}
114 }
115 }
116 offsets.sort_by(|(_, a), (_, b)| a.cmp(b));
117 skip_offsets.sort_by(|a, b| a.cmp(b));
118
119 (offsets, skip_offsets)
120}
121
122pub fn get_step<'a>(step_name: &'a str, flow: &'a str, ast: &'a Flow) -> String {
127 let (offsets, skip_offsets) = get_offsets(ast);
128 let span = Span::new(flow);
129
130 let ((_, offset), next_step) = get_step_offset(step_name, &offsets);
131 let (new, _) = span.take_split(offset);
132 match get_next_offset(offset, next_step, &skip_offsets) {
133 Some(skip_offset) => {
134 let (_, old) = new.take_split(skip_offset - offset);
135 old.fragment().to_string()
136 }
137 None => match clean_text::<CustomError<Span<'a>>>(new) {
138 Ok((_s, string)) => string,
139 Err(e) => match e {
140 Err::Error(_) | Err::Failure(_) => unreachable!(),
141 Err::Incomplete(_err) => unreachable!(),
142 },
143 },
144 }
145}