mini_builder_rs/evaluator/
evaluator.rs

1use crate::parser::{expression::Expression, node::Node, node::NodeContent};
2
3use super::{
4	block::{Block, Blocks, ForBlock, IfBlock},
5	evaluate_blocks,
6	evaluation_context::EvaluationContext,
7	evaluator_builder_error::EvaluatorBuilderError,
8	list_dependencies_block, Dependencies, Evaluate,
9};
10
11pub type BlocksResult<'a, 'b> = Result<Blocks<'a, 'b>, EvaluatorBuilderError>;
12pub type IfBlockResult<'a, 'b> = Result<IfBlock<'a, 'b>, EvaluatorBuilderError>;
13pub type EvaluatorResult<'a, 'b> = Result<Evaluator<'a, 'b>, EvaluatorBuilderError>;
14
15pub struct EvaluatorBuilder<'a, 'b> {
16	nodes: &'a [Box<Node<'b>>],
17	i: usize,
18}
19
20impl<'a, 'b> EvaluatorBuilder<'a, 'b> {
21	pub fn new(nodes: &'a [Box<Node<'b>>]) -> Self {
22		Self { nodes, i: 0 }
23	}
24
25	fn advance(&mut self) {
26		self.i = (self.i + 1).min(self.nodes.len());
27	}
28
29	fn regress(&mut self) {
30		if self.i > 0 {
31			self.i -= 1;
32		}
33	}
34
35	fn peek(&mut self) -> Option<&'a Box<Node<'b>>> {
36		if self.i < self.nodes.len() {
37			Some(&self.nodes[self.i])
38		} else {
39			None
40		}
41	}
42
43	fn next(&mut self) -> Option<&'a Box<Node<'b>>> {
44		let ret = self.peek();
45		self.advance();
46		ret
47	}
48
49	fn build_if(&mut self, first_expression: &'a Expression<'b>) -> IfBlockResult<'a, 'b> {
50		let mut if_blocks = vec![(first_expression, Vec::new())];
51		let mut else_blocks = None;
52		while let Some(n) = self.next() {
53			match &n.content {
54				NodeContent::Elif(expression) => {
55					// push an empty `if_block` with the new expression
56					if_blocks.push((expression, Vec::new()));
57				}
58				NodeContent::Else => {
59					// add the final blocks in the if-else chain and break
60					let blocks = self.build_blocks(true, false)?;
61					else_blocks = Some(blocks);
62					break;
63				}
64				NodeContent::End => break,
65				_ => {
66					self.regress();
67
68					// add blocks to the current `if`
69					let blocks = self.build_blocks(false, true)?;
70					if_blocks.last_mut().unwrap().1.extend(blocks.into_iter());
71				}
72			}
73		}
74		Ok(IfBlock::new(if_blocks, else_blocks))
75	}
76
77	fn build_blocks(&mut self, consume_end: bool, expect_else: bool) -> BlocksResult<'a, 'b> {
78		let mut blocks = Vec::new();
79		while let Some(n) = self.next() {
80			match &n.content {
81				NodeContent::Source(source) => blocks.push(Box::new(Block::Source(source))),
82				NodeContent::Expression(expression) => {
83					blocks.push(Box::new(Block::Expression(expression)))
84				}
85				NodeContent::Assignment(name, tt, expression) => {
86					blocks.push(Box::new(Block::Assignment(name, *tt, expression)))
87				}
88				NodeContent::If(expression) => {
89					let if_block = self.build_if(expression)?;
90					blocks.push(Box::new(Block::If(Box::new(if_block))));
91				}
92				NodeContent::For(var_name, expression) => {
93					let inner_blocks = self.build_blocks(true, false)?;
94					let for_block = ForBlock::new(var_name, expression, inner_blocks);
95					blocks.push(Box::new(Block::For(Box::new(for_block))));
96				}
97				NodeContent::End => {
98					if !consume_end {
99						self.regress();
100					}
101					break;
102				}
103				NodeContent::Else if expect_else => {
104					self.regress();
105					break;
106				}
107				NodeContent::Elif(..) if expect_else => {
108					self.regress();
109					break;
110				}
111				_ => {
112					return Err(EvaluatorBuilderError::UnexpectedNodeContent(format!(
113						"{:?}",
114						n.content
115					)))
116				}
117			}
118		}
119		Ok(blocks)
120	}
121
122	pub fn build(&mut self) -> BlocksResult<'a, 'b> {
123		self.build_blocks(true, false)
124	}
125
126	pub fn build_evaluator(&mut self) -> EvaluatorResult<'a, 'b> {
127		Ok(Evaluator::new(self.build()?))
128	}
129}
130
131pub struct Evaluator<'a, 'b> {
132	blocks: Blocks<'a, 'b>,
133	// shallow dependencies - non builder recursive
134	dependencies: Dependencies,
135}
136
137impl<'a, 'b> Evaluator<'a, 'b> {
138	fn new(blocks: Blocks<'a, 'b>) -> Self {
139		// calculate dependencies
140		let mut dependencies = Dependencies::empty();
141		for block in &blocks {
142			list_dependencies_block(block, &mut dependencies);
143		}
144
145		Self {
146			blocks,
147			dependencies,
148		}
149	}
150}
151
152impl<'a, 'b> Evaluate for Evaluator<'a, 'b> {
153	fn evaluate<'ea>(&self, context: &mut EvaluationContext<'ea, impl Evaluate>) -> String {
154		evaluate_blocks(context, &self.blocks)
155	}
156
157	fn get_dependencies(&self) -> &Dependencies {
158		&self.dependencies
159	}
160}