yozuk_helper_preprocessor/
lib.rs1#![forbid(unsafe_code)]
2#![deny(clippy::all)]
3
4use std::collections::VecDeque;
5use std::fmt;
6use yozuk_sdk::prelude::*;
7
8pub trait TokenParser: Send + Sync {
9 fn parse(&self, tokens: &[Token]) -> Option<Token>;
10}
11
12pub struct TokenMerger<P> {
13 parser: P,
14}
15
16impl<P> fmt::Debug for TokenMerger<P> {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 f.debug_struct("TokenMerger").finish()
19 }
20}
21
22impl<P> TokenMerger<P> {
23 pub fn new(parser: P) -> Self {
24 Self { parser }
25 }
26}
27
28impl<P> Preprocessor for TokenMerger<P>
29where
30 P: TokenParser + 'static,
31{
32 fn preprocess(&self, input: Vec<Token>) -> Vec<Token> {
33 let mut output = Vec::new();
34 let mut tokens = input.into_iter().collect::<VecDeque<_>>();
35 while !tokens.is_empty() {
36 for i in 1..=tokens.len() {
37 let len = tokens.len() + 1 - i;
38 let exp = tokens.as_slices().0;
39 let exp = if exp.len() >= len {
40 &exp[..len]
41 } else {
42 &tokens.make_contiguous()[..len]
43 };
44 if let Some(merged) = self.parser.parse(exp) {
45 for _ in 0..len {
46 tokens.pop_front();
47 }
48 output.push(merged);
49 break;
50 }
51 }
52 if let Some(front) = tokens.pop_front() {
53 output.push(front);
54 }
55 }
56 output
57 }
58}