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    fn space(&mut self, x: usize) {
112        if self.enable {
113            self.width += x as u32;
114        }
115    }
116}
117
118pub mod align_kind {
119    pub const IDENTIFIER: usize = 0;
120    pub const TYPE: usize = 1;
121    pub const EXPRESSION: usize = 2;
122    pub const WIDTH: usize = 3;
123    pub const ARRAY: usize = 4;
124    pub const ASSIGNMENT: usize = 5;
125    pub const PARAMETER: usize = 6;
126    pub const DIRECTION: usize = 7;
127    pub const CLOCK_DOMAIN: usize = 8;
128    pub const NUMBER: usize = 9;
129}
130
131#[derive(Default)]
132pub struct Aligner {
133    pub additions: HashMap<Location, u32>,
134    pub aligns: [Align; 10],
135}
136
137impl Aligner {
138    pub fn new() -> Self {
139        Default::default()
140    }
141
142    pub fn token(&mut self, x: &VerylToken) {
143        for i in 0..self.aligns.len() {
144            self.aligns[i].token(x);
145        }
146    }
147
148    pub fn duplicated_token(&mut self, x: &VerylToken, idx: usize) {
149        for i in 0..self.aligns.len() {
150            self.aligns[i].duplicated_token(x, idx);
151        }
152    }
153
154    pub fn space(&mut self, x: usize) {
155        for i in 0..self.aligns.len() {
156            self.aligns[i].space(x);
157        }
158    }
159
160    pub fn finish_group(&mut self) {
161        for i in 0..self.aligns.len() {
162            self.aligns[i].finish_group();
163        }
164    }
165
166    pub fn finish_item(&mut self) {
167        for i in 0..self.aligns.len() {
168            self.aligns[i].finish_item();
169        }
170    }
171
172    pub fn gather_additions(&mut self) {
173        for align in &self.aligns {
174            for (x, y) in &align.additions {
175                self.additions
176                    .entry(*x)
177                    .and_modify(|val| *val += *y)
178                    .or_insert(*y);
179            }
180        }
181    }
182
183    pub fn enable_auto_finish(&mut self) {
184        for align in &mut self.aligns {
185            align.disable_auto_finish = false;
186        }
187    }
188
189    pub fn disable_auto_finish(&mut self) {
190        for align in &mut self.aligns {
191            align.disable_auto_finish = true;
192        }
193    }
194
195    pub fn any_enabled(&self) -> bool {
196        self.aligns.iter().any(|x| x.enable)
197    }
198}
199
200#[derive(Clone, Debug, Default)]
201pub struct Measure {
202    widths: Vec<u32>,
203    table: HashMap<TokenId, u32>,
204}
205
206impl Measure {
207    pub fn start(&mut self) {
208        self.widths.push(0);
209    }
210
211    pub fn finish(&mut self, id: TokenId) {
212        let width = self.widths.pop().unwrap();
213        self.table.insert(id, width);
214    }
215
216    pub fn add(&mut self, value: u32) {
217        for w in &mut self.widths {
218            *w += value;
219        }
220    }
221
222    pub fn get(&mut self, id: TokenId) -> Option<u32> {
223        self.table.get(&id).copied()
224    }
225}