Skip to main content

veryl_aligner/
lib.rs

1use std::collections::HashMap;
2use veryl_parser::resource_table::TokenId;
3use veryl_parser::veryl_token::{Token, VerylToken};
4
5#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
6pub struct Location {
7    pub line: u32,
8    pub column: u32,
9    pub length: u32,
10    pub duplicated: Option<usize>,
11}
12
13impl From<&Token> for Location {
14    fn from(x: &Token) -> Self {
15        Self {
16            line: x.line,
17            column: x.column,
18            length: x.length,
19            duplicated: None,
20        }
21    }
22}
23
24impl From<Token> for Location {
25    fn from(x: Token) -> Self {
26        Self {
27            line: x.line,
28            column: x.column,
29            length: x.length,
30            duplicated: None,
31        }
32    }
33}
34
35#[derive(Default)]
36pub struct Align {
37    enable: bool,
38    index: usize,
39    max_width: u32,
40    width: u32,
41    line: u32,
42    rest: Vec<(Location, u32)>,
43    additions: HashMap<Location, u32>,
44    disable_auto_finish: bool,
45    pub last_location: Option<Location>,
46}
47
48impl Align {
49    fn finish_group(&mut self) {
50        for (loc, width) in &self.rest {
51            self.additions.insert(*loc, self.max_width - width);
52        }
53        self.rest.clear();
54        self.max_width = 0;
55    }
56
57    pub fn finish_item(&mut self) {
58        if self.enable {
59            self.enable = false;
60            if let Some(loc) = self.last_location {
61                if !self.disable_auto_finish && (self.line > loc.line || loc.line - self.line > 1) {
62                    self.finish_group();
63                }
64                self.max_width = u32::max(self.max_width, self.width);
65                self.line = loc.line;
66                self.rest.push((loc, self.width));
67
68                self.width = 0;
69                self.index += 1;
70            }
71        }
72    }
73
74    pub fn start_item(&mut self) {
75        self.enable = true;
76        self.width = 0;
77    }
78
79    fn token(&mut self, x: &VerylToken) {
80        if self.enable {
81            self.width += x.token.length;
82            let loc: Location = x.token.into();
83            self.last_location = Some(loc);
84        }
85    }
86
87    pub fn dummy_location(&mut self, x: Location) {
88        if self.enable {
89            self.width += 0; // 0 length token
90            self.last_location = Some(x);
91        }
92    }
93
94    pub fn dummy_token(&mut self, x: &VerylToken) {
95        if self.enable {
96            self.width += 0; // 0 length token
97            let loc: Location = x.token.into();
98            self.last_location = Some(loc);
99        }
100    }
101
102    pub fn duplicated_token(&mut self, x: &VerylToken, i: usize) {
103        if self.enable {
104            self.width += x.token.length;
105            let mut loc: Location = x.token.into();
106            loc.duplicated = Some(i);
107            self.last_location = Some(loc);
108        }
109    }
110
111    pub fn add_width(&mut self, width: u32) {
112        if self.enable {
113            self.width += width;
114        }
115    }
116
117    fn space(&mut self, x: usize) {
118        if self.enable {
119            self.width += x as u32;
120        }
121    }
122}
123
124pub mod align_kind {
125    pub const IDENTIFIER: usize = 0;
126    pub const TYPE: usize = 1;
127    pub const EXPRESSION: usize = 2;
128    pub const WIDTH: usize = 3;
129    pub const ARRAY: usize = 4;
130    pub const ASSIGNMENT: usize = 5;
131    pub const PARAMETER: usize = 6;
132    pub const DIRECTION: usize = 7;
133    pub const CLOCK_DOMAIN: usize = 8;
134    pub const NUMBER: usize = 9;
135    pub const VAR_KEYWORD: usize = 10;
136}
137
138#[derive(Default)]
139pub struct Aligner {
140    pub additions: HashMap<Location, u32>,
141    pub aligns: [Align; 11],
142}
143
144impl Aligner {
145    pub fn new() -> Self {
146        Default::default()
147    }
148
149    pub fn token(&mut self, x: &VerylToken) {
150        for i in 0..self.aligns.len() {
151            self.aligns[i].token(x);
152        }
153    }
154
155    pub fn duplicated_token(&mut self, x: &VerylToken, idx: usize) {
156        for i in 0..self.aligns.len() {
157            self.aligns[i].duplicated_token(x, idx);
158        }
159    }
160
161    pub fn space(&mut self, x: usize) {
162        for i in 0..self.aligns.len() {
163            self.aligns[i].space(x);
164        }
165    }
166
167    pub fn finish_group(&mut self) {
168        for i in 0..self.aligns.len() {
169            self.aligns[i].finish_group();
170        }
171    }
172
173    pub fn finish_item(&mut self) {
174        for i in 0..self.aligns.len() {
175            self.aligns[i].finish_item();
176        }
177    }
178
179    pub fn gather_additions(&mut self) {
180        for align in &self.aligns {
181            for (x, y) in &align.additions {
182                self.additions
183                    .entry(*x)
184                    .and_modify(|val| *val += *y)
185                    .or_insert(*y);
186            }
187        }
188    }
189
190    pub fn enable_auto_finish(&mut self) {
191        for align in &mut self.aligns {
192            align.disable_auto_finish = false;
193        }
194    }
195
196    pub fn disable_auto_finish(&mut self) {
197        for align in &mut self.aligns {
198            align.disable_auto_finish = true;
199        }
200    }
201
202    pub fn any_enabled(&self) -> bool {
203        self.aligns.iter().any(|x| x.enable)
204    }
205}
206
207#[derive(Clone, Debug, Default)]
208pub struct Measure {
209    widths: Vec<u32>,
210    table: HashMap<TokenId, u32>,
211}
212
213impl Measure {
214    pub fn start(&mut self) {
215        self.widths.push(0);
216    }
217
218    pub fn finish(&mut self, id: TokenId) {
219        let width = self.widths.pop().unwrap();
220        self.table.insert(id, width);
221    }
222
223    pub fn add(&mut self, value: u32) {
224        for w in &mut self.widths {
225            *w += value;
226        }
227    }
228
229    pub fn get(&mut self, id: TokenId) -> Option<u32> {
230        self.table.get(&id).copied()
231    }
232}