logic_tracer/tokens/mod.rs
1//! This module defines the types of tokens that can be recognized and validated by the
2//! [`Lexer`](crate::components::lexer) and subsequently utilized by the [`Parser`](crate::components::parser).
3//!
4//! It provides a foundational framework for building the lexical components of a language,
5//! including primitive and potentially complex token types.
6//!
7//! ## Usage
8//!
9//! Token types are typically constructed via parsing strings and are extensively used throughout the
10//! lexer and parser components to facilitate language processing.
11
12// Consider re-enabling and documenting the `variables` module if relevant for future extensions.
13// pub mod variables; // Defines variable-related tokens like identifiers.
14
15pub mod numbers; // Contains definitions for numeric types.
16pub mod operators; // Contains definitions for various operators.
17pub mod variables; // Contains definitions for variable-related tokens.
18
19pub use numbers::*;
20pub use operators::*;
21pub use variables::*; // variables generator (constants, alphabets, hiragana, etc...)
22
23use std::fmt::Debug;
24
25/// Represents a generic token within the language processing system.
26///
27/// All token types must implement this trait to ensure they can be debugged and
28/// dynamically handled via polymorphism. Tokens are generally created from strings and
29/// can be represented back as strings for debugging and logging purposes.
30// * IN COMPUTER SCIENCE.
31// * A token is a string of one or more characters, which are treated as a single unit by a program.
32// * Tokens are the smallest elements of a program, and they are classified by the compiler according to their functionality.
33pub trait Token: Debug {
34 /// Constructs an instance of a token from a string, if possible.
35 fn from_str<S: Into<String>>(string: S) -> Option<Self>
36 where
37 Self: Sized;
38
39 /// Returns a string representation of the token, typically used for debugging.
40 fn to_string(&self) -> String {
41 let mut result = std::any::type_name::<Self>()
42 .split("::")
43 .collect::<Vec<&str>>();
44 result.reverse();
45
46 let mut token_type = result.get(0).unwrap();
47 let token_type = token_type
48 .chars()
49 .next()
50 .unwrap()
51 .to_uppercase()
52 .collect::<String>()
53 + &token_type[1..];
54
55 // format!("{:>12} :: {self:?}", token_type) // no additional formatting...
56 let token_type = format!("\x1B[3m{}\x1B[0m", token_type); // italic
57 let token_type = format!("\x1B[1m{}\x1B[0m", token_type); // bold
58
59 format!("{token_type:>28} :: {self:?}")
60 // let token_type = format!("\x1B[36m{}\x1B[0m", token_type); // cyan
61 // let token_type = format!("\x1B[32m{}\x1B[0m", token_type); // green
62 // format!("{:>36} :: {self:?}", token_type) // (format with spacing according to the token_type length...)
63 // todo: make this a bit more dynamic...
64 }
65
66}
67
68#[macro_export]
69/// Macro to implement specific token types for a given trait.
70///
71/// This macro simplifies the creation of token structures that implement a common trait,
72/// allowing for polymorphic handling of different token types within the parsing logic.
73macro_rules! impl_enum_token {
74 ($token_type:ident; $trait_name:ident; //
75 $(
76 $name:ident (
77 $(
78 $variant:ident => ($($str:expr),+)
79 $(,)?
80 )+
81 )
82 ),+ $(,)?
83 ) => {
84 crate::impl_token_trait!($token_type; $trait_name; $($name),+);
85 $(
86 #[derive(Debug, Clone, PartialEq)]
87 pub enum $name { $($variant,)+ }
88
89 impl Token for $name {
90 fn from_str<S: Into<String>>(string: S) -> Option<Self> {
91 match string.into().as_str() {
92 $($($str)|+ => Some($name::$variant),)+
93 _ => None
94 }
95 }
96 }
97
98 impl $trait_name for $name {} //
99 )+
100 };
101}
102
103#[macro_export]
104/// Macro to implement specific token types for a given trait.
105/// Implements the 'from' method for the token type to create a Box<dyn Trait> from a string.
106///
107/// This macro requires that al token types implement the specified trait and provides a `from_str` method to parse a string into a token.
108macro_rules! impl_token_trait {
109 ($token_type:ident; $trait_name:ident;
110 $(
111 $name:ident // Name of the token type
112 ),+ $(,)? // Supports multiple token types
113 ) => {
114 impl $token_type {
115 /// Attempts to create a boxed token from a string if it matches any of the specified types.
116 pub fn from<S: Into<String> + Copy>(string: S) -> Option<Box<dyn $trait_name>> {
117 $(if let Some(value) = $name::from_str(string) {
118 Some(Box::new(value)); // Create some box with the token type
119 })+
120 None // Return None if no types match
121 }
122 }
123 };
124}