Skip to main content

rpk_config/
compiler.rs

1use std::{collections::HashMap, ops::Range, str::CharIndices};
2
3use rpk_common::{
4    keycodes::{
5        key_range::{self, BASIC_0, BASIC_1, BASIC_A},
6        macro_types,
7    },
8    PROTOCOL_VERSION,
9};
10
11use crate::{
12    globals::{
13        self,
14        spec::{GlobalProp, GlobalType},
15    },
16    keycodes::{self, key_code, unshifted_char_code},
17    ConfigError,
18};
19
20type Result<T> = core::result::Result<T, ConfigError>;
21type IndexChar = (usize, char);
22type NameRange = Range<usize>;
23
24const TOO_MANY_RHS: &str = "Only one value may be assigned";
25const TOO_MANY_MULTI_ALIAS_RHS: &str =
26    "Only one value may be assigned to an multi-positioned alias";
27const TOO_MANY_ROWS: &str = "Too many rows";
28const TOO_MANY_COLS: &str = "Too many keys in row";
29const UNKNOWN_ACTION: &str = "Unknown action/keycode";
30const SYNTAX_ERROR: &str = "Syntax error";
31const EOF: &str = "Unexpected end of file";
32
33struct SourceIter<'source> {
34    iter: CharIndices<'source>,
35    current: IndexChar,
36    next: Option<IndexChar>,
37    len: usize,
38}
39impl<'source> SourceIter<'source> {
40    pub fn new(iter: CharIndices<'source>, len: usize) -> Self {
41        Self {
42            iter,
43            current: (usize::MAX, '\0'),
44            next: None,
45            len,
46        }
47    }
48
49    fn put_back(&mut self, item: IndexChar) {
50        assert!(self.next.is_none() && item.0 == self.current.0);
51        self.next = Some(item);
52    }
53
54    fn next(&mut self) -> Option<IndexChar> {
55        let mut in_comment = false;
56        while let Some(item) = self.next.take().or_else(|| self.iter.next()) {
57            match item.1 {
58                '\n' => {}
59                '#' => {
60                    in_comment = true;
61                    continue;
62                }
63                _ => {
64                    if in_comment {
65                        continue;
66                    }
67                }
68            }
69            self.current = item;
70            return Some(item);
71        }
72        self.current.0 = self.len;
73        None
74    }
75
76    fn find(&mut self, pred: impl Fn(char) -> bool) -> Option<IndexChar> {
77        while let Some(item) = self.next() {
78            if pred(item.1) {
79                return Some(item);
80            }
81        }
82        None
83    }
84
85    fn find_close_paren(&mut self, parens: (char, char)) -> Option<IndexChar> {
86        let mut count = 1;
87        while let Some(item) = self.next() {
88            if item.1 == parens.0 {
89                count += 1;
90            } else if item.1 == parens.1 {
91                if count == 1 {
92                    return Some(item);
93                } else {
94                    count -= 1;
95                }
96            }
97        }
98        None
99    }
100}
101
102struct Parser<'source> {
103    iter: SourceIter<'source>,
104    config: KeyboardConfig<'source>,
105    mark_idx: usize,
106}
107
108fn non_ws_char(c: char) -> bool {
109    !c.is_whitespace()
110}
111
112fn invalid_seq_char(c: char) -> bool {
113    c.is_whitespace() || matches!(c, '(' | ')')
114}
115
116fn invalid_arg_char(c: char) -> bool {
117    invalid_seq_char(c) || c == ','
118}
119
120fn invalid_section_char(c: char) -> bool {
121    !matches!(c, '-' | '_' | '\\' | '.' | ':') && !c.is_alphanumeric()
122}
123
124pub struct KeyboardConfig<'source> {
125    pub source: &'source str,
126    pub global_map: HashMap<&'source str, GlobalProp>,
127    pub temp_map: HashMap<&'source str, u16>,
128    pub firmware_map: HashMap<&'source str, &'source str>,
129    pub matrix_map: HashMap<String, Vec<u16>>,
130    layers: HashMap<String, ConfigLayer>,
131    macros_names: HashMap<Vec<u16>, u16>,
132    macros: Vec<Macro>,
133    next_layer: u16,
134    pub row_count: u8,
135    pub col_count: u8,
136}
137
138#[derive(Debug)]
139pub struct ConfigLayer {
140    codes: HashMap<u16, u16>,
141    index: u16,
142    suffix: u8,
143}
144
145#[derive(Debug, PartialEq)]
146pub enum Macro {
147    Modifier { keycode: u16, modifiers: u8 },
148    Tap(Vec<u16>),
149    HoldRelease { hold: u16, release: u16 },
150    Hold(Vec<u16>),
151    Release(Vec<u16>),
152    DualAction(u16, u16),
153    TimedDualAction(u16, u16, u16, u16),
154    Delay(u16),
155}
156impl Macro {
157    fn serialize(&self) -> Vec<u16> {
158        match *self {
159            Macro::Modifier { keycode, modifiers } => {
160                vec![(modifiers as u16) << 8, keycode]
161            }
162            Macro::Tap(ref seq) => binary_seq(macro_types::TAP, seq),
163            Macro::HoldRelease { hold, release } => {
164                vec![macro_types::HOLD_RELEASE, hold, release]
165            }
166            Macro::Hold(ref seq) => binary_seq(macro_types::HOLD, seq),
167            Macro::Release(ref seq) => binary_seq(macro_types::RELEASE, seq),
168            Macro::DualAction(tap, hold) => {
169                vec![macro_types::DUAL_ACTION, tap, hold]
170            }
171            Macro::TimedDualAction(tap, hold, time1, time2) => {
172                if time2 == u16::MAX {
173                    vec![macro_types::DUAL_ACTION, tap, hold, time1]
174                } else {
175                    vec![macro_types::DUAL_ACTION, tap, hold, time1, time2]
176                }
177            }
178            Macro::Delay(n) => {
179                vec![macro_types::DELAY, n]
180            }
181        }
182    }
183}
184
185fn binary_seq(id: u16, seq: &[u16]) -> Vec<u16> {
186    let mut result = Vec::with_capacity(seq.len() + 1);
187    result.push(id);
188    result.extend_from_slice(seq);
189    result
190}
191
192impl<'source> Parser<'source> {
193    fn new(source: &'source str) -> Self {
194        Self {
195            iter: SourceIter::new(source.char_indices(), source.len()),
196            config: KeyboardConfig::new(source),
197            mark_idx: 0,
198        }
199    }
200
201    fn parse_sections(&mut self) -> Result<()> {
202        self.config.scan_layer_names()?;
203        loop {
204            match self.next_non_ws() {
205                None => return Ok(()),
206                Some(start) => {
207                    if start.1 == '[' {
208                        self.mark_start();
209                        let maybe_tag_end = self
210                            .iter
211                            .find(|c| matches!(c, ']' | ':' | '.') || invalid_section_char(c));
212                        if let Some(tag_end) = maybe_tag_end {
213                            let maybe_end = match tag_end.1 {
214                                ':' | '.' => {
215                                    self.iter.find(|c| c == ']' || invalid_section_char(c))
216                                }
217                                _ => maybe_tag_end,
218                            };
219                            if let Some(end) = maybe_end {
220                                let tag_name = &self.config.source[start.0 + 1..tag_end.0];
221                                match tag_name {
222                                    "global" => self.parse_global(tag_end.0 + 1..end.0)?,
223                                    "matrix" => self.parse_matrix()?,
224                                    "firmware" => {
225                                        self.assert_no_suffix(tag_end.0, end.0)?;
226                                        self.parse_firmware()?
227                                    }
228                                    "aliases" => {
229                                        self.assert_no_suffix(tag_end.0, end.0)?;
230                                        self.parse_aliases()?
231                                    }
232                                    _ => self.parse_layer(tag_name)?,
233                                }
234                                continue;
235                            }
236                        }
237
238                        return Err(ConfigError::new("missing ']'".into(), start.0..start.0 + 1));
239                    } else {
240                        return Err(ConfigError::new(
241                            "expected '['".into(),
242                            start.0..start.0 + 1,
243                        ));
244                    }
245                }
246            }
247        }
248    }
249
250    fn parse_global(&mut self, suffix: NameRange) -> Result<()> {
251        if suffix.start < suffix.end {
252            let name = self.name(&suffix);
253            let (name, field) = name.split_once('.').unwrap_or((name, ""));
254
255            match self.config.take_global(name) {
256                Ok(mut g) => {
257                    while let Some(pos) = self.skip_whitespace() {
258                        if pos.1 == '[' {
259                            break;
260                        }
261                        match self.parse_assignment()? {
262                            None => return Ok(()),
263                            Some((left, right)) => {
264                                let eol = self
265                                    .iter
266                                    .find(|c| c == '\n')
267                                    .unwrap_or((self.config.source.len(), '\0'));
268                                if let Err(err) = g.set_sub_field(
269                                    field,
270                                    self.name(&left),
271                                    self.name(&(right.start..eol.0)),
272                                ) {
273                                    return Err(error_span(err, left.start..eol.0));
274                                }
275                            }
276                        }
277                    }
278                    self.config.insert_global(name, g);
279
280                    return Ok(());
281                }
282                Err(err) => return Err(error_span(err.message, suffix)),
283            }
284        }
285
286        while let Some(pos) = self.skip_whitespace() {
287            if pos.1 == '[' {
288                return Ok(());
289            }
290            match self.parse_assignment()? {
291                None => return Ok(()),
292                Some((left, right)) => {
293                    self.assign_global(&left, &right)?;
294                    self.assert_no_more_values(TOO_MANY_RHS)?;
295                }
296            }
297        }
298        Ok(())
299    }
300
301    fn assign_global(&mut self, name_range: &NameRange, value_range: &NameRange) -> Result<()> {
302        let name = self.name(name_range);
303        match name {
304            "unicode_prefix" | "unicode_suffix" => {
305                let action = self.read_action(value_range.start..value_range.end)?;
306                self.config.temp_map.insert(name, action);
307            }
308            _ => {
309                let p = globals::DEFAULTS.get(name).ok_or_else(|| {
310                    error_span(
311                        format!("Invalid global '{}'", name).as_str(),
312                        name_range.start..name_range.end,
313                    )
314                })?;
315
316                use GlobalType::*;
317                let value = GlobalProp {
318                    index: p.index,
319                    spec: match p.spec {
320                        Timeout(_) => {
321                            GlobalType::Timeout(self.config.parse_duration(value_range, 5000)?)
322                        }
323                        _ => unreachable!(),
324                    },
325                };
326
327                self.config.global_map.insert(name, value);
328            }
329        };
330        Ok(())
331    }
332
333    fn parse_matrix(&mut self) -> Result<()> {
334        while let Some(pos) = self.skip_whitespace() {
335            if pos.1 == '[' {
336                return Ok(());
337            }
338            self.skip_whitespace();
339            let mark = self.iter.current.0;
340            match self.parse_assignment()? {
341                None => return Ok(()),
342                Some((left, right)) => {
343                    self.mark_idx = mark;
344                    let mut pos = self
345                        .config
346                        .key_position(self.name(&left))
347                        .ok_or_else(|| self.error("Invalid key code"))?;
348                    if (pos >> 8) as u8 >= self.config.row_count {
349                        return Err(self.error(TOO_MANY_ROWS));
350                    }
351
352                    let mut right = Some(right);
353                    while let Some(value) = &right {
354                        let value = self.name(value);
355                        if (pos & 0xff) as u8 >= self.config.col_count {
356                            return Err(self.error(TOO_MANY_COLS));
357                        }
358                        self.config.assign_position_name(pos, value);
359                        if let Some(code) = keycodes::key_code(value) {
360                            self.config.assign_one_layer_code("main", pos, code);
361                        }
362                        pos += 1;
363                        right = self.next_assignment_value();
364                    }
365                }
366            }
367        }
368        Ok(())
369    }
370
371    fn parse_aliases(&mut self) -> Result<()> {
372        while let Some(pos) = self.skip_whitespace() {
373            if pos.1 == '[' {
374                return Ok(());
375            }
376            self.skip_whitespace();
377            match self.parse_assignment()? {
378                None => return Ok(()),
379                Some((key, right)) => {
380                    let value = self.name(&right);
381                    if !self.config.assign_aliases(self.name(&key), value) {
382                        return Err(error_span("Unknown key name", key));
383                    }
384                    self.assert_no_more_values(TOO_MANY_RHS)?;
385                }
386            }
387        }
388        Ok(())
389    }
390
391    fn parse_firmware(&mut self) -> Result<()> {
392        while let Some(pos) = self.skip_whitespace() {
393            if pos.1 == '[' {
394                return Ok(());
395            }
396            self.skip_whitespace();
397            match self.parse_assignment()? {
398                None => return Ok(()),
399                Some((key, right)) => {
400                    let eol = self
401                        .iter
402                        .find(|c| c == '\n')
403                        .unwrap_or((self.config.source.len(), '\0'));
404                    let key = self.name(&key);
405                    let value = self.trim_value(&(right.start..eol.0));
406                    value
407                        .replace("#", "//")
408                        .parse::<proc_macro2::TokenStream>()
409                        .map_err(|_| error_span(SYNTAX_ERROR, right.start..eol.0))?;
410                    self.config.firmware_map.insert(key, value);
411                }
412            }
413        }
414        Ok(())
415    }
416
417    fn parse_layer(&mut self, name: &str) -> Result<()> {
418        while let Some(pos) = self.skip_whitespace() {
419            if pos.1 == '[' {
420                return Ok(());
421            }
422            self.skip_whitespace();
423            let mark = self.iter.current.0;
424            match self.parse_assignment()? {
425                None => return Ok(()),
426                Some((left_range, right)) => {
427                    self.mark_idx = mark;
428                    let left = self.name(&left_range);
429
430                    let alias_value = self.config.get_aliases(left);
431
432                    let keypos = if let Some(list) = alias_value {
433                        if list.len() == 1 {
434                            list.first().copied()
435                        } else {
436                            None
437                        }
438                    } else {
439                        self.config.key_position(left)
440                    };
441
442                    if let Some(mut keypos) = keypos {
443                        if (keypos >> 8) as u8 >= self.config.row_count {
444                            return Err(self.error(TOO_MANY_ROWS));
445                        }
446                        let mut right = Some(right);
447                        while let Some(value) = &right {
448                            if (keypos & 0xff) as u8 >= self.config.col_count {
449                                return Err(self.error(TOO_MANY_COLS));
450                            }
451
452                            let code = self.read_action(value.to_owned())?;
453                            self.config.assign_one_layer_code(name, keypos, code);
454
455                            right = self.next_assignment_value();
456                            keypos += 1;
457                        }
458                    } else if let Some(positions) = alias_value {
459                        let positions = positions.clone();
460                        let code = self.read_action(right)?;
461                        for pos in positions {
462                            self.config.assign_one_layer_code(name, pos, code);
463                        }
464                        self.assert_no_more_values(TOO_MANY_MULTI_ALIAS_RHS)?;
465                    } else {
466                        return Err(error_span(format!("key not found! {}", left), left_range));
467                    }
468                }
469            }
470        }
471        Ok(())
472    }
473
474    fn assert_no_more_values(&mut self, msg: &str) -> Result<()> {
475        self.mark_start();
476        if self.next_assignment_value().is_some() {
477            Err(self.error(msg))
478        } else {
479            Ok(())
480        }
481    }
482
483    fn read_action(&mut self, name_range: NameRange) -> Result<u16> {
484        let name = self.name(&name_range);
485
486        if let Some(code) = keycodes::key_code(name) {
487            Ok(code)
488        } else if let Some(base_code) = if self.iter.current.1 == '(' {
489            keycodes::action_code(name)
490        } else {
491            keycodes::modifier_macro(name)
492        } {
493            // actions
494            match base_code {
495                key_range::LAYER_MIN..=key_range::REPLACE_LAYERS_MIN => {
496                    self.iter.next();
497                    self.parse_layer_code(base_code)
498                }
499                key_range::MACROS_MIN => self.parse_macro(name_range),
500                _ => unimplemented!("read_action: {}", base_code),
501            }
502        } else {
503            Err(error_span(UNKNOWN_ACTION, name_range))
504        }
505    }
506
507    fn read_arg(&mut self) -> NameRange {
508        self.read(invalid_arg_char)
509    }
510
511    fn read_timeout(&mut self) -> Result<u16> {
512        let nr = self.read_arg();
513        self.config.parse_duration(&nr, 5000)
514    }
515
516    fn read(&mut self, f: impl Fn(char) -> bool) -> NameRange {
517        if let Some(start) = self.next_non_ws() {
518            if invalid_seq_char(start.1) {
519                self.iter.put_back(start);
520                return start.0..start.0;
521            }
522            self.mark_start();
523            if let Some(end) = self.iter.find(f) {
524                self.iter.put_back(end);
525                start.0..end.0
526            } else {
527                start.0..self.iter.current.0
528            }
529        } else {
530            self.iter.current.0..self.iter.current.0
531        }
532    }
533
534    fn read_sequence(&mut self) -> NameRange {
535        if let Some(start) = self.next_non_ws() {
536            if invalid_seq_char(start.1) {
537                self.iter.put_back(start);
538                return start.0..start.0;
539            }
540            self.mark_start();
541            if let Some(end) = self.iter.find(invalid_seq_char) {
542                self.iter.put_back(end);
543                start.0..end.0
544            } else {
545                start.0..self.iter.current.0
546            }
547        } else {
548            self.iter.current.0..self.iter.current.0
549        }
550    }
551
552    fn expect(&mut self, c: char) -> Result<()> {
553        self.mark_start();
554        if let Some(start) = self.next_non_ws() {
555            if start.1 == c {
556                return Ok(());
557            }
558        }
559
560        Err(self.error(format!("Expected {} ", c)))
561    }
562
563    fn name(&self, name_range: &NameRange) -> &'source str {
564        self.config.name(name_range)
565    }
566
567    fn trim_value(&self, name_range: &NameRange) -> &'source str {
568        let mut value = &self.config.source[name_range.start..name_range.end];
569        if let Some(i) = value.rfind('#') {
570            value = &value[..i];
571        }
572
573        value.trim()
574    }
575
576    fn dualaction(&mut self, hold: u16) -> Result<u16> {
577        self.expect(',')?;
578
579        let tap_name = self.read_arg();
580
581        let tap = self.read_action(tap_name)?;
582
583        let Some(c) = self.next_non_ws() else {
584            return Err(self.error(EOF));
585        };
586
587        Ok(if c.1 == ')' {
588            self.add_macro(Macro::DualAction(tap, hold))
589        } else {
590            let t1 = self.read_timeout()?;
591            let Some(c) = self.next_non_ws() else {
592                return Err(self.error(EOF));
593            };
594            if c.1 == ')' {
595                self.add_macro(Macro::TimedDualAction(tap, hold, t1, u16::MAX))
596            } else {
597                let t2 = self.read_timeout()?;
598                self.expect(')')?;
599                self.add_macro(Macro::TimedDualAction(tap, hold, t1, t2))
600            }
601        })
602    }
603
604    fn parse_macro(&mut self, name_range: NameRange) -> Result<u16> {
605        let name = self.name(&name_range);
606        let id = match name {
607            "macro" => {
608                self.iter.next();
609                let seq = self.macro_sequence()?;
610                self.expect(')')?;
611                if seq.len() == 2
612                    && matches!(self.get_macro(seq[0]), Some(Macro::Hold(..)))
613                    && matches!(self.get_macro(seq[1]), Some(Macro::Release(..)))
614                {
615                    self.add_macro(Macro::HoldRelease {
616                        hold: seq[0],
617                        release: seq[1],
618                    })
619                } else {
620                    self.add_macro(Macro::Tap(seq))
621                }
622            }
623            "hold" => {
624                self.iter.next();
625                let seq = self.macro_sequence()?;
626                self.expect(')')?;
627                self.add_macro(Macro::Hold(seq))
628            }
629            "release" => {
630                self.iter.next();
631                let seq = self.macro_sequence()?;
632                self.expect(')')?;
633                self.add_macro(Macro::Release(seq))
634            }
635            "overload" => {
636                self.iter.next();
637                let name = self.read_arg();
638                if name.is_empty() {
639                    return Err(self.error("Missing name"));
640                }
641                let hold = self.get_layer_index(name)? + key_range::LAYER_MIN;
642
643                self.dualaction(hold)?
644            }
645            "dualaction" => {
646                self.iter.next();
647                let hold_name = self.read_arg();
648                let hold = self.read_action(hold_name)?;
649
650                self.dualaction(hold)?
651            }
652            "unicode" => {
653                self.iter.next();
654                let uc = self.read_hex_codes()?;
655                self.expect(')')?;
656                let mac = Macro::Tap(self.config.unicode_to_seq(uc));
657                self.add_macro(mac)
658            }
659            "delay" => {
660                self.iter.next();
661                let nr = self.read_arg();
662                let d = self.config.parse_duration(&nr, 5000)?;
663                self.expect(')')?;
664                let mac = Macro::Delay(d);
665                self.add_macro(mac)
666            }
667            name => {
668                let (modifiers, keycode) = name
669                    .rsplit_once('-')
670                    .ok_or_else(|| error_span(UNKNOWN_ACTION, name_range.clone()))?;
671                let modifiers = keycodes::modifiers_to_bit_map(modifiers).ok_or_else(|| {
672                    ConfigError::new(
673                        format!("Invalid modifiers '{}'", modifiers),
674                        name_range.start..name_range.start + modifiers.len(),
675                    )
676                })?;
677                let keycode = keycodes::key_code(keycode)
678                    .ok_or_else(|| error_span(UNKNOWN_ACTION, name_range))?;
679
680                self.add_macro(Macro::Modifier { keycode, modifiers })
681            }
682        };
683        Ok(id + key_range::MACROS_MIN)
684    }
685
686    fn read_hex_codes(&mut self) -> Result<char> {
687        let mut result: u32 = 0;
688        let start = self.iter.current.0;
689        while let Some(ic) = self.iter.next() {
690            match ic.1 {
691                'a'..='f' => {
692                    result = (result << 4) + 10 + (ic.1 as u32) - ('a' as u32);
693                }
694                'A'..='F' => {
695                    result = (result << 4) + 10 + (ic.1 as u32) - ('A' as u32);
696                }
697                '0'..='9' => {
698                    result = (result << 4) + (ic.1 as u32) - ('0' as u32);
699                }
700                ' ' => {}
701                ')' => {
702                    self.iter.put_back(ic);
703                    break;
704                }
705                _ => {
706                    return Err(error_span(
707                        "Invalid unicode digit",
708                        self.iter.current.0..self.iter.current.0 + 1,
709                    ))
710                }
711            }
712        }
713        char::from_u32(result)
714            .ok_or_else(|| error_span("Invalid unicode", start..self.iter.current.0 + 1))
715    }
716
717    fn macro_sequence(&mut self) -> Result<Vec<u16>> {
718        let mut seq = Vec::new();
719        loop {
720            let range = self.read_sequence();
721            if range.is_empty() {
722                break;
723            }
724            let name = self.name(&range);
725            if let Some(code) = if name.len() > 1 {
726                keycodes::key_code(name)
727            } else {
728                None
729            } {
730                seq.push(code);
731            } else if keycodes::action_code(name).is_some() && self.iter.current.1 == '(' {
732                seq.push(self.read_action(range)?);
733            } else {
734                let (modifiers, keycode) = name.rsplit_once('-').unwrap_or(("", name));
735                let mod_mac = if !modifiers.is_empty()
736                    && keycodes::modifiers_to_bit_map(modifiers).is_some()
737                {
738                    keycodes::key_code(keycode).is_some()
739                } else {
740                    false
741                };
742                if mod_mac {
743                    seq.push(self.parse_macro(range)?);
744                } else {
745                    for c in name.chars() {
746                        let u = unshifted_char_code(c);
747                        if u != c {
748                            seq.push(
749                                key_range::MACROS_MIN
750                                    + self.add_macro(Macro::Modifier {
751                                        keycode: keycodes::char_to_code(u),
752                                        modifiers: keycodes::SHIFT_MOD,
753                                    }),
754                            );
755                        } else {
756                            let code = keycodes::char_to_code(c);
757                            if code != 0 {
758                                seq.push(code)
759                            } else {
760                                let mac = Macro::Tap(self.config.unicode_to_seq(c));
761                                seq.push(key_range::MACROS_MIN + self.add_macro(mac));
762                            }
763                        }
764                    }
765                }
766            }
767        }
768        Ok(seq)
769    }
770
771    fn get_macro(&self, code: u16) -> Option<&Macro> {
772        if matches!(code, key_range::MACROS_MIN..=key_range::MACROS_MAX) {
773            self.config
774                .macros
775                .get((code - key_range::MACROS_MIN) as usize)
776        } else {
777            None
778        }
779    }
780
781    fn add_macro(&mut self, mac: Macro) -> u16 {
782        let bin = mac.serialize();
783        if let Some(id) = self.config.macros_names.get(&bin) {
784            return *id;
785        }
786        let id = self.config.macros.len() as u16;
787
788        self.config.macros.push(mac);
789        self.config.macros_names.insert(bin, id);
790        id
791    }
792
793    fn get_layer_index(&mut self, name_range: NameRange) -> Result<u16> {
794        let name = &self.config.source[name_range.start..name_range.end];
795        if let Some(index) = self.config.get_layer_index(name) {
796            Ok(index)
797        } else {
798            Err(error_span(
799                format!("Unknown layer name {}", name),
800                name_range,
801            ))
802        }
803    }
804
805    fn parse_layer_code(&mut self, base_code: u16) -> Result<u16> {
806        self.mark_start();
807        if let Some(start) = self.next_non_ws() {
808            self.mark_idx = start.0;
809            if let Some(end) = self.iter.find(|c| c == ')' || c.is_whitespace()) {
810                let end_mark = self.iter.current.0 - 1;
811                if end.1 == ')'
812                    || self
813                        .next_non_ws()
814                        .and_then(|c| if c.1 == '(' { Some(c) } else { None })
815                        .is_some()
816                {
817                    return Ok(base_code + self.get_layer_index(start.0..end.0)?);
818                }
819                self.iter.current.0 = end_mark;
820            }
821        }
822        Err(self.error("Invalid layer(...) action"))
823    }
824
825    fn parse_assignment(&mut self) -> Result<Option<(NameRange, NameRange)>> {
826        if let Some(left) = self.read_word()? {
827            if self.match_char('=') {
828                if let Some(right) = self.next_assignment_value() {
829                    return Ok(Some((left, right)));
830                } else {
831                    return Err(self.error("Missing RHS"));
832                }
833            } else {
834                return Err(self.error("Missing ="));
835            }
836        }
837        Ok(None)
838    }
839
840    fn next_assignment_value(&mut self) -> Option<NameRange> {
841        let start = self.iter.find(|c| c == '\n' || !c.is_whitespace())?;
842        self.mark_start();
843        if start.1 == '\n' {
844            return None;
845        }
846        if let Some(parens) = match_paren(start.1) {
847            match self.iter.find_close_paren(parens) {
848                Some(end) => Some(start.0..end.0),
849                None => Some(start.0..self.iter.current.0),
850            }
851        } else {
852            match self.iter.find(invalid_seq_char) {
853                Some(end) => {
854                    self.iter.put_back(end);
855                    Some(start.0..end.0)
856                }
857                None => Some(start.0..self.iter.current.0),
858            }
859        }
860    }
861
862    fn mark_start(&mut self) {
863        self.mark_idx = self.iter.current.0;
864    }
865
866    fn error(&self, message: impl Into<String>) -> ConfigError {
867        ConfigError::new(message.into(), self.mark_idx..self.iter.current.0)
868    }
869
870    fn read_word(&mut self) -> Result<Option<NameRange>> {
871        match self.iter.find(|c| c == '\n' || !c.is_whitespace()) {
872            None => Ok(None),
873            Some(start) => {
874                self.mark_start();
875                if start.1 == '\n' {
876                    return Ok(None);
877                }
878                match self.iter.find(|c| c.is_whitespace()) {
879                    Some(end) => {
880                        if end.1 == '\n' {
881                            self.iter.put_back(end);
882                        }
883                        Ok(Some(start.0..end.0))
884                    }
885                    None => Err(self.error("Expected word")),
886                }
887            }
888        }
889    }
890
891    fn match_char(&mut self, c: char) -> bool {
892        match self.next_non_ws() {
893            None => false,
894            Some(start) => start.1 == c,
895        }
896    }
897
898    fn build_config(self) -> KeyboardConfig<'source> {
899        self.config
900    }
901
902    fn skip_whitespace(&mut self) -> Option<IndexChar> {
903        self.next_non_ws().inspect(|&item| {
904            self.iter.put_back(item);
905        })
906    }
907
908    #[inline]
909    fn next_non_ws(&mut self) -> Option<IndexChar> {
910        self.iter.find(non_ws_char)
911    }
912
913    fn assert_no_suffix(&self, tag_end: usize, end: usize) -> Result<()> {
914        if tag_end == end {
915            Ok(())
916        } else {
917            Err(ConfigError::new(
918                "suffix not allowed here".into(),
919                tag_end..end,
920            ))
921        }
922    }
923}
924
925fn match_paren(start: char) -> Option<(char, char)> {
926    Some(match start {
927        '(' => ('(', ')'),
928        '[' => ('[', ']'),
929        '{' => ('{', '}'),
930        _ => return None,
931    })
932}
933
934const DEFAULT_LAYERS: [(&str, u8); 6] = [
935    ("control", 1),
936    ("shift", 2),
937    ("alt", 4),
938    ("gui", 8),
939    ("altgr", 0x40),
940    ("main", 0),
941];
942
943fn data_to_usize(x: u16) -> usize {
944    u16::from_le(x) as usize
945}
946
947impl<'source> KeyboardConfig<'source> {
948    fn new(source: &'source str) -> Self {
949        let mut layers: HashMap<String, ConfigLayer> = Default::default();
950        for (i, (name, code)) in DEFAULT_LAYERS.into_iter().enumerate() {
951            layers.insert(name.into(), ConfigLayer::new(i as u16, code));
952        }
953
954        Self {
955            source,
956            global_map: Default::default(),
957            temp_map: Default::default(),
958            firmware_map: Default::default(),
959            matrix_map: Default::default(),
960            layers,
961            macros_names: Default::default(),
962            macros: Default::default(),
963            next_layer: DEFAULT_LAYERS.len() as u16,
964            row_count: 0,
965            col_count: 0,
966        }
967    }
968
969    pub fn deserialize(data: &[u16]) -> Self {
970        assert!(data.len() > 14);
971        assert_eq!(data[0], PROTOCOL_VERSION);
972
973        let mut config = Self::new("");
974
975        config.row_count = (u16::from_le(data[1]) >> 8) as u8;
976        config.col_count = (u16::from_le(data[1]) & 0xff) as u8;
977        let layer_count = (u16::from_le(data[2]) & 0xff) as usize;
978        // TODO let macros_count = u16::from_le(data[3]) as usize;
979        let globals_count = u16::from_le(data[4]) as usize;
980
981        config.deserialize_globals(&mut data[5..5 + globals_count].iter().copied());
982
983        let data = &data[5 + globals_count..]; // TODO read globals
984
985        for (i, (name, _)) in DEFAULT_LAYERS.into_iter().enumerate() {
986            let layer = config.layers.get_mut(name).unwrap();
987            layer.set_binary(
988                &data[data_to_usize(data[i])..data_to_usize(data[1 + i])],
989                config.row_count as usize,
990                config.col_count as usize,
991            );
992        }
993
994        for i in DEFAULT_LAYERS.len()..layer_count {
995            let name = format!("layer{}", i);
996            config.new_layer(name.as_str(), 0);
997            let layer = config.layers.get_mut(name.as_str()).unwrap();
998            layer.set_binary(
999                &data[data_to_usize(data[i])..data_to_usize(data[1 + i])],
1000                config.row_count as usize,
1001                config.col_count as usize,
1002            );
1003        }
1004
1005        // TODO read in macros
1006
1007        config
1008    }
1009
1010    pub fn serialize(&self) -> Vec<u16> {
1011        let layer_count = self.layers.len();
1012        let macros_count = self.macros.len();
1013
1014        let globals = self.serialize_globals();
1015
1016        let layer_base = 5 + globals.len();
1017        let mut out = vec![0; 1 + layer_count + macros_count + layer_base];
1018
1019        out[0] = PROTOCOL_VERSION.to_le();
1020        out[1] = ((self.col_count as u16) | ((self.row_count as u16) << 8)).to_le();
1021        out[2] = (layer_count as u16).to_le();
1022        out[3] = (macros_count as u16).to_le();
1023        out[4] = (globals.len() as u16).to_le();
1024
1025        out[5..layer_base].copy_from_slice(globals.as_slice());
1026
1027        let mut layers = self.layers.values().collect::<Vec<_>>();
1028        layers.sort_by(|a, b| Ord::cmp(&a.index, &b.index));
1029        for (i, mut l) in layers
1030            .iter()
1031            .map(|l| l.serialize(self.row_count as usize, self.col_count as usize))
1032            .enumerate()
1033        {
1034            out[layer_base + i] = ((out.len() - layer_base) as u16).to_le();
1035            out.append(&mut l);
1036        }
1037        let macro_base = layer_base + layer_count;
1038
1039        for (i, mut m) in self.macros.iter().map(|m| m.serialize()).enumerate() {
1040            out[macro_base + i] = ((out.len() - layer_base) as u16).to_le();
1041            out.append(&mut m);
1042        }
1043
1044        out[macro_base + macros_count] = ((out.len() - layer_base) as u16).to_le();
1045
1046        out
1047    }
1048
1049    pub fn deserialize_globals(&mut self, data: &mut impl Iterator<Item = u16>) {
1050        while let Some(gp) = GlobalProp::deserialize(data) {
1051            if let Some(name) = gp.default_name() {
1052                self.global_map.insert(name, gp);
1053            }
1054        }
1055    }
1056
1057    pub fn serialize_globals(&self) -> Vec<u16> {
1058        let mut out = self.global_map.values().collect::<Vec<_>>();
1059        out.sort_by(|a, b| Ord::cmp(&a.index, &b.index));
1060        out.into_iter().flat_map(|v| v.serialize()).collect()
1061    }
1062
1063    fn name(&self, name_range: &NameRange) -> &'source str {
1064        let start = if name_range.len() > 1 && self.source[name_range.start..].starts_with('\\') {
1065            name_range.start + 1
1066        } else {
1067            name_range.start
1068        };
1069        &self.source[start..name_range.end]
1070    }
1071
1072    fn unicode_to_seq(&mut self, uc: char) -> Vec<u16> {
1073        let uc = uc as u32;
1074
1075        let mut seq = vec![*self.temp_map.get("unicode_prefix").unwrap_or(&0)];
1076
1077        for i in 0..7 {
1078            let i = (6 - i) << 2;
1079            let d = ((uc >> i) & 0xf) as u16;
1080
1081            let kc = match d {
1082                0 if seq.len() == 1 => continue,
1083                0 => BASIC_0,
1084                10..=15 => BASIC_A + d - 10,
1085                _ => BASIC_1 + d - 1,
1086            };
1087            seq.push(kc);
1088        }
1089
1090        seq.push(*self.temp_map.get("unicode_suffix").unwrap_or(&0));
1091
1092        seq
1093    }
1094
1095    fn parse_duration(&mut self, value_range: &NameRange, max: u16) -> Result<u16> {
1096        if let Ok(n) = self.name(value_range).parse::<u16>() {
1097            if n <= max {
1098                return Ok(n);
1099            }
1100        }
1101        Err(error_span(
1102            format!("Invalid duration; only 0 to {} milliseconds are valid", max),
1103            value_range.start..value_range.end,
1104        ))
1105    }
1106
1107    pub fn key_position(&self, name: &str) -> Option<u16> {
1108        if let Some(name) = name.strip_prefix("0x") {
1109            if let Ok(pos) = u16::from_str_radix(name, 16) {
1110                return Some(match name.len() {
1111                    2 => (pos & 0xf0) << 4 | (pos & 0xf),
1112                    3..=4 => pos,
1113                    _ => return None,
1114                });
1115            }
1116        }
1117        None
1118    }
1119
1120    pub fn global(&self, name: &str) -> Option<GlobalProp> {
1121        self.global_map.get(name).copied()
1122    }
1123
1124    fn take_global(&mut self, name: &'source str) -> Result<GlobalProp> {
1125        match self.global_map.remove(name) {
1126            Some(g) => Ok(g),
1127            None => GlobalProp::new_default(name).map_err(|e| ConfigError::from(e.as_str())),
1128        }
1129    }
1130
1131    fn insert_global(&mut self, name: &'source str, value: GlobalProp) {
1132        self.global_map.insert(name, value);
1133    }
1134
1135    fn assign_aliases(&mut self, key: &str, value: &str) -> bool {
1136        if let Some(pos) = self.key_position(key) {
1137            self.assign_position_name(pos, value);
1138            return true;
1139        }
1140        if let Some(positions) = self.get_aliases(key) {
1141            let positions = positions.clone();
1142            for pos in positions {
1143                self.assign_position_name(pos, value);
1144            }
1145            return true;
1146        }
1147        false
1148    }
1149
1150    fn assign_position_name(&mut self, pos: u16, name: &str) {
1151        if let Some(code) = key_code(name) {
1152            let name = format!("{code:04X}");
1153            if let Some(v) = self.matrix_map.get_mut(name.as_str()) {
1154                v.push(pos);
1155            } else {
1156                self.matrix_map.insert(name, vec![pos]);
1157            }
1158        } else if let Some(v) = self.matrix_map.get_mut(name) {
1159            v.push(pos);
1160        } else {
1161            self.matrix_map.insert(name.into(), vec![pos]);
1162        }
1163    }
1164
1165    pub fn get_aliases(&self, name: &str) -> Option<&Vec<u16>> {
1166        if let Some(code) = key_code(name) {
1167            self.matrix_map.get(format!("{code:04X}").as_str())
1168        } else {
1169            self.matrix_map.get(name)
1170        }
1171    }
1172
1173    pub fn code_at(&self, name: &str, rowcol: u16) -> u16 {
1174        if let Some(layer) = self.layers.get(name) {
1175            return layer.code_at(rowcol);
1176        }
1177        0
1178    }
1179
1180    fn assign_one_layer_code(&mut self, name: &str, pos: u16, code: u16) {
1181        self.layers.get_mut(name).unwrap().set_code(pos, code);
1182    }
1183
1184    fn new_layer(&mut self, name: &str, code: u8) {
1185        self.layers
1186            .insert(name.into(), ConfigLayer::new(self.next_layer, code));
1187
1188        self.next_layer += 1;
1189    }
1190
1191    fn get_layer_index(&self, name: &str) -> Option<u16> {
1192        self.layers.get(name).map(|l| l.index)
1193    }
1194
1195    fn scan_layer_names(&mut self) -> Result<()> {
1196        #[derive(PartialEq)]
1197        enum State {
1198            Ready,
1199            Read(usize, usize),
1200            Search,
1201        }
1202        let mut in_comment = false;
1203        let mut escaped = false;
1204        let mut paren = 0;
1205        let mut parens = ('(', ')');
1206        let mut state = State::Ready;
1207        for (i, c) in self.source.char_indices() {
1208            match c {
1209                _ if escaped => {
1210                    escaped = false;
1211                }
1212                '\n' if paren == 0 => {
1213                    state = State::Ready;
1214                    in_comment = false;
1215                }
1216                _ if in_comment => {}
1217                '#' => {
1218                    in_comment = true;
1219                }
1220                '\\' => {
1221                    escaped = true;
1222                }
1223                _ if paren > 0 => {
1224                    if c == parens.0 {
1225                        paren += 1;
1226                    } else if c == parens.1 {
1227                        paren -= 1;
1228                    }
1229                }
1230                _ => match state {
1231                    State::Read(s, e) => match c {
1232                        ':' if s == e => {
1233                            state = State::Read(s, i);
1234                        }
1235                        ']' => {
1236                            self.ensure_section(s, e, i)?;
1237                            state = State::Search;
1238                        }
1239                        _ => {}
1240                    },
1241                    State::Ready => match c {
1242                        '[' => {
1243                            state = State::Read(i + 1, i + 1);
1244                        }
1245                        _ if c.is_whitespace() => {}
1246                        _ => {
1247                            state = State::Search;
1248                            if let Some(p) = match_paren(c) {
1249                                parens = p;
1250                                paren = 1;
1251                            }
1252                        }
1253                    },
1254                    State::Search => {}
1255                },
1256            }
1257        }
1258        Ok(())
1259    }
1260
1261    fn ensure_section(&mut self, s: usize, e: usize, i: usize) -> Result<()> {
1262        let (name, suffix) = if s == e {
1263            (&self.source[s..i], &self.source[s..e])
1264        } else {
1265            (&self.source[s..e], &self.source[e + 1..i])
1266        };
1267
1268        match name {
1269            "matrix" => {
1270                let mut iter = suffix.split_terminator('x');
1271                if let (Some(row_count), Some(col_count)) = (iter.next(), iter.next()) {
1272                    if let (Ok(row_count), Ok(col_count)) =
1273                        (row_count.parse::<u8>(), col_count.parse::<u8>())
1274                    {
1275                        self.row_count = row_count;
1276                        self.col_count = col_count;
1277                        return Ok(());
1278                    }
1279                }
1280
1281                return Err(ConfigError::new(
1282                    "expected [matrix:rxc] where r and c are row column size".into(),
1283                    s..i,
1284                ));
1285            }
1286            "aliases" => {}
1287            _ => {
1288                let code = keycodes::modifiers_to_bit_map(suffix).ok_or_else(|| {
1289                    ConfigError::new(format!("Invalid layer suffix '{}'", suffix), e + 1..i)
1290                })?;
1291
1292                if let Some(layer) = self.layers.get(name) {
1293                    if layer.suffix != code && code != 0 {
1294                        return Err(ConfigError::new(
1295                            format!(
1296                                "layer suffix may not be changed; {} != {}",
1297                                keycodes::modifiers_to_string(layer.suffix),
1298                                suffix,
1299                            ),
1300                            s..i,
1301                        ));
1302                    }
1303                } else {
1304                    self.new_layer(name, code);
1305                }
1306            }
1307        }
1308
1309        Ok(())
1310    }
1311
1312    pub fn firmware_get(&self, arg: &str) -> Option<&str> {
1313        self.firmware_map
1314            .get(arg)
1315            .or_else(|| {
1316                let arg = arg.to_uppercase();
1317                self.firmware_map.get(arg.as_str())
1318            })
1319            .copied()
1320    }
1321}
1322
1323impl ConfigLayer {
1324    fn new(index: u16, suffix: u8) -> Self {
1325        Self {
1326            codes: Default::default(),
1327            index,
1328            suffix,
1329        }
1330    }
1331
1332    fn set_binary(&mut self, data: &[u16], row_count: usize, col_count: usize) {
1333        self.suffix = u16::from_le(data[0]) as u8;
1334
1335        let data = &data[1..];
1336        if row_count * col_count == data.len() {
1337            for row in 0..row_count {
1338                for col in 0..col_count {
1339                    self.codes.insert(
1340                        ((row << 8) + col) as u16,
1341                        u16::from_le(data[row * col_count + col]),
1342                    );
1343                }
1344            }
1345        } else {
1346            let mut k = 0;
1347            for (i, v) in data.iter().enumerate() {
1348                let v = u16::from_le(*v);
1349                if i & 1 == 0 {
1350                    k = v;
1351                } else {
1352                    self.codes.insert(k, v);
1353                }
1354            }
1355        }
1356    }
1357
1358    fn serialize(&self, row_count: usize, col_count: usize) -> Vec<u16> {
1359        let mut bin = vec![0];
1360        bin[0] = (self.suffix as u16).to_le();
1361        if self.codes.len() * 3 > row_count * col_count {
1362            // normal array
1363            bin.resize(1 + row_count * col_count, 0);
1364            for (k, v) in self.codes.iter() {
1365                let i = (k >> 8) as usize * col_count + (k & 0xff) as usize;
1366                let _ = (k, v, i, k >> 8, (k & 0xff));
1367                bin[i + 1] = v.to_le();
1368            }
1369        } else {
1370            bin.resize(1 + self.codes.len() * 2, 0);
1371            let mut codes = self.codes.iter().collect::<Vec<_>>();
1372            codes.sort_by_key(|k| k.0);
1373            for (i, (k, v)) in codes.into_iter().enumerate() {
1374                bin[i * 2 + 1] = k.to_le();
1375                bin[i * 2 + 2] = v.to_le();
1376            }
1377            // sparse array
1378        }
1379        bin
1380    }
1381
1382    pub fn code_at(&self, pos: u16) -> u16 {
1383        *self.codes.get(&pos).unwrap_or(&0)
1384    }
1385
1386    fn set_code(&mut self, pos: u16, code: u16) {
1387        self.codes.insert(pos, code);
1388    }
1389}
1390
1391fn error_span(message: impl Into<String>, range: NameRange) -> ConfigError {
1392    ConfigError::new(message.into(), range)
1393}
1394
1395pub fn compile(source: &str) -> Result<KeyboardConfig> {
1396    let mut parser = Parser::new(source);
1397
1398    parser.parse_sections()?;
1399    Ok(parser.build_config())
1400}
1401
1402#[cfg(test)]
1403#[path = "compiler_test.rs"]
1404mod test;