logos_codegen/generator/
tables.rs

1use crate::util::ToIdent;
2use proc_macro2::{Literal, TokenStream};
3use quote::{quote, ToTokens};
4use syn::Ident;
5
6pub struct TableStack {
7    tables: Vec<(Ident, [u8; 256])>,
8    shift: u8,
9}
10
11pub struct TableView<'a> {
12    ident: &'a Ident,
13    table: &'a mut [u8; 256],
14    mask: u8,
15}
16
17impl TableStack {
18    pub fn new() -> Self {
19        TableStack {
20            tables: vec![("COMPACT_TABLE_0".to_ident(), [0; 256])],
21            shift: 0,
22        }
23    }
24
25    pub fn view(&mut self) -> TableView {
26        let mask = if self.shift < 8 {
27            // Reusing existing table with a shifted mask
28            let mask = 1u8 << self.shift;
29
30            self.shift += 1;
31
32            mask
33        } else {
34            // Need to create a new table
35            let ident = format!("COMPACT_TABLE_{}", self.tables.len()).to_ident();
36
37            self.tables.push((ident, [0; 256]));
38            self.shift = 1;
39
40            1
41        };
42
43        let (ref ident, ref mut table) = self.tables.last_mut().unwrap();
44
45        TableView { ident, table, mask }
46    }
47}
48
49impl<'a> TableView<'a> {
50    pub fn ident(&self) -> &'a Ident {
51        self.ident
52    }
53
54    pub fn flag(&mut self, byte: u8) {
55        self.table[byte as usize] |= self.mask;
56    }
57
58    pub fn mask(&self) -> Literal {
59        Literal::u8_unsuffixed(self.mask)
60    }
61}
62
63impl ToTokens for TableStack {
64    fn to_tokens(&self, out: &mut TokenStream) {
65        if self.shift == 0 {
66            return;
67        }
68
69        for (ident, table) in self.tables.iter() {
70            let bytes = table.iter().copied().map(Literal::u8_unsuffixed);
71
72            out.extend(quote! {
73                static #ident: [u8; 256] = [#(#bytes),*];
74            });
75        }
76    }
77}