lexigram_core/lib.rs
1// Copyright (c) 2025 Redglyph (@gmail.com). All Rights Reserved.
2
3pub mod alt;
4pub mod segmap;
5pub mod char_reader;
6pub mod fixed_sym_table;
7pub mod log;
8pub mod lexer;
9pub mod parser;
10
11/// ID of a lexer token
12pub type TokenId = u16;
13/// ID of a nonterminal
14pub type VarId = u16;
15/// ID of a rule alternative. We use the same type as [VarId] because they're very similar quantities.
16pub type AltId = VarId;
17
18pub trait CollectJoin {
19 fn join(&mut self, separator: &str) -> String
20 where Self: Iterator,
21 <Self as Iterator>::Item: ToString
22 {
23 self.map(|x| x.to_string()).collect::<Vec<_>>().join(separator)
24 }
25
26 fn to_vec(self) -> Vec<<Self as Iterator>::Item>
27 where Self: Iterator + Sized
28 {
29 self.collect::<Vec<_>>()
30 }
31}
32
33impl<I: Iterator> CollectJoin for I {}
34
35// ---------------------------------------------------------------------------------------------
36// Macros
37
38pub mod macros {
39 /// Generates an `OpCode` instance.
40 ///
41 /// # Examples
42 /// ```
43 /// # use lexigram_core::TokenId;
44 /// # use lexigram_core::opcode;
45 /// # use lexigram_core::VarId;
46 /// # use lexigram_core::parser::OpCode;
47 /// assert_eq!(opcode!(e), OpCode::Empty);
48 /// assert_eq!(opcode!(t 2), OpCode::T(2 as TokenId));
49 /// assert_eq!(opcode!(nt 3), OpCode::NT(3));
50 /// assert_eq!(opcode!(loop 2), OpCode::Loop(2));
51 /// assert_eq!(opcode!(exit 1), OpCode::Exit(1));
52 /// assert_eq!(opcode!(nt 3), OpCode::NT(3));
53 /// assert_eq!(opcode!(loop 2), OpCode::Loop(2));
54 /// assert_eq!(opcode!(exit 1), OpCode::Exit(1));
55 /// assert_eq!(opcode!(end), OpCode::End);
56 #[macro_export]
57 macro_rules! opcode {
58 (e) => { $crate::parser::OpCode::Empty };
59 (t $id:expr) => { $crate::parser::OpCode::T($id as $crate::TokenId) };
60 (nt $id:expr) => { $crate::parser::OpCode::NT($id as $crate::VarId) };
61 (loop $id:expr) => { $crate::parser::OpCode::Loop($id as $crate::VarId) };
62 (exit $id:expr) => { $crate::parser::OpCode::Exit($id as $crate::VarId) };
63 (nt $id:expr) => { $crate::parser::OpCode::NT($id as $crate::VarId, 0) };
64 (loop $id:expr) => { $crate::parser::OpCode::Loop($id as $crate::VarId, 0) };
65 (exit $id:expr) => { $crate::parser::OpCode::Exit($id as $crate::VarId, 0) };
66 (end) => { $crate::parser::OpCode::End };
67 }
68
69 /// Generates an opcode strip. A strip is made up of `OpCode` items separated by a comma.
70 ///
71 /// # Example
72 /// ```
73 /// # use lexigram_core::{TokenId, VarId, strip, opcode};
74 /// # use lexigram_core::alt::Alternative;
75 /// # use lexigram_core::parser::{OpCode, Symbol};
76 /// assert_eq!(strip!(nt 1, loop 5, t 3, e), vec![opcode!(nt 1), opcode!(loop 5), opcode!(t 3), opcode!(e)]);
77 /// ```
78 #[macro_export]
79 macro_rules! strip {
80 () => { std::vec![] };
81 ($($a:ident $($b:expr)?,)+) => { strip![$($a $($b)?),+] };
82 ($($a:ident $($b:expr)?),*) => { std::vec![$($crate::opcode!($a $($b)?)),*] };
83 }
84}